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
277 /* The instruction size can be either 4 byte (word instruction) or 8 bytes
278 (prefix instruction) starting with ISA 3.1 */
279 #define WORD_INST_SIZE 4
280 #define PREFIX_INST_SIZE 8
282 /*------------------------------------------------------------*/
283 /*--- Debugging output ---*/
284 /*------------------------------------------------------------*/
286 /* Pre DIP macro for prefix instruction printing. */
287 #define pDIP(flag,format, args...) \
288 if (vex_traceflags & VEX_TRACE_FE){ \
289 if (flag) {vex_printf("p"); vex_printf(format, ## args);} \
290 else {vex_printf(format, ## args); vex_printf("\n");}}
292 /* Post DIP macro to print additional args for prefix instruction printing. */
293 #define DIPp(flag,format, args...) \
294 if (vex_traceflags & VEX_TRACE_FE) { \
295 if (flag) {vex_printf(format, ## args); vex_printf("\n");}}
297 /* Post DIP macro with no additional args for prefix instruction printing. */
299 if (vex_traceflags & VEX_TRACE_FE) {if (flag) vex_printf("\n");}
301 #define DIP(format, args...) \
302 if (vex_traceflags & VEX_TRACE_FE) \
303 vex_printf(format, ## args)
305 #define DIS(buf, format, args...) \
306 if (vex_traceflags & VEX_TRACE_FE) \
307 vex_sprintf(buf, format, ## args)
310 /*------------------------------------------------------------*/
311 /*--- Offsets of various parts of the ppc32/64 guest state ---*/
312 /*------------------------------------------------------------*/
314 #define offsetofPPCGuestState(_x) \
315 (mode64 ? offsetof(VexGuestPPC64State, _x) : \
316 offsetof(VexGuestPPC32State, _x))
318 #define OFFB_CIA offsetofPPCGuestState(guest_CIA)
319 #define OFFB_IP_AT_SYSCALL offsetofPPCGuestState(guest_IP_AT_SYSCALL)
320 #define OFFB_SPRG3_RO offsetofPPCGuestState(guest_SPRG3_RO)
321 #define OFFB_LR offsetofPPCGuestState(guest_LR)
322 #define OFFB_CTR offsetofPPCGuestState(guest_CTR)
323 #define OFFB_XER_SO offsetofPPCGuestState(guest_XER_SO)
324 #define OFFB_XER_OV offsetofPPCGuestState(guest_XER_OV)
325 #define OFFB_XER_OV32 offsetofPPCGuestState(guest_XER_OV32)
326 #define OFFB_XER_CA offsetofPPCGuestState(guest_XER_CA)
327 #define OFFB_XER_CA32 offsetofPPCGuestState(guest_XER_CA32)
328 #define OFFB_XER_BC offsetofPPCGuestState(guest_XER_BC)
329 #define OFFB_FPROUND offsetofPPCGuestState(guest_FPROUND)
330 #define OFFB_DFPROUND offsetofPPCGuestState(guest_DFPROUND)
331 #define OFFB_C_FPCC offsetofPPCGuestState(guest_C_FPCC)
332 #define OFFB_VRSAVE offsetofPPCGuestState(guest_VRSAVE)
333 #define OFFB_VSCR offsetofPPCGuestState(guest_VSCR)
334 #define OFFB_EMNOTE offsetofPPCGuestState(guest_EMNOTE)
335 #define OFFB_CMSTART offsetofPPCGuestState(guest_CMSTART)
336 #define OFFB_CMLEN offsetofPPCGuestState(guest_CMLEN)
337 #define OFFB_NRADDR offsetofPPCGuestState(guest_NRADDR)
338 #define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2)
339 #define OFFB_TFHAR offsetofPPCGuestState(guest_TFHAR)
340 #define OFFB_TEXASR offsetofPPCGuestState(guest_TEXASR)
341 #define OFFB_TEXASRU offsetofPPCGuestState(guest_TEXASRU)
342 #define OFFB_TFIAR offsetofPPCGuestState(guest_TFIAR)
343 #define OFFB_PPR offsetofPPCGuestState(guest_PPR)
344 #define OFFB_PSPB offsetofPPCGuestState(guest_PSPB)
345 #define OFFB_DSCR offsetofPPCGuestState(guest_DSCR)
346 /* Note the offset for the various ACC entries are calculated based on
347 the OFFB_ACC_0_r0 value. */
348 #define OFFB_ACC_0_r0 offsetofPPCGuestState(guest_ACC_0_r0)
349 #define OFFB_syscall_flag offsetofPPCGuestState(guest_syscall_flag)
352 /*------------------------------------------------------------*/
353 /*--- Extract instruction fields --- */
354 /*------------------------------------------------------------*/
356 /* Extract field from insn, given idx (zero = lsb) and field length */
357 #define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1))
359 /* Extract primary opcode, instr[31:26] */
360 static UChar
ifieldOPC( UInt instr
) {
361 return toUChar( IFIELD( instr
, 26, 6 ) );
364 /* Extract 11-bit secondary opcode, instr[10:0] */
365 static UInt
ifieldOPClo11 ( UInt instr
) {
366 return IFIELD( instr
, 0, 11 );
369 /* Extract 10-bit secondary opcode, instr[10:1] */
370 static UInt
ifieldOPClo10 ( UInt instr
) {
371 return IFIELD( instr
, 1, 10 );
374 /* Extract 9-bit secondary opcode, instr[9:1] */
375 static UInt
ifieldOPClo9 ( UInt instr
) {
376 return IFIELD( instr
, 1, 9 );
379 /* Extract 8-bit secondary opcode, instr[8:1] */
380 static UInt
ifieldOPClo8 ( UInt instr
) {
381 return IFIELD( instr
, 1, 8 );
384 /* Extract 4-bit secondary opcode, instr[5:1] */
385 static UInt
ifieldOPClo4 ( UInt instr
) {
386 return IFIELD( instr
, 0, 4 );
389 /* Extract 5-bit secondary opcode, instr[5:1] */
390 static UInt
ifieldOPClo5 ( UInt instr
) {
391 return IFIELD( instr
, 1, 5 );
394 /* Extract 2-bit secondary opcode, instr[1:0] */
395 static UInt
ifieldOPC0o2 ( UInt instr
) {
396 return IFIELD( instr
, 0, 2 );
399 /* Extract RD (destination register) field, instr[25:21] */
400 static UChar
ifieldRegDS( UInt instr
) {
401 return toUChar( IFIELD( instr
, 21, 5 ) );
404 /* Extract XTp (destination register) field, instr[25:22, 21] */
405 static UChar
ifieldRegXTp ( UInt instr
)
407 UChar TX
= toUChar (IFIELD (instr
, 21, 1));
408 UChar Tp
= toUChar (IFIELD (instr
, 22, 4));
409 /* XTp = 32 * TX + 2* Tp; Only even values of XTp can be encoded. */
410 return (TX
<< 5) | (Tp
<< 1);
413 /* Extract XT (destination register) field, instr[0,25:21] */
414 static UChar
ifieldRegXT ( UInt instr
)
416 UChar upper_bit
= toUChar (IFIELD (instr
, 0, 1));
417 UChar lower_bits
= toUChar (IFIELD (instr
, 21, 5));
418 return (upper_bit
<< 5) | lower_bits
;
421 /* Extract XS (store source register) field, instr[0,25:21] */
422 static inline UChar
ifieldRegXS ( UInt instr
)
424 return ifieldRegXT ( instr
);
427 /* Extract RA (1st source register) field, instr[20:16] */
428 static UChar
ifieldRegA ( UInt instr
) {
429 return toUChar( IFIELD( instr
, 16, 5 ) );
432 /* Extract XA (1st source register) field, instr[2,20:16] */
433 static UChar
ifieldRegXA ( UInt instr
)
435 UChar upper_bit
= toUChar (IFIELD (instr
, 2, 1));
436 UChar lower_bits
= toUChar (IFIELD (instr
, 16, 5));
437 return (upper_bit
<< 5) | lower_bits
;
440 /* Extract RB (2nd source register) field, instr[15:11] */
441 static UChar
ifieldRegB ( UInt instr
) {
442 return toUChar( IFIELD( instr
, 11, 5 ) );
445 /* Extract XB (2nd source register) field, instr[1,15:11] */
446 static UChar
ifieldRegXB ( UInt instr
)
448 UChar upper_bit
= toUChar (IFIELD (instr
, 1, 1));
449 UChar lower_bits
= toUChar (IFIELD (instr
, 11, 5));
450 return (upper_bit
<< 5) | lower_bits
;
453 /* Extract RC (3rd source register) field, instr[10:6] */
454 static UChar
ifieldRegC ( UInt instr
) {
455 return toUChar( IFIELD( instr
, 6, 5 ) );
458 /* Extract XC (3rd source register) field, instr[3,10:6] */
459 static UChar
ifieldRegXC ( UInt instr
)
461 UChar upper_bit
= toUChar (IFIELD (instr
, 3, 1));
462 UChar lower_bits
= toUChar (IFIELD (instr
, 6, 5));
463 return (upper_bit
<< 5) | lower_bits
;
466 /* Extract bit 10, instr[10] */
467 static UChar
ifieldBIT10 ( UInt instr
) {
468 return toUChar( IFIELD( instr
, 10, 1 ) );
471 /* Extract 2nd lowest bit, instr[1] */
472 static UChar
ifieldBIT1 ( UInt instr
) {
473 return toUChar( IFIELD( instr
, 1, 1 ) );
476 /* Extract lowest bit, instr[0] */
477 static UChar
ifieldBIT0 ( UInt instr
) {
478 return toUChar( instr
& 0x1 );
481 /* Extract unsigned bottom half, instr[15:0] */
482 static UInt
ifieldUIMM16 ( UInt instr
) {
483 return instr
& 0xFFFF;
486 /* Extract unsigned bottom 26 bits, instr[25:0] */
487 static UInt
ifieldUIMM26 ( UInt instr
) {
488 return instr
& 0x3FFFFFF;
491 /* Extract DM field, instr[9:8] */
492 static UChar
ifieldDM ( UInt instr
) {
493 return toUChar( IFIELD( instr
, 8, 2 ) );
496 /* Extract SHW field, instr[9:8] */
497 static inline UChar
ifieldSHW ( UInt instr
)
499 return ifieldDM ( instr
);
502 /* Extract AT field from theInstr 8LS:D form */
503 static UChar
ifieldAT ( UInt instr
) {
504 return toUChar( IFIELD( instr
, 23, 3 ) );
507 /*------------------------------------------------------------*/
508 /*--- Guest-state identifiers ---*/
509 /*------------------------------------------------------------*/
512 PPC_GST_CIA
, // Current Instruction Address
513 PPC_GST_LR
, // Link Register
514 PPC_GST_CTR
, // Count Register
515 PPC_GST_XER
, // Overflow, carry flags, byte count
516 PPC_GST_CR
, // Condition Register
517 PPC_GST_FPSCR
, // Floating Point Status/Control Register
518 PPC_GST_VRSAVE
, // Vector Save/Restore Register
519 PPC_GST_VSCR
, // Vector Status and Control Register
520 PPC_GST_EMWARN
, // Emulation warnings
521 PPC_GST_CMSTART
,// For icbi: start of area to invalidate
522 PPC_GST_CMLEN
, // For icbi: length of area to invalidate
523 PPC_GST_IP_AT_SYSCALL
, // the CIA of the most recently executed SC insn
524 PPC_GST_SPRG3_RO
, // SPRG3
525 PPC_GST_TFHAR
, // Transactional Failure Handler Address Register
526 PPC_GST_TFIAR
, // Transactional Failure Instruction Address Register
527 PPC_GST_TEXASR
, // Transactional EXception And Summary Register
528 PPC_GST_TEXASRU
, // Transactional EXception And Summary Register Upper
529 PPC_GST_PPR
, // Program Priority register
530 PPC_GST_PPR32
, // Upper 32-bits of Program Priority register
531 PPC_GST_PSPB
, /* Problem State Priority Boost register, Note, the
532 * register is initialized to a non-zero value. Currently
533 * Valgrind is not supporting the register value to
534 * automatically decrement. Could be added later if
537 PPC_GST_DSCR
, // Data Stream Control Register
538 PPC_GST_ACC_0_r0
, /* Accumulator register file. Eight accumulators each
539 * with four 128-bit registers.
575 #define MASK_FPSCR_RN 0x3ULL // Binary floating point rounding mode
576 #define MASK_FPSCR_DRN 0x700000000ULL // Decimal floating point rounding mode
577 #define MASK_FPSCR_C_FPCC 0x1F000ULL // Floating-Point Condition code FPCC
579 #define MASK_VSCR_VALID 0x00010001
582 /*------------------------------------------------------------*/
583 /*--- Misc Helpers ---*/
584 /*------------------------------------------------------------*/
586 static void Get_lmd( IRTemp
* lmd
, IRExpr
* gfield_0_4
);
588 /* Generate mask with 1's from 'begin' through 'end',
589 wrapping if begin > end.
590 begin->end works from right to left, 0=lsb
592 static UInt
MASK32( UInt begin
, UInt end
)
597 m1
= ((UInt
)(-1)) << begin
;
598 m2
= ((UInt
)(-1)) << end
<< 1;
600 if (begin
> end
) mask
= ~mask
; // wrap mask
604 static ULong
MASK64( UInt begin
, UInt end
)
609 m1
= ((ULong
)(-1)) << begin
;
610 m2
= ((ULong
)(-1)) << end
<< 1;
612 if (begin
> end
) mask
= ~mask
; // wrap mask
616 static Addr64
nextInsnAddr( void )
618 /* Note in the case of a prefix instruction, delta has already been
619 incremented by WORD_INST_SIZE to move past the prefix part of the
620 instruction. So only need to increment by WORD_INST_SIZE to get to
621 the start of the next instruction. */
622 return guest_CIA_curr_instr
+ WORD_INST_SIZE
;
626 /*------------------------------------------------------------*/
627 /*--- Helper bits and pieces for deconstructing the ---*/
628 /*--- ppc32/64 insn stream. ---*/
629 /*------------------------------------------------------------*/
631 /* Add a statement to the list held by "irsb". */
632 static void stmt ( IRStmt
* st
)
634 addStmtToIRSB( irsb
, st
);
637 /* Generate a new temporary of the given type. */
638 static IRTemp
newTemp ( IRType ty
)
640 vassert(isPlausibleIRType(ty
));
641 return newIRTemp( irsb
->tyenv
, ty
);
644 /* Various simple conversions */
646 static UChar
extend_s_5to8 ( UChar x
)
648 return toUChar((((Int
)x
) << 27) >> 27);
651 static UInt
extend_s_8to32( UChar x
)
653 return (UInt
)((((Int
)x
) << 24) >> 24);
656 static UInt
extend_s_16to32 ( UInt x
)
658 return (UInt
)((((Int
)x
) << 16) >> 16);
661 static ULong
extend_s_16to64 ( UInt x
)
663 return (ULong
)((((Long
)x
) << 48) >> 48);
666 static ULong
extend_s_26to64 ( UInt x
)
668 return (ULong
)((((Long
)x
) << 38) >> 38);
671 static ULong
extend_s_32to64 ( UInt x
)
673 return (ULong
)((((Long
)x
) << 32) >> 32);
676 /* Do a proper-endian load of a 32-bit word, regardless of the endianness
677 of the underlying host. */
678 static UInt
getUIntPPCendianly ( const UChar
* p
)
681 if (host_endness
== VexEndnessBE
) {
696 /*------------------------------------------------------------*/
697 /*--- Helpers for constructing IR. ---*/
698 /*------------------------------------------------------------*/
700 static void assign ( IRTemp dst
, IRExpr
* e
)
702 stmt( IRStmt_WrTmp(dst
, e
) );
705 /* This generates a normal (non store-conditional) store. */
706 static void store ( IRExpr
* addr
, IRExpr
* data
)
708 IRType tyA
= typeOfIRExpr(irsb
->tyenv
, addr
);
709 vassert(tyA
== Ity_I32
|| tyA
== Ity_I64
);
711 if (host_endness
== VexEndnessBE
)
712 stmt( IRStmt_Store(Iend_BE
, addr
, data
) );
714 stmt( IRStmt_Store(Iend_LE
, addr
, data
) );
717 static IRExpr
* unop ( IROp op
, IRExpr
* a
)
719 return IRExpr_Unop(op
, a
);
722 static IRExpr
* binop ( IROp op
, IRExpr
* a1
, IRExpr
* a2
)
724 return IRExpr_Binop(op
, a1
, a2
);
727 static IRExpr
* triop ( IROp op
, IRExpr
* a1
, IRExpr
* a2
, IRExpr
* a3
)
729 return IRExpr_Triop(op
, a1
, a2
, a3
);
732 static IRExpr
* qop ( IROp op
, IRExpr
* a1
, IRExpr
* a2
,
733 IRExpr
* a3
, IRExpr
* a4
)
735 return IRExpr_Qop(op
, a1
, a2
, a3
, a4
);
738 static IRExpr
* mkexpr ( IRTemp tmp
)
740 return IRExpr_RdTmp(tmp
);
743 #define mkU1(_n) IRExpr_Const(IRConst_U1(_n))
745 static IRExpr
* mkU8 ( UChar i
)
747 return IRExpr_Const(IRConst_U8(i
));
750 static IRExpr
* mkU16 ( UInt i
)
752 return IRExpr_Const(IRConst_U16(i
));
755 static IRExpr
* mkU32 ( UInt i
)
757 return IRExpr_Const(IRConst_U32(i
));
760 static IRExpr
* mkU64 ( ULong i
)
762 return IRExpr_Const(IRConst_U64(i
));
765 static IRExpr
* mkV128 ( UShort i
)
767 vassert(i
== 0 || i
== 0xffff);
768 return IRExpr_Const(IRConst_V128(i
));
771 /* This generates a normal (non load-linked) load. */
772 static IRExpr
* load ( IRType ty
, IRExpr
* addr
)
774 if (host_endness
== VexEndnessBE
)
775 return IRExpr_Load(Iend_BE
, ty
, addr
);
777 return IRExpr_Load(Iend_LE
, ty
, addr
);
780 static IRStmt
* stmt_load ( IRTemp result
,
781 IRExpr
* addr
, IRExpr
* storedata
)
783 if (host_endness
== VexEndnessBE
)
784 return IRStmt_LLSC(Iend_BE
, result
, addr
, storedata
);
786 return IRStmt_LLSC(Iend_LE
, result
, addr
, storedata
);
789 static IRExpr
* mkOR1 ( IRExpr
* arg1
, IRExpr
* arg2
)
791 vassert(typeOfIRExpr(irsb
->tyenv
, arg1
) == Ity_I1
);
792 vassert(typeOfIRExpr(irsb
->tyenv
, arg2
) == Ity_I1
);
793 return unop(Iop_32to1
, binop(Iop_Or32
, unop(Iop_1Uto32
, arg1
),
794 unop(Iop_1Uto32
, arg2
)));
797 static IRExpr
* mkAND1 ( IRExpr
* arg1
, IRExpr
* arg2
)
799 vassert(typeOfIRExpr(irsb
->tyenv
, arg1
) == Ity_I1
);
800 vassert(typeOfIRExpr(irsb
->tyenv
, arg2
) == Ity_I1
);
801 return unop(Iop_32to1
, binop(Iop_And32
, unop(Iop_1Uto32
, arg1
),
802 unop(Iop_1Uto32
, arg2
)));
805 static inline IRExpr
* mkXOr4_32( IRTemp t0
, IRTemp t1
, IRTemp t2
,
808 return binop( Iop_Xor32
,
809 binop( Iop_Xor32
, mkexpr( t0
), mkexpr( t1
) ),
810 binop( Iop_Xor32
, mkexpr( t2
), mkexpr( t3
) ) );
813 static inline IRExpr
* mkOr3_V128( IRTemp t0
, IRTemp t1
, IRTemp t2
)
815 return binop( Iop_OrV128
,
817 binop( Iop_OrV128
, mkexpr( t1
), mkexpr( t2
) ) );
820 static inline IRExpr
* mkOr4_V128( IRTemp t0
, IRTemp t1
, IRTemp t2
,
823 return binop( Iop_OrV128
,
824 binop( Iop_OrV128
, mkexpr( t0
), mkexpr( t1
) ),
825 binop( Iop_OrV128
, mkexpr( t2
), mkexpr( t3
) ) );
828 static inline IRExpr
* mkOr4_V128_expr( IRExpr
* t0
, IRExpr
* t1
, IRExpr
* t2
,
831 /* arguments are already expressions */
832 return binop( Iop_OrV128
,
833 binop( Iop_OrV128
, ( t0
), ( t1
) ),
834 binop( Iop_OrV128
, ( t2
), ( t3
) ) );
837 static IRExpr
* mkNOT1 ( IRExpr
* arg1
)
839 vassert(typeOfIRExpr(irsb
->tyenv
, arg1
) == Ity_I1
);
840 return unop(Iop_32to1
, unop(Iop_Not32
, unop(Iop_1Uto32
, arg1
) ) );
843 /* expand V128_8Ux16 to 2x V128_16Ux8's */
844 static void expand8Ux16( IRExpr
* vIn
,
845 /*OUTs*/ IRTemp
* vEvn
, IRTemp
* vOdd
)
847 IRTemp ones8x16
= newTemp(Ity_V128
);
849 vassert(typeOfIRExpr(irsb
->tyenv
, vIn
) == Ity_V128
);
850 vassert(vEvn
&& *vEvn
== IRTemp_INVALID
);
851 vassert(vOdd
&& *vOdd
== IRTemp_INVALID
);
852 *vEvn
= newTemp(Ity_V128
);
853 *vOdd
= newTemp(Ity_V128
);
855 assign( ones8x16
, unop(Iop_Dup8x16
, mkU8(0x1)) );
856 assign( *vOdd
, binop(Iop_MullEven8Ux16
, mkexpr(ones8x16
), vIn
) );
857 assign( *vEvn
, binop(Iop_MullEven8Ux16
, mkexpr(ones8x16
),
858 binop(Iop_ShrV128
, vIn
, mkU8(8))) );
861 /* expand V128_8Sx16 to 2x V128_16Sx8's */
862 static void expand8Sx16( IRExpr
* vIn
,
863 /*OUTs*/ IRTemp
* vEvn
, IRTemp
* vOdd
)
865 IRTemp ones8x16
= newTemp(Ity_V128
);
867 vassert(typeOfIRExpr(irsb
->tyenv
, vIn
) == Ity_V128
);
868 vassert(vEvn
&& *vEvn
== IRTemp_INVALID
);
869 vassert(vOdd
&& *vOdd
== IRTemp_INVALID
);
870 *vEvn
= newTemp(Ity_V128
);
871 *vOdd
= newTemp(Ity_V128
);
873 assign( ones8x16
, unop(Iop_Dup8x16
, mkU8(0x1)) );
874 assign( *vOdd
, binop(Iop_MullEven8Sx16
, mkexpr(ones8x16
), vIn
) );
875 assign( *vEvn
, binop(Iop_MullEven8Sx16
, mkexpr(ones8x16
),
876 binop(Iop_ShrV128
, vIn
, mkU8(8))) );
879 /* expand V128_16Uto8 to 2x V128_32Ux4's */
880 static void expand16Ux8( IRExpr
* vIn
,
881 /*OUTs*/ IRTemp
* vEvn
, IRTemp
* vOdd
)
883 IRTemp ones16x8
= newTemp(Ity_V128
);
885 vassert(typeOfIRExpr(irsb
->tyenv
, vIn
) == Ity_V128
);
886 vassert(vEvn
&& *vEvn
== IRTemp_INVALID
);
887 vassert(vOdd
&& *vOdd
== IRTemp_INVALID
);
888 *vEvn
= newTemp(Ity_V128
);
889 *vOdd
= newTemp(Ity_V128
);
891 assign( ones16x8
, unop(Iop_Dup16x8
, mkU16(0x1)) );
892 assign( *vOdd
, binop(Iop_MullEven16Ux8
, mkexpr(ones16x8
), vIn
) );
893 assign( *vEvn
, binop(Iop_MullEven16Ux8
, mkexpr(ones16x8
),
894 binop(Iop_ShrV128
, vIn
, mkU8(16))) );
897 /* expand V128_16Sto8 to 2x V128_32Sx4's */
898 static void expand16Sx8( IRExpr
* vIn
,
899 /*OUTs*/ IRTemp
* vEvn
, IRTemp
* vOdd
)
901 IRTemp ones16x8
= newTemp(Ity_V128
);
903 vassert(typeOfIRExpr(irsb
->tyenv
, vIn
) == Ity_V128
);
904 vassert(vEvn
&& *vEvn
== IRTemp_INVALID
);
905 vassert(vOdd
&& *vOdd
== IRTemp_INVALID
);
906 *vEvn
= newTemp(Ity_V128
);
907 *vOdd
= newTemp(Ity_V128
);
909 assign( ones16x8
, unop(Iop_Dup16x8
, mkU16(0x1)) );
910 assign( *vOdd
, binop(Iop_MullEven16Sx8
, mkexpr(ones16x8
), vIn
) );
911 assign( *vEvn
, binop(Iop_MullEven16Sx8
, mkexpr(ones16x8
),
912 binop(Iop_ShrV128
, vIn
, mkU8(16))) );
915 /* break V128 to 4xF64's*/
916 static void breakV128to4xF64( IRExpr
* t128
,
918 IRTemp
* t3
, IRTemp
* t2
,
919 IRTemp
* t1
, IRTemp
* t0
)
921 IRTemp hi64
= newTemp(Ity_I64
);
922 IRTemp lo64
= newTemp(Ity_I64
);
924 vassert(typeOfIRExpr(irsb
->tyenv
, t128
) == Ity_V128
);
925 vassert(t0
&& *t0
== IRTemp_INVALID
);
926 vassert(t1
&& *t1
== IRTemp_INVALID
);
927 vassert(t2
&& *t2
== IRTemp_INVALID
);
928 vassert(t3
&& *t3
== IRTemp_INVALID
);
929 *t0
= newTemp(Ity_F64
);
930 *t1
= newTemp(Ity_F64
);
931 *t2
= newTemp(Ity_F64
);
932 *t3
= newTemp(Ity_F64
);
934 assign( hi64
, unop(Iop_V128HIto64
, t128
) );
935 assign( lo64
, unop(Iop_V128to64
, t128
) );
938 unop( Iop_ReinterpI32asF32
,
939 unop( Iop_64HIto32
, mkexpr( hi64
) ) ) ) );
942 unop( Iop_ReinterpI32asF32
, unop( Iop_64to32
, mkexpr( hi64
) ) ) ) );
945 unop( Iop_ReinterpI32asF32
,
946 unop( Iop_64HIto32
, mkexpr( lo64
) ) ) ) );
949 unop( Iop_ReinterpI32asF32
, unop( Iop_64to32
, mkexpr( lo64
) ) ) ) );
953 /* break V128 to 4xI32's, then sign-extend to I64's */
954 static void breakV128to4x64S( IRExpr
* t128
,
956 IRTemp
* t3
, IRTemp
* t2
,
957 IRTemp
* t1
, IRTemp
* t0
)
959 IRTemp hi64
= newTemp(Ity_I64
);
960 IRTemp lo64
= newTemp(Ity_I64
);
962 vassert(typeOfIRExpr(irsb
->tyenv
, t128
) == Ity_V128
);
963 vassert(t0
&& *t0
== IRTemp_INVALID
);
964 vassert(t1
&& *t1
== IRTemp_INVALID
);
965 vassert(t2
&& *t2
== IRTemp_INVALID
);
966 vassert(t3
&& *t3
== IRTemp_INVALID
);
967 *t0
= newTemp(Ity_I64
);
968 *t1
= newTemp(Ity_I64
);
969 *t2
= newTemp(Ity_I64
);
970 *t3
= newTemp(Ity_I64
);
972 assign( hi64
, unop(Iop_V128HIto64
, t128
) );
973 assign( lo64
, unop(Iop_V128to64
, t128
) );
974 assign( *t3
, unop(Iop_32Sto64
, unop(Iop_64HIto32
, mkexpr(hi64
))) );
975 assign( *t2
, unop(Iop_32Sto64
, unop(Iop_64to32
, mkexpr(hi64
))) );
976 assign( *t1
, unop(Iop_32Sto64
, unop(Iop_64HIto32
, mkexpr(lo64
))) );
977 assign( *t0
, unop(Iop_32Sto64
, unop(Iop_64to32
, mkexpr(lo64
))) );
980 /* break V128 to 4xI32's, then zero-extend to I64's */
981 static void breakV128to4x64U ( IRExpr
* t128
,
983 IRTemp
* t3
, IRTemp
* t2
,
984 IRTemp
* t1
, IRTemp
* t0
)
986 IRTemp hi64
= newTemp(Ity_I64
);
987 IRTemp lo64
= newTemp(Ity_I64
);
989 vassert(typeOfIRExpr(irsb
->tyenv
, t128
) == Ity_V128
);
990 vassert(t0
&& *t0
== IRTemp_INVALID
);
991 vassert(t1
&& *t1
== IRTemp_INVALID
);
992 vassert(t2
&& *t2
== IRTemp_INVALID
);
993 vassert(t3
&& *t3
== IRTemp_INVALID
);
994 *t0
= newTemp(Ity_I64
);
995 *t1
= newTemp(Ity_I64
);
996 *t2
= newTemp(Ity_I64
);
997 *t3
= newTemp(Ity_I64
);
999 assign( hi64
, unop(Iop_V128HIto64
, t128
) );
1000 assign( lo64
, unop(Iop_V128to64
, t128
) );
1001 assign( *t3
, unop(Iop_32Uto64
, unop(Iop_64HIto32
, mkexpr(hi64
))) );
1002 assign( *t2
, unop(Iop_32Uto64
, unop(Iop_64to32
, mkexpr(hi64
))) );
1003 assign( *t1
, unop(Iop_32Uto64
, unop(Iop_64HIto32
, mkexpr(lo64
))) );
1004 assign( *t0
, unop(Iop_32Uto64
, unop(Iop_64to32
, mkexpr(lo64
))) );
1007 static void breakV128to4x32( IRExpr
* t128
,
1009 IRTemp
* t3
, IRTemp
* t2
,
1010 IRTemp
* t1
, IRTemp
* t0
)
1012 IRTemp hi64
= newTemp(Ity_I64
);
1013 IRTemp lo64
= newTemp(Ity_I64
);
1015 vassert(typeOfIRExpr(irsb
->tyenv
, t128
) == Ity_V128
);
1016 vassert(t0
&& *t0
== IRTemp_INVALID
);
1017 vassert(t1
&& *t1
== IRTemp_INVALID
);
1018 vassert(t2
&& *t2
== IRTemp_INVALID
);
1019 vassert(t3
&& *t3
== IRTemp_INVALID
);
1020 *t0
= newTemp(Ity_I32
);
1021 *t1
= newTemp(Ity_I32
);
1022 *t2
= newTemp(Ity_I32
);
1023 *t3
= newTemp(Ity_I32
);
1025 assign( hi64
, unop(Iop_V128HIto64
, t128
) );
1026 assign( lo64
, unop(Iop_V128to64
, t128
) );
1027 assign( *t3
, unop(Iop_64HIto32
, mkexpr(hi64
)) );
1028 assign( *t2
, unop(Iop_64to32
, mkexpr(hi64
)) );
1029 assign( *t1
, unop(Iop_64HIto32
, mkexpr(lo64
)) );
1030 assign( *t0
, unop(Iop_64to32
, mkexpr(lo64
)) );
1033 static IRExpr
* mkV128from32( IRTemp t3
, IRTemp t2
,
1034 IRTemp t1
, IRTemp t0
)
1037 binop( Iop_64HLtoV128
,
1038 binop(Iop_32HLto64
, mkexpr(t3
), mkexpr(t2
)),
1039 binop(Iop_32HLto64
, mkexpr(t1
), mkexpr(t0
))
1043 static IRExpr
* extract_field_from_vector( IRTemp vB
, IRExpr
* index
, UInt mask
)
1045 /* vB is a vector, extract bits starting at index to size of mask */
1046 return unop( Iop_V128to64
,
1051 binop( Iop_Mul64
, index
,
1053 binop( Iop_64HLtoV128
,
1055 mkU64( mask
) ) ) );
1058 static IRExpr
* insert_field_into_vector( IRTemp vSrc
, IRExpr
* index
,
1059 IRExpr
* bits
, IRExpr
* mask
)
1061 /* vSrc is a vector v128, index is I64 between 0 and 15 bytes, bits is I64,
1062 mask is I64. Indexing is based on the least significant byte being
1063 index 0. Insert bits starting at index to size of mask */
1064 IRTemp shift
= newTemp(Ity_I8
);
1065 IRTemp tmp_mask
= newTemp(Ity_V128
);
1066 IRTemp tmp_not_mask
= newTemp(Ity_V128
);
1067 UInt index_mask
= 0xF; //Index is only 4-bits wide
1069 assign( shift
, unop( Iop_64to8
,
1073 mkU64( index_mask
) ),
1075 assign( tmp_mask
, binop( Iop_ShlV128
,
1076 binop( Iop_64HLtoV128
,
1080 assign( tmp_not_mask
, unop( Iop_NotV128
, mkexpr( tmp_mask
) ) );
1081 return binop( Iop_OrV128
,
1084 mkexpr( tmp_not_mask
) ),
1087 binop( Iop_64HLtoV128
,
1091 mkexpr( tmp_mask
) ) );
1094 static IRExpr
* extractBytefromV256( IRTemp vA
, IRTemp vB
, UInt byte_index
)
1096 UInt byte_mask
= 0xFF;
1097 UInt byte_size
= 8; // size in bits
1098 IRTemp shift
= newTemp(Ity_I8
);
1099 IRTemp select_tmp
= newTemp(Ity_I64
);
1100 IRTemp reg_select
= newTemp(Ity_V128
);
1101 IRTemp src_tmp
= newTemp(Ity_V128
);
1103 /* The byte numbering is right to left: byte_n-1, byte_n-2, ...., byte0.
1104 The byte-index is between 0 and 31. */
1105 assign( shift
, unop( Iop_64to8
,
1109 mkexpr( byte_index
) ),
1110 mkU64( byte_size
) ) ) );
1112 /* Create mask to select byte from srcA if byte_index > 16 or
1113 from srcB. Use byte_index[4] to select srcA or srcB. */
1114 assign( select_tmp
, unop( Iop_1Sto64
,
1117 mkexpr( byte_index
),
1120 assign( reg_select
, binop( Iop_64HLtoV128
,
1121 mkexpr( select_tmp
),
1122 mkexpr( select_tmp
) ) );
1127 mkexpr( reg_select
),
1130 mkexpr( shift
) ) ),
1132 unop( Iop_NotV128
, mkexpr( reg_select
) ),
1135 mkexpr( shift
) ) ) ) );
1137 /* Mask off element */
1138 return binop( Iop_And64
,
1139 unop( Iop_V128to64
, mkexpr( src_tmp
) ),
1140 mkU64( byte_mask
) );
1143 /* Signed saturating narrow 64S to 32 */
1144 static IRExpr
* mkQNarrow64Sto32 ( IRExpr
* t64
)
1146 IRTemp hi32
= newTemp(Ity_I32
);
1147 IRTemp lo32
= newTemp(Ity_I32
);
1149 vassert(typeOfIRExpr(irsb
->tyenv
, t64
) == Ity_I64
);
1151 assign( hi32
, unop(Iop_64HIto32
, t64
));
1152 assign( lo32
, unop(Iop_64to32
, t64
));
1155 /* if (hi32 == (lo32 >>s 31)) */
1156 binop(Iop_CmpEQ32
, mkexpr(hi32
),
1157 binop( Iop_Sar32
, mkexpr(lo32
), mkU8(31))),
1158 /* then: within signed-32 range: lo half good enough */
1160 /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */
1161 binop(Iop_Add32
, mkU32(0x7FFFFFFF),
1162 binop(Iop_Shr32
, mkexpr(hi32
), mkU8(31))));
1165 /* Unsigned saturating narrow 64S to 32 */
1166 static IRExpr
* mkQNarrow64Uto32 ( IRExpr
* t64
)
1168 IRTemp hi32
= newTemp(Ity_I32
);
1169 IRTemp lo32
= newTemp(Ity_I32
);
1171 vassert(typeOfIRExpr(irsb
->tyenv
, t64
) == Ity_I64
);
1173 assign( hi32
, unop(Iop_64HIto32
, t64
));
1174 assign( lo32
, unop(Iop_64to32
, t64
));
1177 /* if (top 32 bits of t64 are 0) */
1178 binop(Iop_CmpEQ32
, mkexpr(hi32
), mkU32(0)),
1179 /* then: within unsigned-32 range: lo half good enough */
1181 /* else: positive saturate -> 0xFFFFFFFF */
1185 /* Signed saturate narrow 64->32, combining to V128 */
1186 static IRExpr
* mkV128from4x64S ( IRExpr
* t3
, IRExpr
* t2
,
1187 IRExpr
* t1
, IRExpr
* t0
)
1189 vassert(typeOfIRExpr(irsb
->tyenv
, t3
) == Ity_I64
);
1190 vassert(typeOfIRExpr(irsb
->tyenv
, t2
) == Ity_I64
);
1191 vassert(typeOfIRExpr(irsb
->tyenv
, t1
) == Ity_I64
);
1192 vassert(typeOfIRExpr(irsb
->tyenv
, t0
) == Ity_I64
);
1193 return binop(Iop_64HLtoV128
,
1195 mkQNarrow64Sto32( t3
),
1196 mkQNarrow64Sto32( t2
)),
1198 mkQNarrow64Sto32( t1
),
1199 mkQNarrow64Sto32( t0
)));
1202 /* Unsigned saturate narrow 64->32, combining to V128 */
1203 static IRExpr
* mkV128from4x64U ( IRExpr
* t3
, IRExpr
* t2
,
1204 IRExpr
* t1
, IRExpr
* t0
)
1206 vassert(typeOfIRExpr(irsb
->tyenv
, t3
) == Ity_I64
);
1207 vassert(typeOfIRExpr(irsb
->tyenv
, t2
) == Ity_I64
);
1208 vassert(typeOfIRExpr(irsb
->tyenv
, t1
) == Ity_I64
);
1209 vassert(typeOfIRExpr(irsb
->tyenv
, t0
) == Ity_I64
);
1210 return binop(Iop_64HLtoV128
,
1212 mkQNarrow64Uto32( t3
),
1213 mkQNarrow64Uto32( t2
)),
1215 mkQNarrow64Uto32( t1
),
1216 mkQNarrow64Uto32( t0
)));
1219 /* Simulate irops Iop_MullOdd*, since we don't have them */
1220 #define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \
1221 binop(Iop_MullEven8Ux16, \
1222 binop(Iop_ShrV128, expr_vA, mkU8(8)), \
1223 binop(Iop_ShrV128, expr_vB, mkU8(8)))
1225 #define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \
1226 binop(Iop_MullEven8Sx16, \
1227 binop(Iop_ShrV128, expr_vA, mkU8(8)), \
1228 binop(Iop_ShrV128, expr_vB, mkU8(8)))
1230 #define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \
1231 binop(Iop_MullEven16Ux8, \
1232 binop(Iop_ShrV128, expr_vA, mkU8(16)), \
1233 binop(Iop_ShrV128, expr_vB, mkU8(16)))
1235 #define MK_Iop_MullOdd32Ux4( expr_vA, expr_vB ) \
1236 binop(Iop_MullEven32Ux4, \
1237 binop(Iop_ShrV128, expr_vA, mkU8(32)), \
1238 binop(Iop_ShrV128, expr_vB, mkU8(32)))
1240 #define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \
1241 binop(Iop_MullEven16Sx8, \
1242 binop(Iop_ShrV128, expr_vA, mkU8(16)), \
1243 binop(Iop_ShrV128, expr_vB, mkU8(16)))
1245 #define MK_Iop_MullOdd32Sx4( expr_vA, expr_vB ) \
1246 binop(Iop_MullEven32Sx4, \
1247 binop(Iop_ShrV128, expr_vA, mkU8(32)), \
1248 binop(Iop_ShrV128, expr_vB, mkU8(32)))
1251 static IRExpr
* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr
* src
)
1253 vassert(typeOfIRExpr(irsb
->tyenv
, src
) == Ity_I64
);
1254 return unop(Iop_32Sto64
, unop(Iop_64to32
, src
));
1257 static IRExpr
* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr
* src
)
1259 vassert(typeOfIRExpr(irsb
->tyenv
, src
) == Ity_I64
);
1260 return unop(Iop_32Uto64
, unop(Iop_64to32
, src
));
1263 static IROp
mkSzOp ( IRType ty
, IROp op8
)
1266 vassert(ty
== Ity_I8
|| ty
== Ity_I16
||
1267 ty
== Ity_I32
|| ty
== Ity_I64
);
1268 vassert(op8
== Iop_Add8
|| op8
== Iop_Sub8
|| op8
== Iop_Mul8
||
1269 op8
== Iop_Or8
|| op8
== Iop_And8
|| op8
== Iop_Xor8
||
1270 op8
== Iop_Shl8
|| op8
== Iop_Shr8
|| op8
== Iop_Sar8
||
1271 op8
== Iop_CmpEQ8
|| op8
== Iop_CmpNE8
||
1273 adj
= ty
==Ity_I8
? 0 : (ty
==Ity_I16
? 1 : (ty
==Ity_I32
? 2 : 3));
1277 /* Make sure we get valid 32 and 64bit addresses */
1278 static Addr64
mkSzAddr ( IRType ty
, Addr64 addr
)
1280 vassert(ty
== Ity_I32
|| ty
== Ity_I64
);
1281 return ( ty
== Ity_I64
?
1283 (Addr64
)extend_s_32to64( toUInt(addr
) ) );
1286 /* sz, ULong -> IRExpr */
1287 static IRExpr
* mkSzImm ( IRType ty
, ULong imm64
)
1289 vassert(ty
== Ity_I32
|| ty
== Ity_I64
);
1290 return ty
== Ity_I64
? mkU64(imm64
) : mkU32((UInt
)imm64
);
1293 /* sz, ULong -> IRConst */
1294 static IRConst
* mkSzConst ( IRType ty
, ULong imm64
)
1296 vassert(ty
== Ity_I32
|| ty
== Ity_I64
);
1297 return ( ty
== Ity_I64
?
1298 IRConst_U64(imm64
) :
1299 IRConst_U32((UInt
)imm64
) );
1302 /* Sign extend imm16 -> IRExpr* */
1303 static IRExpr
* mkSzExtendS16 ( IRType ty
, UInt imm16
)
1305 vassert(ty
== Ity_I32
|| ty
== Ity_I64
);
1306 return ( ty
== Ity_I64
?
1307 mkU64(extend_s_16to64(imm16
)) :
1308 mkU32(extend_s_16to32(imm16
)) );
1311 /* Sign extend imm32 -> IRExpr* */
1312 static IRExpr
* mkSzExtendS32 ( IRType ty
, UInt imm32
)
1314 vassert(ty
== Ity_I32
|| ty
== Ity_I64
);
1315 return ( ty
== Ity_I64
?
1316 mkU64(extend_s_32to64(imm32
)) :
1320 /* IR narrows I32/I64 -> I8/I16/I32 */
1321 static IRExpr
* mkNarrowTo8 ( IRType ty
, IRExpr
* src
)
1323 vassert(ty
== Ity_I32
|| ty
== Ity_I64
);
1324 return ty
== Ity_I64
? unop(Iop_64to8
, src
) : unop(Iop_32to8
, src
);
1327 static IRExpr
* mkNarrowTo16 ( IRType ty
, IRExpr
* src
)
1329 vassert(ty
== Ity_I32
|| ty
== Ity_I64
);
1330 return ty
== Ity_I64
? unop(Iop_64to16
, src
) : unop(Iop_32to16
, src
);
1333 static IRExpr
* mkNarrowTo32 ( IRType ty
, IRExpr
* src
)
1335 vassert(ty
== Ity_I32
|| ty
== Ity_I64
);
1336 return ty
== Ity_I64
? unop(Iop_64to32
, src
) : src
;
1339 /* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */
1340 static IRExpr
* mkWidenFrom8 ( IRType ty
, IRExpr
* src
, Bool sined
)
1343 vassert(ty
== Ity_I32
|| ty
== Ity_I64
);
1344 if (sined
) op
= (ty
==Ity_I32
) ? Iop_8Sto32
: Iop_8Sto64
;
1345 else op
= (ty
==Ity_I32
) ? Iop_8Uto32
: Iop_8Uto64
;
1346 return unop(op
, src
);
1349 static IRExpr
* mkWidenFrom16 ( IRType ty
, IRExpr
* src
, Bool sined
)
1352 vassert(ty
== Ity_I32
|| ty
== Ity_I64
);
1353 if (sined
) op
= (ty
==Ity_I32
) ? Iop_16Sto32
: Iop_16Sto64
;
1354 else op
= (ty
==Ity_I32
) ? Iop_16Uto32
: Iop_16Uto64
;
1355 return unop(op
, src
);
1358 static IRExpr
* mkWidenFrom32 ( IRType ty
, IRExpr
* src
, Bool sined
)
1360 vassert(ty
== Ity_I32
|| ty
== Ity_I64
);
1363 return (sined
) ? unop(Iop_32Sto64
, src
) : unop(Iop_32Uto64
, src
);
1367 static Int
integerGuestRegOffset ( UInt archreg
)
1369 vassert(archreg
< 32);
1371 // jrs: probably not necessary; only matters if we reference sub-parts
1372 // of the ppc registers, but that isn't the case
1373 // later: this might affect Altivec though?
1376 case 0: return offsetofPPCGuestState(guest_GPR0
);
1377 case 1: return offsetofPPCGuestState(guest_GPR1
);
1378 case 2: return offsetofPPCGuestState(guest_GPR2
);
1379 case 3: return offsetofPPCGuestState(guest_GPR3
);
1380 case 4: return offsetofPPCGuestState(guest_GPR4
);
1381 case 5: return offsetofPPCGuestState(guest_GPR5
);
1382 case 6: return offsetofPPCGuestState(guest_GPR6
);
1383 case 7: return offsetofPPCGuestState(guest_GPR7
);
1384 case 8: return offsetofPPCGuestState(guest_GPR8
);
1385 case 9: return offsetofPPCGuestState(guest_GPR9
);
1386 case 10: return offsetofPPCGuestState(guest_GPR10
);
1387 case 11: return offsetofPPCGuestState(guest_GPR11
);
1388 case 12: return offsetofPPCGuestState(guest_GPR12
);
1389 case 13: return offsetofPPCGuestState(guest_GPR13
);
1390 case 14: return offsetofPPCGuestState(guest_GPR14
);
1391 case 15: return offsetofPPCGuestState(guest_GPR15
);
1392 case 16: return offsetofPPCGuestState(guest_GPR16
);
1393 case 17: return offsetofPPCGuestState(guest_GPR17
);
1394 case 18: return offsetofPPCGuestState(guest_GPR18
);
1395 case 19: return offsetofPPCGuestState(guest_GPR19
);
1396 case 20: return offsetofPPCGuestState(guest_GPR20
);
1397 case 21: return offsetofPPCGuestState(guest_GPR21
);
1398 case 22: return offsetofPPCGuestState(guest_GPR22
);
1399 case 23: return offsetofPPCGuestState(guest_GPR23
);
1400 case 24: return offsetofPPCGuestState(guest_GPR24
);
1401 case 25: return offsetofPPCGuestState(guest_GPR25
);
1402 case 26: return offsetofPPCGuestState(guest_GPR26
);
1403 case 27: return offsetofPPCGuestState(guest_GPR27
);
1404 case 28: return offsetofPPCGuestState(guest_GPR28
);
1405 case 29: return offsetofPPCGuestState(guest_GPR29
);
1406 case 30: return offsetofPPCGuestState(guest_GPR30
);
1407 case 31: return offsetofPPCGuestState(guest_GPR31
);
1410 vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/
1413 static IRExpr
* getIReg ( UInt archreg
)
1415 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
1416 vassert(archreg
< 32);
1417 return IRExpr_Get( integerGuestRegOffset(archreg
), ty
);
1420 /* Ditto, but write to a reg instead. */
1421 static void putIReg ( UInt archreg
, IRExpr
* e
)
1423 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
1424 vassert(archreg
< 32);
1425 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == ty
);
1426 stmt( IRStmt_Put(integerGuestRegOffset(archreg
), e
) );
1430 /* Floating point egisters are mapped to VSX registers[0..31]. */
1431 static Int
floatGuestRegOffset ( UInt archreg
)
1433 vassert(archreg
< 32);
1435 if (host_endness
== VexEndnessLE
) {
1437 case 0: return offsetofPPCGuestState(guest_VSR0
) + 8;
1438 case 1: return offsetofPPCGuestState(guest_VSR1
) + 8;
1439 case 2: return offsetofPPCGuestState(guest_VSR2
) + 8;
1440 case 3: return offsetofPPCGuestState(guest_VSR3
) + 8;
1441 case 4: return offsetofPPCGuestState(guest_VSR4
) + 8;
1442 case 5: return offsetofPPCGuestState(guest_VSR5
) + 8;
1443 case 6: return offsetofPPCGuestState(guest_VSR6
) + 8;
1444 case 7: return offsetofPPCGuestState(guest_VSR7
) + 8;
1445 case 8: return offsetofPPCGuestState(guest_VSR8
) + 8;
1446 case 9: return offsetofPPCGuestState(guest_VSR9
) + 8;
1447 case 10: return offsetofPPCGuestState(guest_VSR10
) + 8;
1448 case 11: return offsetofPPCGuestState(guest_VSR11
) + 8;
1449 case 12: return offsetofPPCGuestState(guest_VSR12
) + 8;
1450 case 13: return offsetofPPCGuestState(guest_VSR13
) + 8;
1451 case 14: return offsetofPPCGuestState(guest_VSR14
) + 8;
1452 case 15: return offsetofPPCGuestState(guest_VSR15
) + 8;
1453 case 16: return offsetofPPCGuestState(guest_VSR16
) + 8;
1454 case 17: return offsetofPPCGuestState(guest_VSR17
) + 8;
1455 case 18: return offsetofPPCGuestState(guest_VSR18
) + 8;
1456 case 19: return offsetofPPCGuestState(guest_VSR19
) + 8;
1457 case 20: return offsetofPPCGuestState(guest_VSR20
) + 8;
1458 case 21: return offsetofPPCGuestState(guest_VSR21
) + 8;
1459 case 22: return offsetofPPCGuestState(guest_VSR22
) + 8;
1460 case 23: return offsetofPPCGuestState(guest_VSR23
) + 8;
1461 case 24: return offsetofPPCGuestState(guest_VSR24
) + 8;
1462 case 25: return offsetofPPCGuestState(guest_VSR25
) + 8;
1463 case 26: return offsetofPPCGuestState(guest_VSR26
) + 8;
1464 case 27: return offsetofPPCGuestState(guest_VSR27
) + 8;
1465 case 28: return offsetofPPCGuestState(guest_VSR28
) + 8;
1466 case 29: return offsetofPPCGuestState(guest_VSR29
) + 8;
1467 case 30: return offsetofPPCGuestState(guest_VSR30
) + 8;
1468 case 31: return offsetofPPCGuestState(guest_VSR31
) + 8;
1473 case 0: return offsetofPPCGuestState(guest_VSR0
);
1474 case 1: return offsetofPPCGuestState(guest_VSR1
);
1475 case 2: return offsetofPPCGuestState(guest_VSR2
);
1476 case 3: return offsetofPPCGuestState(guest_VSR3
);
1477 case 4: return offsetofPPCGuestState(guest_VSR4
);
1478 case 5: return offsetofPPCGuestState(guest_VSR5
);
1479 case 6: return offsetofPPCGuestState(guest_VSR6
);
1480 case 7: return offsetofPPCGuestState(guest_VSR7
);
1481 case 8: return offsetofPPCGuestState(guest_VSR8
);
1482 case 9: return offsetofPPCGuestState(guest_VSR9
);
1483 case 10: return offsetofPPCGuestState(guest_VSR10
);
1484 case 11: return offsetofPPCGuestState(guest_VSR11
);
1485 case 12: return offsetofPPCGuestState(guest_VSR12
);
1486 case 13: return offsetofPPCGuestState(guest_VSR13
);
1487 case 14: return offsetofPPCGuestState(guest_VSR14
);
1488 case 15: return offsetofPPCGuestState(guest_VSR15
);
1489 case 16: return offsetofPPCGuestState(guest_VSR16
);
1490 case 17: return offsetofPPCGuestState(guest_VSR17
);
1491 case 18: return offsetofPPCGuestState(guest_VSR18
);
1492 case 19: return offsetofPPCGuestState(guest_VSR19
);
1493 case 20: return offsetofPPCGuestState(guest_VSR20
);
1494 case 21: return offsetofPPCGuestState(guest_VSR21
);
1495 case 22: return offsetofPPCGuestState(guest_VSR22
);
1496 case 23: return offsetofPPCGuestState(guest_VSR23
);
1497 case 24: return offsetofPPCGuestState(guest_VSR24
);
1498 case 25: return offsetofPPCGuestState(guest_VSR25
);
1499 case 26: return offsetofPPCGuestState(guest_VSR26
);
1500 case 27: return offsetofPPCGuestState(guest_VSR27
);
1501 case 28: return offsetofPPCGuestState(guest_VSR28
);
1502 case 29: return offsetofPPCGuestState(guest_VSR29
);
1503 case 30: return offsetofPPCGuestState(guest_VSR30
);
1504 case 31: return offsetofPPCGuestState(guest_VSR31
);
1508 vpanic("floatGuestRegOffset(ppc)"); /*notreached*/
1511 static IRExpr
* getFReg ( UInt archreg
)
1513 vassert(archreg
< 32);
1514 return IRExpr_Get( floatGuestRegOffset(archreg
), Ity_F64
);
1517 /* Ditto, but write to a reg instead. */
1518 static void putFReg ( UInt archreg
, IRExpr
* e
)
1520 vassert(archreg
< 32);
1521 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_F64
);
1522 stmt( IRStmt_Put(floatGuestRegOffset(archreg
), e
) );
1525 /* get Decimal float value. Note, they share floating point register file. */
1526 static IRExpr
* getDReg(UInt archreg
) {
1528 vassert( archreg
< 32 );
1529 e
= IRExpr_Get( floatGuestRegOffset( archreg
), Ity_D64
);
1532 static IRExpr
* getDReg32(UInt archreg
) {
1534 vassert( archreg
< 32 );
1535 e
= IRExpr_Get( floatGuestRegOffset( archreg
), Ity_D32
);
1539 /* Read a floating point register pair and combine their contents into a
1541 static IRExpr
*getDReg_pair(UInt archreg
) {
1542 IRExpr
*high
= getDReg( archreg
);
1543 IRExpr
*low
= getDReg( archreg
+ 1 );
1545 return binop( Iop_D64HLtoD128
, high
, low
);
1548 /* Ditto, but write to a reg instead. */
1549 static void putDReg32(UInt archreg
, IRExpr
* e
) {
1550 vassert( archreg
< 32 );
1551 vassert( typeOfIRExpr(irsb
->tyenv
, e
) == Ity_D32
);
1552 stmt( IRStmt_Put( floatGuestRegOffset( archreg
), e
) );
1555 static void putDReg(UInt archreg
, IRExpr
* e
) {
1556 vassert( archreg
< 32 );
1557 vassert( typeOfIRExpr(irsb
->tyenv
, e
) == Ity_D64
);
1558 stmt( IRStmt_Put( floatGuestRegOffset( archreg
), e
) );
1561 /* Write a 128-bit floating point value into a register pair. */
1562 static void putDReg_pair(UInt archreg
, IRExpr
*e
) {
1563 IRTemp low
= newTemp( Ity_D64
);
1564 IRTemp high
= newTemp( Ity_D64
);
1566 vassert( archreg
< 32 );
1567 vassert( typeOfIRExpr(irsb
->tyenv
, e
) == Ity_D128
);
1569 assign( low
, unop( Iop_D128LOtoD64
, e
) );
1570 assign( high
, unop( Iop_D128HItoD64
, e
) );
1572 stmt( IRStmt_Put( floatGuestRegOffset( archreg
), mkexpr( high
) ) );
1573 stmt( IRStmt_Put( floatGuestRegOffset( archreg
+ 1 ), mkexpr( low
) ) );
1576 static Int
vsxGuestRegOffset ( UInt archreg
)
1578 vassert(archreg
< 64);
1580 case 0: return offsetofPPCGuestState(guest_VSR0
);
1581 case 1: return offsetofPPCGuestState(guest_VSR1
);
1582 case 2: return offsetofPPCGuestState(guest_VSR2
);
1583 case 3: return offsetofPPCGuestState(guest_VSR3
);
1584 case 4: return offsetofPPCGuestState(guest_VSR4
);
1585 case 5: return offsetofPPCGuestState(guest_VSR5
);
1586 case 6: return offsetofPPCGuestState(guest_VSR6
);
1587 case 7: return offsetofPPCGuestState(guest_VSR7
);
1588 case 8: return offsetofPPCGuestState(guest_VSR8
);
1589 case 9: return offsetofPPCGuestState(guest_VSR9
);
1590 case 10: return offsetofPPCGuestState(guest_VSR10
);
1591 case 11: return offsetofPPCGuestState(guest_VSR11
);
1592 case 12: return offsetofPPCGuestState(guest_VSR12
);
1593 case 13: return offsetofPPCGuestState(guest_VSR13
);
1594 case 14: return offsetofPPCGuestState(guest_VSR14
);
1595 case 15: return offsetofPPCGuestState(guest_VSR15
);
1596 case 16: return offsetofPPCGuestState(guest_VSR16
);
1597 case 17: return offsetofPPCGuestState(guest_VSR17
);
1598 case 18: return offsetofPPCGuestState(guest_VSR18
);
1599 case 19: return offsetofPPCGuestState(guest_VSR19
);
1600 case 20: return offsetofPPCGuestState(guest_VSR20
);
1601 case 21: return offsetofPPCGuestState(guest_VSR21
);
1602 case 22: return offsetofPPCGuestState(guest_VSR22
);
1603 case 23: return offsetofPPCGuestState(guest_VSR23
);
1604 case 24: return offsetofPPCGuestState(guest_VSR24
);
1605 case 25: return offsetofPPCGuestState(guest_VSR25
);
1606 case 26: return offsetofPPCGuestState(guest_VSR26
);
1607 case 27: return offsetofPPCGuestState(guest_VSR27
);
1608 case 28: return offsetofPPCGuestState(guest_VSR28
);
1609 case 29: return offsetofPPCGuestState(guest_VSR29
);
1610 case 30: return offsetofPPCGuestState(guest_VSR30
);
1611 case 31: return offsetofPPCGuestState(guest_VSR31
);
1612 case 32: return offsetofPPCGuestState(guest_VSR32
);
1613 case 33: return offsetofPPCGuestState(guest_VSR33
);
1614 case 34: return offsetofPPCGuestState(guest_VSR34
);
1615 case 35: return offsetofPPCGuestState(guest_VSR35
);
1616 case 36: return offsetofPPCGuestState(guest_VSR36
);
1617 case 37: return offsetofPPCGuestState(guest_VSR37
);
1618 case 38: return offsetofPPCGuestState(guest_VSR38
);
1619 case 39: return offsetofPPCGuestState(guest_VSR39
);
1620 case 40: return offsetofPPCGuestState(guest_VSR40
);
1621 case 41: return offsetofPPCGuestState(guest_VSR41
);
1622 case 42: return offsetofPPCGuestState(guest_VSR42
);
1623 case 43: return offsetofPPCGuestState(guest_VSR43
);
1624 case 44: return offsetofPPCGuestState(guest_VSR44
);
1625 case 45: return offsetofPPCGuestState(guest_VSR45
);
1626 case 46: return offsetofPPCGuestState(guest_VSR46
);
1627 case 47: return offsetofPPCGuestState(guest_VSR47
);
1628 case 48: return offsetofPPCGuestState(guest_VSR48
);
1629 case 49: return offsetofPPCGuestState(guest_VSR49
);
1630 case 50: return offsetofPPCGuestState(guest_VSR50
);
1631 case 51: return offsetofPPCGuestState(guest_VSR51
);
1632 case 52: return offsetofPPCGuestState(guest_VSR52
);
1633 case 53: return offsetofPPCGuestState(guest_VSR53
);
1634 case 54: return offsetofPPCGuestState(guest_VSR54
);
1635 case 55: return offsetofPPCGuestState(guest_VSR55
);
1636 case 56: return offsetofPPCGuestState(guest_VSR56
);
1637 case 57: return offsetofPPCGuestState(guest_VSR57
);
1638 case 58: return offsetofPPCGuestState(guest_VSR58
);
1639 case 59: return offsetofPPCGuestState(guest_VSR59
);
1640 case 60: return offsetofPPCGuestState(guest_VSR60
);
1641 case 61: return offsetofPPCGuestState(guest_VSR61
);
1642 case 62: return offsetofPPCGuestState(guest_VSR62
);
1643 case 63: return offsetofPPCGuestState(guest_VSR63
);
1646 vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/
1649 /* Vector registers are mapped to VSX registers[32..63]. */
1650 static Int
vectorGuestRegOffset ( UInt archreg
)
1652 vassert(archreg
< 32);
1655 case 0: return offsetofPPCGuestState(guest_VSR32
);
1656 case 1: return offsetofPPCGuestState(guest_VSR33
);
1657 case 2: return offsetofPPCGuestState(guest_VSR34
);
1658 case 3: return offsetofPPCGuestState(guest_VSR35
);
1659 case 4: return offsetofPPCGuestState(guest_VSR36
);
1660 case 5: return offsetofPPCGuestState(guest_VSR37
);
1661 case 6: return offsetofPPCGuestState(guest_VSR38
);
1662 case 7: return offsetofPPCGuestState(guest_VSR39
);
1663 case 8: return offsetofPPCGuestState(guest_VSR40
);
1664 case 9: return offsetofPPCGuestState(guest_VSR41
);
1665 case 10: return offsetofPPCGuestState(guest_VSR42
);
1666 case 11: return offsetofPPCGuestState(guest_VSR43
);
1667 case 12: return offsetofPPCGuestState(guest_VSR44
);
1668 case 13: return offsetofPPCGuestState(guest_VSR45
);
1669 case 14: return offsetofPPCGuestState(guest_VSR46
);
1670 case 15: return offsetofPPCGuestState(guest_VSR47
);
1671 case 16: return offsetofPPCGuestState(guest_VSR48
);
1672 case 17: return offsetofPPCGuestState(guest_VSR49
);
1673 case 18: return offsetofPPCGuestState(guest_VSR50
);
1674 case 19: return offsetofPPCGuestState(guest_VSR51
);
1675 case 20: return offsetofPPCGuestState(guest_VSR52
);
1676 case 21: return offsetofPPCGuestState(guest_VSR53
);
1677 case 22: return offsetofPPCGuestState(guest_VSR54
);
1678 case 23: return offsetofPPCGuestState(guest_VSR55
);
1679 case 24: return offsetofPPCGuestState(guest_VSR56
);
1680 case 25: return offsetofPPCGuestState(guest_VSR57
);
1681 case 26: return offsetofPPCGuestState(guest_VSR58
);
1682 case 27: return offsetofPPCGuestState(guest_VSR59
);
1683 case 28: return offsetofPPCGuestState(guest_VSR60
);
1684 case 29: return offsetofPPCGuestState(guest_VSR61
);
1685 case 30: return offsetofPPCGuestState(guest_VSR62
);
1686 case 31: return offsetofPPCGuestState(guest_VSR63
);
1689 vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/
1692 static IRExpr
* getVReg ( UInt archreg
)
1694 vassert(archreg
< 32);
1695 return IRExpr_Get( vectorGuestRegOffset(archreg
), Ity_V128
);
1698 /* Get contents of 128-bit reg guest register */
1699 static IRExpr
* getF128Reg ( UInt archreg
)
1701 vassert(archreg
< 64);
1702 return IRExpr_Get( vectorGuestRegOffset(archreg
), Ity_F128
);
1705 /* Ditto, but write to a reg instead. */
1706 static void putF128Reg ( UInt archreg
, IRExpr
* e
)
1708 vassert(archreg
< 64);
1709 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_F128
);
1710 stmt( IRStmt_Put(vectorGuestRegOffset(archreg
), e
) );
1713 /* Ditto, but write to a reg instead. */
1714 static void putVReg ( UInt archreg
, IRExpr
* e
)
1716 vassert(archreg
< 32);
1717 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_V128
);
1718 stmt( IRStmt_Put(vectorGuestRegOffset(archreg
), e
) );
1721 /* Get contents of VSX guest register */
1722 static IRExpr
* getVSReg ( UInt archreg
)
1724 vassert(archreg
< 64);
1725 return IRExpr_Get( vsxGuestRegOffset(archreg
), Ity_V128
);
1728 /* Ditto, but write to a VSX reg instead. */
1729 static void putVSReg ( UInt archreg
, IRExpr
* e
)
1731 vassert(archreg
< 64);
1732 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_V128
);
1733 stmt( IRStmt_Put(vsxGuestRegOffset(archreg
), e
) );
1737 static Int
guestCR321offset ( UInt cr
)
1740 case 0: return offsetofPPCGuestState(guest_CR0_321
);
1741 case 1: return offsetofPPCGuestState(guest_CR1_321
);
1742 case 2: return offsetofPPCGuestState(guest_CR2_321
);
1743 case 3: return offsetofPPCGuestState(guest_CR3_321
);
1744 case 4: return offsetofPPCGuestState(guest_CR4_321
);
1745 case 5: return offsetofPPCGuestState(guest_CR5_321
);
1746 case 6: return offsetofPPCGuestState(guest_CR6_321
);
1747 case 7: return offsetofPPCGuestState(guest_CR7_321
);
1748 default: vpanic("guestCR321offset(ppc)");
1752 static Int
guestCR0offset ( UInt cr
)
1755 case 0: return offsetofPPCGuestState(guest_CR0_0
);
1756 case 1: return offsetofPPCGuestState(guest_CR1_0
);
1757 case 2: return offsetofPPCGuestState(guest_CR2_0
);
1758 case 3: return offsetofPPCGuestState(guest_CR3_0
);
1759 case 4: return offsetofPPCGuestState(guest_CR4_0
);
1760 case 5: return offsetofPPCGuestState(guest_CR5_0
);
1761 case 6: return offsetofPPCGuestState(guest_CR6_0
);
1762 case 7: return offsetofPPCGuestState(guest_CR7_0
);
1763 default: vpanic("guestCR3offset(ppc)");
1775 } _popcount_data_type
;
1777 /*-----------------------------------------------------------*/
1778 /*--- IR popcount helpers ---*/
1779 /*-----------------------------------------------------------*/
1780 /* Generate an IR sequence to do a popcount operation on the supplied
1781 IRTemp, and return a new IRTemp holding the result. 'ty' may be
1782 Ity_I32 or Ity_I64 only. */
1783 static IRTemp
gen_POPCOUNT ( IRType ty
, IRTemp src
,
1784 _popcount_data_type data_type
)
1786 /* Do count across 2^data_type bits,
1788 half word: data_type = 4
1790 double word: data_type = 6 (not supported for 32-bit type)
1793 _popcount_data_type idx
, i
;
1795 IRTemp old
= IRTemp_INVALID
;
1796 IRTemp nyu
= IRTemp_INVALID
;
1798 vassert(ty
== Ity_I64
|| ty
== Ity_I32
);
1800 // Use a single IROp in cases where we can.
1802 if (ty
== Ity_I64
&& data_type
== DWORD
) {
1803 IRTemp res
= newTemp(Ity_I64
);
1804 assign(res
, unop(Iop_PopCount64
, mkexpr(src
)));
1808 if (ty
== Ity_I32
&& data_type
== WORD
) {
1809 IRTemp res
= newTemp(Ity_I32
);
1810 assign(res
, unop(Iop_PopCount32
, mkexpr(src
)));
1814 // For the rest, we have to do it the slow way.
1816 if (ty
== Ity_I32
) {
1818 for (idx
= 0; idx
< WORD
; idx
++) {
1819 mask
[idx
] = newTemp(ty
);
1820 shift
[idx
] = 1 << idx
;
1822 assign(mask
[0], mkU32(0x55555555));
1823 assign(mask
[1], mkU32(0x33333333));
1824 assign(mask
[2], mkU32(0x0F0F0F0F));
1825 assign(mask
[3], mkU32(0x00FF00FF));
1826 assign(mask
[4], mkU32(0x0000FFFF));
1828 for (i
= 0; i
< data_type
; i
++) {
1836 binop(Iop_Shr32
, mkexpr(old
), mkU8(shift
[i
])),
1843 // else, ty == Ity_I64
1846 for (i
= 0; i
< DWORD
; i
++) {
1847 mask
[i
] = newTemp( Ity_I64
);
1850 assign( mask
[0], mkU64( 0x5555555555555555ULL
) );
1851 assign( mask
[1], mkU64( 0x3333333333333333ULL
) );
1852 assign( mask
[2], mkU64( 0x0F0F0F0F0F0F0F0FULL
) );
1853 assign( mask
[3], mkU64( 0x00FF00FF00FF00FFULL
) );
1854 assign( mask
[4], mkU64( 0x0000FFFF0000FFFFULL
) );
1855 assign( mask
[5], mkU64( 0x00000000FFFFFFFFULL
) );
1857 for (i
= 0; i
< data_type
; i
++) {
1858 nyu
= newTemp( Ity_I64
);
1861 binop( Iop_And64
, mkexpr( old
), mkexpr( mask
[i
] ) ),
1863 binop( Iop_Shr64
, mkexpr( old
), mkU8( shift
[i
] ) ),
1864 mkexpr( mask
[i
] ) ) ) );
1870 /* Special purpose population count function for
1871 * vpopcntd in 32-bit mode.
1873 static IRTemp
gen_vpopcntd_mode32 ( IRTemp src1
, IRTemp src2
)
1875 IRTemp retval
= newTemp(Ity_I64
);
1882 unop(Iop_PopCount32
, mkexpr(src1
)),
1883 unop(Iop_PopCount32
, mkexpr(src2
)))));
1888 // ROTL(src32/64, rot_amt5/6)
1889 static IRExpr
* /* :: Ity_I32/64 */ ROTL ( IRExpr
* src
,
1893 vassert(typeOfIRExpr(irsb
->tyenv
,rot_amt
) == Ity_I8
);
1895 if (typeOfIRExpr(irsb
->tyenv
,src
) == Ity_I64
) {
1896 // rot = (src << rot_amt) | (src >> (64-rot_amt))
1897 mask
= binop(Iop_And8
, rot_amt
, mkU8(63));
1898 rot
= binop(Iop_Or64
,
1899 binop(Iop_Shl64
, src
, mask
),
1900 binop(Iop_Shr64
, src
, binop(Iop_Sub8
, mkU8(64), mask
)));
1902 // rot = (src << rot_amt) | (src >> (32-rot_amt))
1903 mask
= binop(Iop_And8
, rot_amt
, mkU8(31));
1904 rot
= binop(Iop_Or32
,
1905 binop(Iop_Shl32
, src
, mask
),
1906 binop(Iop_Shr32
, src
, binop(Iop_Sub8
, mkU8(32), mask
)));
1908 /* Note: the ITE not merely an optimisation; it's needed
1909 because otherwise the Shr is a shift by the word size when
1910 mask denotes zero. For rotates by immediates, a lot of
1911 this junk gets folded out. */
1912 return IRExpr_ITE( binop(Iop_CmpNE8
, mask
, mkU8(0)),
1913 /* non-zero rotate */ rot
,
1914 /* zero rotate */ src
);
1917 /* Standard effective address calc: (rA + rB) */
1918 static IRExpr
* ea_rA_idxd ( UInt rA
, UInt rB
)
1920 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
1923 return binop(mkSzOp(ty
, Iop_Add8
), getIReg(rA
), getIReg(rB
));
1926 /* Standard effective address calc: (rA + simm) */
1927 static IRExpr
* ea_rA_simm ( UInt rA
, UInt simm16
)
1929 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
1931 return binop(mkSzOp(ty
, Iop_Add8
), getIReg(rA
),
1932 mkSzExtendS16(ty
, simm16
));
1935 /* Standard effective address calc: (rA|0) */
1936 static IRExpr
* ea_rAor0 ( UInt rA
)
1938 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
1941 return mkSzImm(ty
, 0);
1947 /* Standard effective address calc: (rA|0) + rB */
1948 static IRExpr
* ea_rAor0_idxd ( UInt rA
, UInt rB
)
1952 return (rA
== 0) ? getIReg(rB
) : ea_rA_idxd( rA
, rB
);
1955 /* Standard effective address calc: (rA|0) + simm16 */
1956 static IRExpr
* ea_rAor0_simm ( UInt rA
, UInt simm16
)
1958 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
1961 return mkSzExtendS16(ty
, simm16
);
1963 return ea_rA_simm( rA
, simm16
);
1968 /* Align effective address */
1969 static IRExpr
* addr_align( IRExpr
* addr
, UChar align
)
1971 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
1974 case 1: return addr
; // byte aligned
1975 case 2: mask
= ~0ULL << 1; break; // half-word aligned
1976 case 4: mask
= ~0ULL << 2; break; // word aligned
1977 case 16: mask
= ~0ULL << 4; break; // quad-word aligned
1979 vex_printf("addr_align: align = %u\n", align
);
1980 vpanic("addr_align(ppc)");
1983 vassert(typeOfIRExpr(irsb
->tyenv
,addr
) == ty
);
1984 return binop( mkSzOp(ty
, Iop_And8
), addr
, mkSzImm(ty
, mask
) );
1988 /* Exit the trace if ADDR (intended to be a guest memory address) is
1989 not ALIGN-aligned, generating a request for a SIGBUS followed by a
1990 restart of the current insn. */
1991 static void gen_SIGBUS_if_misaligned ( IRTemp addr
, UChar align
)
1993 vassert(align
== 2 || align
== 4 || align
== 8 || align
== 16);
1995 vassert(typeOfIRTemp(irsb
->tyenv
, addr
) == Ity_I64
);
1999 binop(Iop_And64
, mkexpr(addr
), mkU64(align
-1)),
2002 IRConst_U64( guest_CIA_curr_instr
), OFFB_CIA
2006 vassert(typeOfIRTemp(irsb
->tyenv
, addr
) == Ity_I32
);
2010 binop(Iop_And32
, mkexpr(addr
), mkU32(align
-1)),
2013 IRConst_U32( guest_CIA_curr_instr
), OFFB_CIA
2020 /* Generate AbiHints which mark points at which the ELF or PowerOpen
2021 ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some
2022 N) becomes undefined. That is at function calls and returns. ELF
2023 ppc32 doesn't have this "feature" (how fortunate for it). nia is
2024 the address of the next instruction to be executed.
2026 static void make_redzone_AbiHint ( const VexAbiInfo
* vbi
,
2027 IRTemp nia
, const HChar
* who
)
2029 Int szB
= vbi
->guest_stack_redzone_size
;
2030 if (0) vex_printf("AbiHint: %s\n", who
);
2034 vassert(typeOfIRTemp(irsb
->tyenv
, nia
) == Ity_I64
);
2035 stmt( IRStmt_AbiHint(
2036 binop(Iop_Sub64
, getIReg(1), mkU64(szB
)),
2041 vassert(typeOfIRTemp(irsb
->tyenv
, nia
) == Ity_I32
);
2042 stmt( IRStmt_AbiHint(
2043 binop(Iop_Sub32
, getIReg(1), mkU32(szB
)),
2052 /*------------------------------------------------------------*/
2053 /*--- Helpers for condition codes. ---*/
2054 /*------------------------------------------------------------*/
2056 /* Condition register layout.
2058 In the hardware, CR is laid out like this. The leftmost end is the
2059 most significant bit in the register; however the IBM documentation
2060 numbers the bits backwards for some reason.
2062 CR0 CR1 .......... CR6 CR7
2063 0 .. 3 ....................... 28 .. 31 (IBM bit numbering)
2064 31 28 3 0 (normal bit numbering)
2066 Each CR field is 4 bits: [<,>,==,SO]
2068 Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc.
2070 Indexing from BI to guest state:
2074 this references CR n:
2076 off==0 -> guest_CRn_321 >> 3
2077 off==1 -> guest_CRn_321 >> 2
2078 off==2 -> guest_CRn_321 >> 1
2079 off==3 -> guest_CRn_SO
2081 Bear in mind the only significant bit in guest_CRn_SO is bit 0
2082 (normal notation) and in guest_CRn_321 the significant bits are
2083 3, 2 and 1 (normal notation).
2086 static void putCR321 ( UInt cr
, IRExpr
* e
)
2089 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_I8
);
2090 stmt( IRStmt_Put(guestCR321offset(cr
), e
) );
2093 static void putCR0 ( UInt cr
, IRExpr
* e
)
2096 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_I8
);
2097 stmt( IRStmt_Put(guestCR0offset(cr
), e
) );
2100 static void putC ( IRExpr
* e
)
2102 /* The assumption is that the value of the Floating-Point Result
2103 * Class Descriptor bit (C) is passed in the lower four bits of a
2106 * Note, the C and FPCC bits which are fields in the FPSCR
2107 * register are stored in their own memory location of
2108 * memory. The FPCC bits are in the lower 4 bits. The C bit needs
2109 * to be shifted to bit 4 in the memory location that holds C and FPCC.
2110 * Note not all of the FPSCR register bits are supported. We are
2111 * only writing C bit.
2115 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_I32
);
2117 /* Get the FPCC bit field */
2118 tmp
= binop( Iop_And32
,
2120 unop( Iop_8Uto32
, IRExpr_Get( OFFB_C_FPCC
, Ity_I8
) ) );
2122 stmt( IRStmt_Put( OFFB_C_FPCC
,
2124 binop( Iop_Or32
, tmp
,
2126 binop( Iop_And32
, mkU32( 0x1 ), e
),
2127 mkU8( 4 ) ) ) ) ) );
2130 static IRExpr
* /* :: Ity_I8 */ getCR0 ( UInt cr
)
2133 return IRExpr_Get(guestCR0offset(cr
), Ity_I8
);
2136 static IRExpr
* /* :: Ity_I8 */ getCR321 ( UInt cr
)
2139 return IRExpr_Get(guestCR321offset(cr
), Ity_I8
);
2142 /* Fetch the specified CR bit (as per IBM/hardware notation) and
2143 return it at the bottom of an I32; the top 31 bits are guaranteed
2145 static IRExpr
* /* :: Ity_I32 */ getCRbit ( UInt bi
)
2151 /* Fetch the SO bit for this CR field */
2152 /* Note: And32 is redundant paranoia iff guest state only has 0
2153 or 1 in that slot. */
2154 return binop(Iop_And32
, unop(Iop_8Uto32
, getCR0(n
)), mkU32(1));
2156 /* Fetch the <, > or == bit for this CR field */
2157 return binop( Iop_And32
,
2159 unop(Iop_8Uto32
, getCR321(n
)),
2160 mkU8(toUChar(3-off
)) ),
2165 /* Dually, write the least significant bit of BIT to the specified CR
2166 bit. Indexing as per getCRbit. */
2167 static void putCRbit ( UInt bi
, IRExpr
* bit
)
2171 vassert(typeOfIRExpr(irsb
->tyenv
,bit
) == Ity_I32
);
2172 safe
= binop(Iop_And32
, bit
, mkU32(1));
2177 /* This is the SO bit for this CR field */
2178 putCR0(n
, unop(Iop_32to8
, safe
));
2181 vassert(off
== 1 || off
== 2 || off
== 3);
2186 /* old value with field masked out */
2187 binop(Iop_And32
, unop(Iop_8Uto32
, getCR321(n
)),
2188 mkU32(~(1 << off
))),
2189 /* new value in the right place */
2190 binop(Iop_Shl32
, safe
, mkU8(toUChar(off
)))
2197 /* Fetch the specified CR bit (as per IBM/hardware notation) and
2198 return it somewhere in an I32; it does not matter where, but
2199 whichever bit it is, all other bits are guaranteed to be zero. In
2200 other words, the I32-typed expression will be zero if the bit is
2201 zero and nonzero if the bit is 1. Write into *where the index
2202 of where the bit will be. */
2205 IRExpr
* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi
, Int
* where
)
2211 /* Fetch the SO bit for this CR field */
2212 /* Note: And32 is redundant paranoia iff guest state only has 0
2213 or 1 in that slot. */
2215 return binop(Iop_And32
, unop(Iop_8Uto32
, getCR0(n
)), mkU32(1));
2217 /* Fetch the <, > or == bit for this CR field */
2219 return binop( Iop_And32
,
2220 unop(Iop_8Uto32
, getCR321(n
)),
2221 mkU32(1 << (3-off
)) );
2225 /* Set the CR0 flags following an arithmetic operation.
2226 (Condition Register CR0 Field Definition, PPC32 p60)
2228 static IRExpr
* getXER_SO ( void );
2229 static void set_CR0 ( IRExpr
* result
)
2231 vassert(typeOfIRExpr(irsb
->tyenv
,result
) == Ity_I32
||
2232 typeOfIRExpr(irsb
->tyenv
,result
) == Ity_I64
);
2234 putCR321( 0, unop(Iop_64to8
,
2235 binop(Iop_CmpORD64S
, result
, mkU64(0))) );
2237 putCR321( 0, unop(Iop_32to8
,
2238 binop(Iop_CmpORD32S
, result
, mkU32(0))) );
2240 putCR0( 0, getXER_SO() );
2244 /* Set the CR6 flags following an AltiVec compare operation.
2245 * NOTE: This also works for VSX single-precision compares.
2247 static void set_AV_CR6 ( IRExpr
* result
, Bool test_all_ones
)
2249 /* CR6[0:3] = {all_ones, 0, all_zeros, 0}
2250 32 bit: all_zeros = (v[0] || v[1] || v[2] || v[3]) == 0x0000'0000
2251 all_ones = ~(v[0] && v[1] && v[2] && v[3]) == 0x0000'0000
2252 where v[] denotes 32-bit lanes
2254 64 bit: all_zeros = (v[0] || v[1]) == 0x0000'0000'0000'0000
2255 all_ones = ~(v[0] && v[1]) == 0x0000'0000'0000'0000
2256 where v[] denotes 64-bit lanes
2258 The 32- and 64-bit versions compute the same thing, but the 64-bit one
2259 tries to be a bit more efficient.
2261 vassert(typeOfIRExpr(irsb
->tyenv
,result
) == Ity_V128
);
2263 IRTemp overlappedOred
= newTemp(Ity_V128
);
2264 IRTemp overlappedAnded
= newTemp(Ity_V128
);
2267 IRTemp v0
= newTemp(Ity_V128
);
2268 IRTemp v1
= newTemp(Ity_V128
);
2269 assign( v0
, result
);
2270 assign( v1
, binop(Iop_ShrV128
, result
, mkU8(64)) );
2271 assign(overlappedOred
,
2272 binop(Iop_OrV128
, mkexpr(v0
), mkexpr(v1
)));
2273 assign(overlappedAnded
,
2274 binop(Iop_AndV128
, mkexpr(v0
), mkexpr(v1
)));
2276 IRTemp v0
= newTemp(Ity_V128
);
2277 IRTemp v1
= newTemp(Ity_V128
);
2278 IRTemp v2
= newTemp(Ity_V128
);
2279 IRTemp v3
= newTemp(Ity_V128
);
2280 assign( v0
, result
);
2281 assign( v1
, binop(Iop_ShrV128
, result
, mkU8(32)) );
2282 assign( v2
, binop(Iop_ShrV128
, result
, mkU8(64)) );
2283 assign( v3
, binop(Iop_ShrV128
, result
, mkU8(96)) );
2284 assign(overlappedOred
,
2286 binop(Iop_OrV128
, mkexpr(v0
), mkexpr(v1
)),
2287 binop(Iop_OrV128
, mkexpr(v2
), mkexpr(v3
))));
2288 assign(overlappedAnded
,
2290 binop(Iop_AndV128
, mkexpr(v0
), mkexpr(v1
)),
2291 binop(Iop_AndV128
, mkexpr(v2
), mkexpr(v3
))));
2294 IRTemp rOnes
= newTemp(Ity_I8
);
2295 IRTemp rZeroes
= newTemp(Ity_I8
);
2302 unop(Iop_V128to64
, mkexpr(overlappedOred
)))));
2308 unop(Iop_V128to64
, mkexpr(overlappedAnded
))))));
2314 unop(Iop_V128to32
, mkexpr(overlappedOred
)))));
2320 unop(Iop_V128to32
, mkexpr(overlappedAnded
))))));
2323 // rOnes might not be used below. But iropt will remove it, so there's no
2324 // inefficiency as a result.
2326 if (test_all_ones
) {
2327 putCR321( 6, binop(Iop_Or8
,
2328 binop(Iop_Shl8
, mkexpr(rOnes
), mkU8(3)),
2329 binop(Iop_Shl8
, mkexpr(rZeroes
), mkU8(1))) );
2331 putCR321( 6, binop(Iop_Shl8
, mkexpr(rZeroes
), mkU8(1)) );
2333 putCR0( 6, mkU8(0) );
2337 static IRExpr
* create_DCM ( IRType size
, IRTemp NaN
, IRTemp inf
, IRTemp zero
,
2338 IRTemp dnorm
, IRTemp pos
)
2340 /* This is a general function for creating the DCM for a 32-bit or
2341 64-bit expression based on the passes size.
2344 IROp opAND
, opOR
, opSHL
, opXto1
, op1UtoX
;
2346 vassert( ( size
== Ity_I32
) || ( size
== Ity_I64
) );
2348 if ( size
== Ity_I32
) {
2353 op1UtoX
= Iop_1Uto32
;
2354 neg
= newTemp( Ity_I32
);
2361 op1UtoX
= Iop_1Uto64
;
2362 neg
= newTemp( Ity_I64
);
2365 assign( neg
, unop( op1UtoX
, mkNOT1( unop( opXto1
,
2366 mkexpr ( pos
) ) ) ) );
2369 binop( opSHL
, mkexpr( NaN
), mkU8( 6 ) ),
2402 mkexpr( dnorm
) ) ) ) );
2405 /*------------------------------------------------------------*/
2406 /*--- Helpers for XER flags. ---*/
2407 /*------------------------------------------------------------*/
2409 static void putXER_SO ( IRExpr
* e
)
2412 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_I8
);
2413 so
= binop(Iop_And8
, e
, mkU8(1));
2414 stmt( IRStmt_Put( OFFB_XER_SO
, so
) );
2417 static void putXER_OV ( IRExpr
* e
)
2419 /* Interface to write XER[OV] */
2421 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_I8
);
2422 ov
= binop(Iop_And8
, e
, mkU8(1));
2423 stmt( IRStmt_Put( OFFB_XER_OV
, ov
) );
2426 static void putXER_OV32 ( IRExpr
* e
)
2428 /*Interface to write XER[OV32] */
2430 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_I8
);
2431 ov
= binop(Iop_And8
, e
, mkU8(1));
2433 /* The OV32 bit was added to XER in ISA 3.0. Do not write unless we
2434 * ISA 3.0 or beyond is supported. */
2435 if( OV32_CA32_supported
)
2436 stmt( IRStmt_Put( OFFB_XER_OV32
, ov
) );
2439 static void putXER_CA ( IRExpr
* e
)
2441 /* Interface to write XER[CA] */
2443 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_I8
);
2444 ca
= binop(Iop_And8
, e
, mkU8(1));
2445 stmt( IRStmt_Put( OFFB_XER_CA
, ca
) );
2448 static void putXER_CA32 ( IRExpr
* e
)
2450 /* Interface to write XER[CA32] */
2452 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_I8
);
2453 ca
= binop(Iop_And8
, e
, mkU8(1));
2455 /* The CA32 bit was added to XER in ISA 3.0. Do not write unless we
2456 * ISA 3.0 or beyond is supported. */
2457 if( OV32_CA32_supported
)
2458 stmt( IRStmt_Put( OFFB_XER_CA32
, ca
) );
2461 static void putXER_BC ( IRExpr
* e
)
2464 vassert(typeOfIRExpr(irsb
->tyenv
, e
) == Ity_I8
);
2465 bc
= binop(Iop_And8
, e
, mkU8(0x7F));
2466 stmt( IRStmt_Put( OFFB_XER_BC
, bc
) );
2469 static IRExpr
* /* :: Ity_I8 */ getXER_SO ( void )
2471 return IRExpr_Get( OFFB_XER_SO
, Ity_I8
);
2474 static IRExpr
* /* :: Ity_I32 */ getXER_SO_32 ( void )
2476 return binop( Iop_And32
, unop(Iop_8Uto32
, getXER_SO()), mkU32(1) );
2479 static IRExpr
* /* :: Ity_I8 */ getXER_OV ( void )
2481 return IRExpr_Get( OFFB_XER_OV
, Ity_I8
);
2484 static IRExpr
* /* :: Ity_I8 */ getXER_OV32 ( void )
2486 return IRExpr_Get( OFFB_XER_OV32
, Ity_I8
);
2489 static IRExpr
* /* :: Ity_I32 */ getXER_OV_32 ( void )
2491 /* get XER[OV], 32-bit interface */
2492 return binop( Iop_And32
, unop(Iop_8Uto32
, getXER_OV()), mkU32(1) );
2495 static IRExpr
* /* :: Ity_I32 */ getXER_OV32_32 ( void )
2497 /* get XER[OV32], 32-bit interface */
2498 return binop( Iop_And32
, unop(Iop_8Uto32
, getXER_OV32()), mkU32(1) );
2501 static IRExpr
* /* :: Ity_I32 */ getXER_CA_32 ( void )
2503 /* get XER[CA], 32-bit interface */
2504 IRExpr
* ca
= IRExpr_Get( OFFB_XER_CA
, Ity_I8
);
2505 return binop( Iop_And32
, unop(Iop_8Uto32
, ca
), mkU32(1) );
2508 static IRExpr
* /* :: Ity_I32 */ getXER_CA32_32 ( void )
2510 /* get XER[CA32], 32-bit interface */
2511 IRExpr
* ca
= IRExpr_Get( OFFB_XER_CA32
, Ity_I8
);
2512 return binop( Iop_And32
, unop(Iop_8Uto32
, ca
), mkU32(1) );
2515 static IRExpr
* /* :: Ity_I8 */ getXER_BC ( void )
2517 return IRExpr_Get( OFFB_XER_BC
, Ity_I8
);
2520 static IRExpr
* /* :: Ity_I32 */ getXER_BC_32 ( void )
2522 IRExpr
* bc
= IRExpr_Get( OFFB_XER_BC
, Ity_I8
);
2523 return binop( Iop_And32
, unop(Iop_8Uto32
, bc
), mkU32(0x7F) );
2527 /* RES is the result of doing OP on ARGL and ARGR. Set %XER.OV and
2528 %XER.SO accordingly. */
2530 static IRExpr
* calculate_XER_OV_32( UInt op
, IRExpr
* res
,
2531 IRExpr
* argL
, IRExpr
* argR
)
2536 # define INT32_MIN 0x80000000
2538 # define XOR2(_aa,_bb) \
2539 binop(Iop_Xor32,(_aa),(_bb))
2541 # define XOR3(_cc,_dd,_ee) \
2542 binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee))
2544 # define AND3(_ff,_gg,_hh) \
2545 binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh))
2548 unop(Iop_Not32, (_jj))
2551 case /* 0 */ PPCG_FLAG_OP_ADD
:
2552 case /* 1 */ PPCG_FLAG_OP_ADDE
:
2553 /* (argL^argR^-1) & (argL^res) & (1<<31) ?1:0 */
2554 // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
2556 = AND3( XOR3(argL
,argR
,mkU32(-1)),
2559 /* xer_ov can only be 0 or 1<<31 */
2561 = binop(Iop_Shr32
, xer_ov
, mkU8(31) );
2564 case /* 2 */ PPCG_FLAG_OP_DIVW
:
2565 /* (argL == INT32_MIN && argR == -1) || argR == 0 */
2569 binop(Iop_CmpEQ32
, argL
, mkU32(INT32_MIN
)),
2570 binop(Iop_CmpEQ32
, argR
, mkU32(-1))
2572 binop(Iop_CmpEQ32
, argR
, mkU32(0) )
2575 = unop(Iop_1Uto32
, xer_ov
);
2578 case /* 3 */ PPCG_FLAG_OP_DIVWU
:
2581 = unop(Iop_1Uto32
, binop(Iop_CmpEQ32
, argR
, mkU32(0)));
2584 case /* 4 */ PPCG_FLAG_OP_MULLW
:
2585 /* OV true if result can't be represented in 32 bits
2586 i.e sHi != sign extension of sLo */
2587 t64
= newTemp(Ity_I64
);
2588 assign( t64
, binop(Iop_MullS32
, argL
, argR
) );
2590 = binop( Iop_CmpNE32
,
2591 unop(Iop_64HIto32
, mkexpr(t64
)),
2593 unop(Iop_64to32
, mkexpr(t64
)),
2597 = unop(Iop_1Uto32
, xer_ov
);
2600 case /* 5 */ PPCG_FLAG_OP_NEG
:
2601 /* argL == INT32_MIN */
2604 binop(Iop_CmpEQ32
, argL
, mkU32(INT32_MIN
)) );
2607 case /* 6 */ PPCG_FLAG_OP_SUBF
:
2608 case /* 7 */ PPCG_FLAG_OP_SUBFC
:
2609 case /* 8 */ PPCG_FLAG_OP_SUBFE
:
2610 /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */
2612 = AND3( XOR3(NOT(argL
),argR
,mkU32(-1)),
2613 XOR2(NOT(argL
),res
),
2615 /* xer_ov can only be 0 or 1<<31 */
2617 = binop(Iop_Shr32
, xer_ov
, mkU8(31) );
2620 case PPCG_FLAG_OP_DIVWEU
:
2623 unop( Iop_1Uto32
, binop( Iop_CmpEQ32
, argR
, mkU32( 0 ) ) ),
2624 unop( Iop_1Uto32
, binop( Iop_CmpLT32U
, argR
, argL
) ) );
2627 case PPCG_FLAG_OP_DIVWE
:
2629 /* If argR == 0 of if the result cannot fit in the 32-bit destination register,
2630 * then OV <- 1. If dest reg is 0 AND both dividend and divisor are non-zero,
2631 * an overflow is implied.
2633 xer_ov
= binop( Iop_Or32
,
2634 unop( Iop_1Uto32
, binop( Iop_CmpEQ32
, argR
, mkU32( 0 ) ) ),
2635 unop( Iop_1Uto32
, mkAND1( binop( Iop_CmpEQ32
, res
, mkU32( 0 ) ),
2636 mkAND1( binop( Iop_CmpNE32
, argL
, mkU32( 0 ) ),
2637 binop( Iop_CmpNE32
, argR
, mkU32( 0 ) ) ) ) ) );
2643 vex_printf("calculate_XER_OV_32: op = %u\n", op
);
2644 vpanic("calculate_XER_OV_32(ppc)");
2656 static void set_XER_OV_OV32_32( UInt op
, IRExpr
* res
,
2657 IRExpr
* argL
, IRExpr
* argR
)
2661 vassert(op
< PPCG_FLAG_OP_NUMBER
);
2662 vassert(typeOfIRExpr(irsb
->tyenv
,res
) == Ity_I32
);
2663 vassert(typeOfIRExpr(irsb
->tyenv
,argL
) == Ity_I32
);
2664 vassert(typeOfIRExpr(irsb
->tyenv
,argR
) == Ity_I32
);
2666 xer_ov
= calculate_XER_OV_32( op
, res
, argL
, argR
);
2668 /* xer_ov MUST denote either 0 or 1, no other value allowed */
2669 putXER_OV( unop(Iop_32to8
, xer_ov
) );
2670 putXER_OV32( unop(Iop_32to8
, xer_ov
) );
2673 static IRExpr
* calculate_XER_OV_64( UInt op
, IRExpr
* res
,
2674 IRExpr
* argL
, IRExpr
* argR
)
2678 # define INT64_MIN 0x8000000000000000ULL
2680 # define XOR2(_aa,_bb) \
2681 binop(Iop_Xor64,(_aa),(_bb))
2683 # define XOR3(_cc,_dd,_ee) \
2684 binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee))
2686 # define AND3(_ff,_gg,_hh) \
2687 binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh))
2690 unop(Iop_Not64, (_jj))
2693 case /* 0 */ PPCG_FLAG_OP_ADD
:
2694 case /* 1 */ PPCG_FLAG_OP_ADDE
:
2695 /* (argL^argR^-1) & (argL^res) & (1<<63) ? 1:0 */
2696 // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
2698 = AND3( XOR3(argL
,argR
,mkU64(-1)),
2701 /* xer_ov can only be 0 or 1<<63 */
2703 = unop(Iop_64to1
, binop(Iop_Shr64
, xer_ov
, mkU8(63)));
2706 case /* 2 */ PPCG_FLAG_OP_DIVW
:
2707 /* (argL == INT64_MIN && argR == -1) || argR == 0 */
2711 binop(Iop_CmpEQ64
, argL
, mkU64(INT64_MIN
)),
2712 binop(Iop_CmpEQ64
, argR
, mkU64(-1))
2714 binop(Iop_CmpEQ64
, argR
, mkU64(0) )
2718 case /* 3 */ PPCG_FLAG_OP_DIVWU
:
2721 = binop(Iop_CmpEQ64
, argR
, mkU64(0));
2724 case /* 4 */ PPCG_FLAG_OP_MULLW
: {
2725 /* OV true if result can't be represented in 64 bits
2726 i.e sHi != sign extension of sLo */
2728 = binop( Iop_CmpNE32
,
2729 unop(Iop_64HIto32
, res
),
2731 unop(Iop_64to32
, res
),
2737 case /* 5 */ PPCG_FLAG_OP_NEG
:
2738 /* argL == INT64_MIN */
2740 = binop(Iop_CmpEQ64
, argL
, mkU64(INT64_MIN
));
2743 case /* 6 */ PPCG_FLAG_OP_SUBF
:
2744 case /* 7 */ PPCG_FLAG_OP_SUBFC
:
2745 case /* 8 */ PPCG_FLAG_OP_SUBFE
:
2746 /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */
2748 = AND3( XOR3(NOT(argL
),argR
,mkU64(-1)),
2749 XOR2(NOT(argL
),res
),
2751 /* xer_ov can only be 0 or 1<<63 */
2753 = unop(Iop_64to1
, binop(Iop_Shr64
, xer_ov
, mkU8(63)));
2756 case /* 14 */ PPCG_FLAG_OP_DIVDE
:
2758 /* If argR == 0, we must set the OV bit. But there's another condition
2759 * where we can get overflow set for divde . . . when the
2760 * result cannot fit in the 64-bit destination register. If dest reg is 0 AND
2761 * both dividend and divisor are non-zero, it implies an overflow.
2764 = mkOR1( binop( Iop_CmpEQ64
, argR
, mkU64( 0 ) ),
2765 mkAND1( binop( Iop_CmpEQ64
, res
, mkU64( 0 ) ),
2766 mkAND1( binop( Iop_CmpNE64
, argL
, mkU64( 0 ) ),
2767 binop( Iop_CmpNE64
, argR
, mkU64( 0 ) ) ) ) );
2770 case /* 17 */ PPCG_FLAG_OP_DIVDEU
:
2771 /* If argR == 0 or if argL >= argR, set OV. */
2772 xer_ov
= mkOR1( binop( Iop_CmpEQ64
, argR
, mkU64( 0 ) ),
2773 binop( Iop_CmpLE64U
, argR
, argL
) );
2776 case /* 18 */ PPCG_FLAG_OP_MULLD
: {
2778 /* OV true if result can't be represented in 64 bits
2779 i.e sHi != sign extension of sLo */
2780 t128
= newTemp(Ity_I128
);
2781 assign( t128
, binop(Iop_MullS64
, argL
, argR
) );
2783 = binop( Iop_CmpNE64
,
2784 unop(Iop_128HIto64
, mkexpr(t128
)),
2786 unop(Iop_128to64
, mkexpr(t128
)),
2793 vex_printf("calculate_XER_OV_64: op = %u\n", op
);
2794 vpanic("calculate_XER_OV_64(ppc64)");
2806 static void set_XER_OV_64( UInt op
, IRExpr
* res
,
2807 IRExpr
* argL
, IRExpr
* argR
)
2810 vassert(op
< PPCG_FLAG_OP_NUMBER
);
2811 vassert(typeOfIRExpr(irsb
->tyenv
,res
) == Ity_I64
);
2812 vassert(typeOfIRExpr(irsb
->tyenv
,argL
) == Ity_I64
);
2813 vassert(typeOfIRExpr(irsb
->tyenv
,argR
) == Ity_I64
);
2815 /* xer_ov MUST denote either 0 or 1, no other value allowed */
2816 xer_ov
= calculate_XER_OV_64( op
, res
, argL
, argR
);
2817 putXER_OV( unop(Iop_1Uto8
, xer_ov
) );
2819 /* Update the summary overflow */
2820 putXER_SO( binop(Iop_Or8
, getXER_SO(), getXER_OV()) );
2823 static void update_SO( void ) {
2824 /* Update the summary overflow bit */
2825 putXER_SO( binop(Iop_Or8
, getXER_SO(), getXER_OV()) );
2828 static void copy_OV_to_OV32( void ) {
2829 /* Update the OV32 to match OV */
2830 putXER_OV32( getXER_OV() );
2833 static void set_XER_OV_OV32_SO ( IRType ty
, UInt op
, IRExpr
* res
,
2834 IRExpr
* argL
, IRExpr
* argR
)
2836 if (ty
== Ity_I32
) {
2837 set_XER_OV_OV32_32( op
, res
, argL
, argR
);
2840 set_XER_OV_64( op
, res
, argL
, argR
);
2841 xer_ov_32
= calculate_XER_OV_32( op
, unop(Iop_64to32
, res
),
2842 unop(Iop_64to32
, argL
),
2843 unop(Iop_64to32
, argR
));
2844 putXER_OV32( unop(Iop_32to8
, xer_ov_32
) );
2851 /* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA
2852 value being OLDCA. Set %XER.CA accordingly. */
2854 static IRExpr
* calculate_XER_CA_32 ( UInt op
, IRExpr
* res
,
2855 IRExpr
* argL
, IRExpr
* argR
, IRExpr
* oldca
)
2860 case /* 0 */ PPCG_FLAG_OP_ADD
:
2863 = unop(Iop_1Uto32
, binop(Iop_CmpLT32U
, res
, argL
));
2866 case /* 1 */ PPCG_FLAG_OP_ADDE
:
2867 /* res <u argL || (old_ca==1 && res==argL) */
2870 binop(Iop_CmpLT32U
, res
, argL
),
2872 binop(Iop_CmpEQ32
, oldca
, mkU32(1)),
2873 binop(Iop_CmpEQ32
, res
, argL
)
2877 = unop(Iop_1Uto32
, xer_ca
);
2880 case /* 8 */ PPCG_FLAG_OP_SUBFE
:
2881 /* res <u argR || (old_ca==1 && res==argR) */
2884 binop(Iop_CmpLT32U
, res
, argR
),
2886 binop(Iop_CmpEQ32
, oldca
, mkU32(1)),
2887 binop(Iop_CmpEQ32
, res
, argR
)
2891 = unop(Iop_1Uto32
, xer_ca
);
2894 case /* 7 */ PPCG_FLAG_OP_SUBFC
:
2895 case /* 9 */ PPCG_FLAG_OP_SUBFI
:
2898 = unop(Iop_1Uto32
, binop(Iop_CmpLE32U
, res
, argR
));
2901 case /* 10 */ PPCG_FLAG_OP_SRAW
:
2902 /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
2903 If it is <= 31, behave like SRAWI; else XER.CA is the sign
2905 /* This term valid for shift amount < 32 only */
2909 binop(Iop_Sar32
, argL
, mkU8(31)),
2913 binop(Iop_Shl32
, mkU32(1),
2914 unop(Iop_32to8
,argR
)),
2920 /* shift amt > 31 ? */
2921 binop(Iop_CmpLT32U
, mkU32(31), argR
),
2922 /* yes -- get sign bit of argL */
2923 binop(Iop_Shr32
, argL
, mkU8(31)),
2924 /* no -- be like srawi */
2925 unop(Iop_1Uto32
, binop(Iop_CmpNE32
, xer_ca
, mkU32(0)))
2929 case /* 11 */ PPCG_FLAG_OP_SRAWI
:
2930 /* xer_ca is 1 iff src was negative and bits_shifted_out !=
2931 0. Since the shift amount is known to be in the range
2932 0 .. 31 inclusive the following seems viable:
2933 xer.ca == 1 iff the following is nonzero:
2934 (argL >>s 31) -- either all 0s or all 1s
2935 & (argL & (1<<argR)-1) -- the stuff shifted out */
2939 binop(Iop_Sar32
, argL
, mkU8(31)),
2943 binop(Iop_Shl32
, mkU32(1),
2944 unop(Iop_32to8
,argR
)),
2949 = unop(Iop_1Uto32
, binop(Iop_CmpNE32
, xer_ca
, mkU32(0)));
2953 vex_printf("set_XER_CA: op = %u\n", op
);
2954 vpanic("set_XER_CA(ppc)");
2960 static void set_XER_CA_32 ( UInt op
, IRExpr
* res
,
2961 IRExpr
* argL
, IRExpr
* argR
, IRExpr
* oldca
)
2964 vassert(op
< PPCG_FLAG_OP_NUMBER
);
2965 vassert(typeOfIRExpr(irsb
->tyenv
,res
) == Ity_I32
);
2966 vassert(typeOfIRExpr(irsb
->tyenv
,argL
) == Ity_I32
);
2967 vassert(typeOfIRExpr(irsb
->tyenv
,argR
) == Ity_I32
);
2968 vassert(typeOfIRExpr(irsb
->tyenv
,oldca
) == Ity_I32
);
2970 /* Incoming oldca is assumed to hold the values 0 or 1 only. This
2971 seems reasonable given that it's always generated by
2972 getXER_CA_32(), which masks it accordingly. In any case it being
2973 0 or 1 is an invariant of the ppc guest state representation;
2974 if it has any other value, that invariant has been violated. */
2976 xer_ca
= calculate_XER_CA_32( op
, res
, argL
, argR
, oldca
);
2978 /* xer_ca MUST denote either 0 or 1, no other value allowed */
2979 putXER_CA( unop(Iop_32to8
, xer_ca
) );
2982 static IRExpr
* calculate_XER_CA_64 ( UInt op
, IRExpr
* res
,
2983 IRExpr
* argL
, IRExpr
* argR
, IRExpr
* oldca
)
2988 case /* 0 */ PPCG_FLAG_OP_ADD
:
2991 = unop(Iop_1Uto32
, binop(Iop_CmpLT64U
, res
, argL
));
2994 case /* 1 */ PPCG_FLAG_OP_ADDE
:
2995 /* res <u argL || (old_ca==1 && res==argL) */
2998 binop(Iop_CmpLT64U
, res
, argL
),
3000 binop(Iop_CmpEQ64
, oldca
, mkU64(1)),
3001 binop(Iop_CmpEQ64
, res
, argL
)
3005 = unop(Iop_1Uto32
, xer_ca
);
3008 case /* 8 */ PPCG_FLAG_OP_SUBFE
:
3009 /* res <u argR || (old_ca==1 && res==argR) */
3012 binop(Iop_CmpLT64U
, res
, argR
),
3014 binop(Iop_CmpEQ64
, oldca
, mkU64(1)),
3015 binop(Iop_CmpEQ64
, res
, argR
)
3019 = unop(Iop_1Uto32
, xer_ca
);
3022 case /* 7 */ PPCG_FLAG_OP_SUBFC
:
3023 case /* 9 */ PPCG_FLAG_OP_SUBFI
:
3026 = unop(Iop_1Uto32
, binop(Iop_CmpLE64U
, res
, argR
));
3030 case /* 10 */ PPCG_FLAG_OP_SRAW
:
3031 /* The shift amount is guaranteed to be in 0 .. 31 inclusive.
3032 If it is <= 31, behave like SRAWI; else XER.CA is the sign
3034 /* This term valid for shift amount < 31 only */
3039 binop(Iop_Sar64
, argL
, mkU8(31)),
3043 binop(Iop_Shl64
, mkU64(1),
3044 unop(Iop_64to8
,argR
)),
3050 /* shift amt > 31 ? */
3051 binop(Iop_CmpLT64U
, mkU64(31), argR
),
3052 /* yes -- get sign bit of argL */
3053 unop(Iop_64to32
, binop(Iop_Shr64
, argL
, mkU8(63))),
3054 /* no -- be like srawi */
3055 unop(Iop_1Uto32
, binop(Iop_CmpNE64
, xer_ca
, mkU64(0)))
3059 case /* 11 */ PPCG_FLAG_OP_SRAWI
:
3060 /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
3061 Since the shift amount is known to be in the range 0 .. 31
3062 inclusive the following seems viable:
3063 xer.ca == 1 iff the following is nonzero:
3064 (argL >>s 31) -- either all 0s or all 1s
3065 & (argL & (1<<argR)-1) -- the stuff shifted out */
3070 binop(Iop_Sar64
, argL
, mkU8(31)),
3074 binop(Iop_Shl64
, mkU64(1),
3075 unop(Iop_64to8
,argR
)),
3080 = unop(Iop_1Uto32
, binop(Iop_CmpNE64
, xer_ca
, mkU64(0)));
3084 case /* 12 */ PPCG_FLAG_OP_SRAD
:
3085 /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
3086 If it is <= 63, behave like SRADI; else XER.CA is the sign
3088 /* This term valid for shift amount < 63 only */
3093 binop(Iop_Sar64
, argL
, mkU8(63)),
3097 binop(Iop_Shl64
, mkU64(1),
3098 unop(Iop_64to8
,argR
)),
3104 /* shift amt > 63 ? */
3105 binop(Iop_CmpLT64U
, mkU64(63), argR
),
3106 /* yes -- get sign bit of argL */
3107 unop(Iop_64to32
, binop(Iop_Shr64
, argL
, mkU8(63))),
3108 /* no -- be like sradi */
3109 unop(Iop_1Uto32
, binop(Iop_CmpNE64
, xer_ca
, mkU64(0)))
3114 case /* 13 */ PPCG_FLAG_OP_SRADI
:
3115 /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
3116 Since the shift amount is known to be in the range 0 .. 63
3117 inclusive, the following seems viable:
3118 xer.ca == 1 iff the following is nonzero:
3119 (argL >>s 63) -- either all 0s or all 1s
3120 & (argL & (1<<argR)-1) -- the stuff shifted out */
3125 binop(Iop_Sar64
, argL
, mkU8(63)),
3129 binop(Iop_Shl64
, mkU64(1),
3130 unop(Iop_64to8
,argR
)),
3135 = unop(Iop_1Uto32
, binop(Iop_CmpNE64
, xer_ca
, mkU64(0)));
3139 vex_printf("set_XER_CA: op = %u\n", op
);
3140 vpanic("set_XER_CA(ppc64)");
3146 static void set_XER_CA_64 ( UInt op
, IRExpr
* res
,
3147 IRExpr
* argL
, IRExpr
* argR
, IRExpr
* oldca
)
3150 vassert(op
< PPCG_FLAG_OP_NUMBER
);
3151 vassert(typeOfIRExpr(irsb
->tyenv
,res
) == Ity_I64
);
3152 vassert(typeOfIRExpr(irsb
->tyenv
,argL
) == Ity_I64
);
3153 vassert(typeOfIRExpr(irsb
->tyenv
,argR
) == Ity_I64
);
3154 vassert(typeOfIRExpr(irsb
->tyenv
,oldca
) == Ity_I64
);
3156 /* Incoming oldca is assumed to hold the values 0 or 1 only. This
3157 seems reasonable given that it's always generated by
3158 getXER_CA_32(), which masks it accordingly. In any case it being
3159 0 or 1 is an invariant of the ppc guest state representation;
3160 if it has any other value, that invariant has been violated. */
3162 xer_ca
= calculate_XER_CA_64( op
, res
, argL
, argR
, oldca
);
3164 /* xer_ca MUST denote either 0 or 1, no other value allowed */
3165 putXER_CA( unop(Iop_32to8
, xer_ca
) );
3168 static void set_XER_CA_CA32 ( IRType ty
, UInt op
, IRExpr
* res
,
3169 IRExpr
* argL
, IRExpr
* argR
, IRExpr
* oldca
)
3171 if (ty
== Ity_I32
) {
3172 set_XER_CA_32( op
, res
, argL
, argR
, oldca
);
3174 set_XER_CA_64( op
, res
, argL
, argR
, oldca
);
3178 /* Used only by addex instruction, which uses and sets OV as carry. */
3179 static void set_XER_OV_OV32_ADDEX ( IRType ty
, IRExpr
* res
,
3180 IRExpr
* argL
, IRExpr
* argR
,
3183 if (ty
== Ity_I32
) {
3184 IRTemp xer_ov
= newTemp(Ity_I32
);
3185 assign ( xer_ov
, unop(Iop_32to8
,
3186 calculate_XER_CA_32( PPCG_FLAG_OP_ADDE
,
3187 res
, argL
, argR
, old_ov
) ) );
3188 putXER_OV( mkexpr (xer_ov
) );
3189 putXER_OV32( mkexpr (xer_ov
) );
3193 xer_ov
= calculate_XER_CA_64( PPCG_FLAG_OP_ADDE
,
3194 res
, argL
, argR
, old_ov
);
3195 putXER_OV( unop(Iop_32to8
, xer_ov
) );
3196 xer_ov_32
= calculate_XER_CA_32( PPCG_FLAG_OP_ADDE
,
3197 unop(Iop_64to32
, res
),
3198 unop(Iop_64to32
, argL
),
3199 unop(Iop_64to32
, argR
),
3200 unop(Iop_64to32
, old_ov
) );
3201 putXER_OV32( unop(Iop_32to8
, xer_ov_32
) );
3205 static IRExpr
* absI64( IRTemp src
)
3209 sign_mask
= newTemp( Ity_I64
);
3210 twos_comp
= newTemp( Ity_I64
);
3212 assign( sign_mask
, unop( Iop_1Sto64
, unop( Iop_64to1
, binop( Iop_Shr64
,
3213 mkexpr( src
), mkU8( 63 ) ) ) ) );
3214 assign( twos_comp
, binop( Iop_Add64
, unop( Iop_Not64
, mkexpr( src
) ), mkU64( 1 ) ) );
3216 return binop( Iop_Or64
,
3217 binop( Iop_And64
, mkexpr ( src
), unop( Iop_Not64
, mkexpr( sign_mask
) ) ),
3218 binop( Iop_And64
, mkexpr( twos_comp
), mkexpr( sign_mask
) ) );
3221 static IRExpr
* locate_vector_ele_eq ( IRTemp src
, IRExpr
*value
,
3222 UInt dir
, IRType size
)
3225 /* Find the index, 0 to max-1, of the element in 128-bit vector that matches
3226 value. The returned value will be index+1. Return the index as an
3227 Ity_I8. If no match is found, the returned value is equal to the number
3228 of elements in the vector plus one. The argument dir specifies match from
3229 left (dir = 0) or from the right (dir != 0). */
3231 UInt max
= 0; /* number of vector elements */
3233 IRTemp cnt
[MAX_ELE
+1];
3234 IRTemp flag
[MAX_ELE
+1];
3235 IRTemp cmp_result
[MAX_ELE
];
3238 vassert(size
== Ity_I8
|| size
== Ity_I16
);
3240 if (size
== Ity_I8
) {
3247 num_bytes
= 2; // num bytes in half word
3250 cnt
[0] = newTemp(Ity_I8
);
3251 assign( cnt
[0], mkU8( 1 ) );
3252 flag
[0] = newTemp(Ity_I8
);
3253 assign( flag
[0], mkU8( 1 ) );
3255 for (i
= 0; i
< max
; i
++) {
3257 byte_index
= (max
- 1 - i
)*num_bytes
;
3259 byte_index
= i
*num_bytes
;
3262 cnt
[i
+1] = newTemp(Ity_I8
);
3263 cmp_result
[i
] = newTemp(Ity_I8
);
3264 flag
[i
+1] = newTemp(Ity_I8
);
3266 assign( cmp_result
[i
],
3272 extract_field_from_vector( src
,
3273 mkU64( byte_index
),
3276 assign( flag
[i
+1], binop( Iop_And8
,
3279 mkexpr( cmp_result
[i
] ) ) ) );
3281 // Once flag[i] becomes zero, it forces the increment to zero
3284 binop( Iop_And8
, mkexpr( flag
[i
+1] ), mkU8( 1 ) ),
3285 mkexpr( cnt
[i
] ) ) );
3287 return mkexpr( cnt
[max
] );
3291 /*-----------------------------------------------------------*/
3292 /*--- Prefix instruction helpers ---*/
3293 /*-----------------------------------------------------------*/
3294 #define DFORM_IMMASK 0xffffffff
3295 #define DSFORM_IMMASK 0xfffffffc
3296 #define DQFORM_IMMASK 0xfffffff0
3297 #define DA8LSFORM_IMMASK 0x3fffffff // Algebraic 8LS Dform
3299 #define ISA_3_1_PREFIX_CHECK if (prefix) {if (!allow_isa_3_1) goto decode_noIsa3_1;}
3301 /* ENABLE_PREFIX_CHECK is for development purposes. Turn off for production
3302 releases to improve performance. */
3303 #define ENABLE_PREFIX_CHECK 0
3305 #if ENABLE_PREFIX_CHECK
3306 #define PREFIX_CHECK { vassert( !prefix_instruction( prefix ) ); }
3308 #define PREFIX_CHECK { }
3311 /* Bits 0:5 of all prefix instructions are assigned the primary opcode
3312 value 0b000001. 0b000001 is not available for use as a primary opcode for
3313 either word instructions or suffixes of prefixed instructions. */
3315 #define PREFIX_INST 0x1
3316 #define PREFIX_NOP_INVALID -1
3318 #define CONCAT(_aa,_bb,_cc) ((_aa) << (_cc) | (_bb))
3320 /* The codes for the prefix types */
3321 #define pType0 0 /* Eight-Byte Load/Store Instructions */
3322 #define pType1 1 /* Eight-Byte Register-to-Register Instructions */
3323 #define pType2 2 /* Modified Load/Store Instructions */
3324 #define pType3 3 /* Modified Register-to-Register Instructions */
3326 /* Extract unsigned from prefix instr[17:0] */
3327 static UInt
ifieldUIMM18 ( UInt instr
) {
3328 return instr
& 0x3FFFF;
3331 static ULong
extend_s_34to64 ( ULong x
)
3333 return (ULong
)((((Long
)x
) << 30) >> 30);
3336 static UChar
PrefixType( UInt instr
) {
3337 return toUChar( IFIELD( instr
, 24, 2 ) );
3340 /* Extract XT 8RR D-form (destination register) field, instr[38:42] | [47] */
3341 static UChar
ifieldRegXT_8RR_D ( UInt instr
)
3343 UChar TX
= toUChar (IFIELD (instr
, (63 - 47), 1));
3344 UChar T
= toUChar (IFIELD (instr
, (63 - 42), 4));
3345 return (TX
<< 5) | T
;
3348 /* Extract immediate 8RR D-form prefix[16:31] or inst[48:63] */
3349 static UInt
ifield_imm_8RR_D ( UInt instr
)
3351 return IFIELD( instr
, 0, 16 );
3354 static UChar
ifieldR( UInt instr
) {
3355 return toUChar( IFIELD( instr
, 20, 1 ) );
3358 /* Sign extend imm34 -> IRExpr* */
3359 static IRExpr
* mkSzExtendS34 ( ULong imm64
)
3361 return ( mkU64(extend_s_34to64(imm64
)));
3364 /* Prefix instruction effective address calc: (rA + simm) */
3365 static IRExpr
* ea_rA_simm34 ( UInt rA
, ULong simm34
)
3369 return binop(Iop_Add64
, getIReg(rA
), mkSzExtendS34(simm34
));
3372 /* Standard prefix instruction effective address calc: (rA|0) + simm16 */
3373 static IRExpr
* ea_rAor0_simm34 ( UInt rA
, ULong simm34
)
3378 return mkSzExtendS34(simm34
);
3380 return ea_rA_simm34( rA
, simm34
);
3384 static int prefix_instruction ( UInt instr
)
3386 /* Format of first 4 bytes of prefix instruction
3387 bits [0:5] - must be 0x1 identifying this as a prefix inst
3388 bits [6:7] - prefix instruction type. */
3389 UChar opcode
= IFIELD( instr
, 26, 6);
3391 if (opcode
== PREFIX_INST
) return True
;
3395 /* standard offset calculation, check prefix type */
3396 static IRExpr
* calculate_prefix_EA ( UInt prefix
, UInt suffixInstr
,
3397 UChar rA_addr
, UInt ptype
,
3398 UInt immediate_mask
,
3399 ULong
*immediate_val
,
3402 IRType ty
= Ity_I64
;
3403 ULong d0
= ifieldUIMM18(prefix
); // Will be zero for word inst
3404 ULong d1
= ifieldUIMM16(suffixInstr
) & immediate_mask
;
3405 ULong D
= CONCAT( d0
, d1
, 16 ); // result is 34 bits wide
3406 Bool is_prefix
= prefix_instruction( prefix
);
3407 IRTemp tmp
= newTemp(ty
);
3410 *immediate_val
= extend_s_16to32( d1
);
3411 assign( tmp
, ea_rAor0_simm( rA_addr
, d1
) );
3415 vassert( ty
== Ity_I64
); // prefix instructions must be 64-bit
3416 vassert( (ptype
== pType0
) || (ptype
== pType2
) );
3417 *R
= ifieldR( prefix
);
3418 *immediate_val
= extend_s_34to64( D
); // D is 34 bits wide
3419 assign( tmp
, ea_rAor0_simm34( rA_addr
, D
) );
3424 return mkexpr ( tmp
);
3426 /* Add immediate value from instruction to the current instruction
3427 address. guest_CIA_curr_instr is pointing at the prefix, use address
3428 of the instruction prefix. */
3429 return binop( Iop_Add64
,
3431 mkU64( guest_CIA_curr_instr
) );
3434 /* Extract prefix intruction register fields 8RR:XX4-form */
3435 static UChar
ifieldRegXT_8RR_XX4 ( UInt instr
) {
3436 return toUChar( ( IFIELD( instr
, (63-63), 1) << 5)
3437 | ( IFIELD( instr
, (63-42), 5 ) ) ); // instr[38:42] | [63]
3440 static UChar
ifieldRegXA_8RR_XX4 ( UInt instr
) {
3441 return toUChar( ( IFIELD( instr
, (63-61), 1) << 5)
3442 | ( IFIELD( instr
, (63-47), 5 ) ) ); // instr[43:47] | [61]
3445 static UChar
ifieldRegXB_8RR_XX4 ( UInt instr
) {
3446 return toUChar( ( IFIELD( instr
, (63-62), 1) << 5)
3447 | ( IFIELD( instr
, (63-52), 5 ) ) ); // instr[48:52] | [62]
3450 static UChar
ifieldRegXC_8RR_XX4 ( UInt instr
) {
3451 return toUChar( ( IFIELD( instr
, (63-60), 1) << 5)
3452 | ( IFIELD( instr
, (63-57), 5 ) ) ); // instr[53:57] | [60]
3455 /*------------------------------------------------------------*/
3456 /*--- Read/write to guest-state --- */
3457 /*------------------------------------------------------------*/
3459 static IRExpr
* /* :: Ity_I32/64 */ getGST ( PPC_GST reg
)
3461 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
3463 case PPC_GST_SPRG3_RO
:
3464 return IRExpr_Get( OFFB_SPRG3_RO
, ty
);
3467 return IRExpr_Get( OFFB_CIA
, ty
);
3470 return IRExpr_Get( OFFB_LR
, ty
);
3473 return IRExpr_Get( OFFB_CTR
, ty
);
3475 case PPC_GST_VRSAVE
:
3476 return IRExpr_Get( OFFB_VRSAVE
, Ity_I32
);
3479 return binop(Iop_And32
, IRExpr_Get( OFFB_VSCR
,Ity_I32
),
3480 mkU32(MASK_VSCR_VALID
));
3483 /* Synthesise the entire CR into a single word. Expensive. */
3484 # define FIELD(_n) \
3488 binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \
3489 binop(Iop_And8, getCR0(_n), mkU8(1)) \
3492 mkU8(4 * (7-(_n))) \
3494 return binop(Iop_Or32
,
3496 binop(Iop_Or32
, FIELD(0), FIELD(1)),
3497 binop(Iop_Or32
, FIELD(2), FIELD(3))
3500 binop(Iop_Or32
, FIELD(4), FIELD(5)),
3501 binop(Iop_Or32
, FIELD(6), FIELD(7))
3508 return binop(Iop_Or32
,
3511 binop( Iop_Shl32
, getXER_SO_32(), mkU8(31)),
3512 binop( Iop_Shl32
, getXER_OV_32(), mkU8(30))),
3514 binop( Iop_Shl32
, getXER_CA_32(), mkU8(29)),
3517 binop( Iop_Shl32
, getXER_OV32_32(), mkU8(19)),
3518 binop( Iop_Shl32
, getXER_CA32_32(), mkU8(18))));
3521 return IRExpr_Get( OFFB_TFHAR
, ty
);
3523 case PPC_GST_TEXASR
:
3524 return IRExpr_Get( OFFB_TEXASR
, ty
);
3526 case PPC_GST_TEXASRU
:
3527 return IRExpr_Get( OFFB_TEXASRU
, ty
);
3530 return IRExpr_Get( OFFB_TFIAR
, ty
);
3533 return IRExpr_Get( OFFB_PPR
, ty
);
3536 return unop( Iop_64HIto32
, IRExpr_Get( OFFB_PPR
, ty
) );
3539 return IRExpr_Get( OFFB_PSPB
, ty
);
3542 return IRExpr_Get( OFFB_DSCR
, ty
);
3545 vex_printf("getGST(ppc): reg = %u", reg
);
3546 vpanic("getGST(ppc)");
3550 /* Get a masked word from the given reg */
3551 static IRExpr
* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg
, ULong mask
)
3553 IRTemp val
= newTemp(Ity_I32
);
3554 vassert( reg
< PPC_GST_MAX
);
3558 case PPC_GST_FPSCR
: {
3559 /* Vex-generated code expects the FPSCR to be set as follows:
3560 all exceptions masked, round-to-nearest.
3561 This corresponds to a FPSCR value of 0x0. */
3563 /* In the lower 32 bits of FPSCR, we're keeping track of the binary
3564 * floating point rounding mode and Floating-point Condition code, so
3565 * if the mask isn't asking for either of these, just return 0x0.
3567 if ( mask
& ( MASK_FPSCR_C_FPCC
| MASK_FPSCR_RN
) ) {
3568 assign( val
, binop( Iop_Or32
,
3569 unop( Iop_8Uto32
, IRExpr_Get( OFFB_FPROUND
, Ity_I8
) ),
3572 IRExpr_Get( OFFB_C_FPCC
, Ity_I8
) ),
3575 assign( val
, mkU32(0x0) );
3582 vex_printf("getGST_masked(ppc): reg = %u", reg
);
3583 vpanic("getGST_masked(ppc)");
3586 if ( mask
!= 0xFFFFFFFF ) {
3587 return binop(Iop_And32
, mkexpr(val
), mkU32(mask
));
3593 /* Get a masked word from the given reg */
3594 static IRExpr
* /* ::Ity_I32 */getGST_masked_upper(PPC_GST reg
, ULong mask
) {
3596 vassert( reg
< PPC_GST_MAX
);
3600 case PPC_GST_FPSCR
: {
3601 /* In the upper 32 bits of FPSCR, we're only keeping track
3602 * of the decimal floating point rounding mode, so if the mask
3603 * isn't asking for this, just return 0x0.
3605 if (mask
& MASK_FPSCR_DRN
) {
3606 val
= binop( Iop_And32
,
3607 unop( Iop_8Uto32
, IRExpr_Get( OFFB_DFPROUND
, Ity_I8
) ),
3608 unop( Iop_64HIto32
, mkU64( mask
) ) );
3610 val
= mkU32( 0x0ULL
);
3616 vex_printf( "getGST_masked_upper(ppc): reg = %u", reg
);
3617 vpanic( "getGST_masked_upper(ppc)" );
3623 /* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation)
3624 and return it at the bottom of an I32; the top 27 bits are
3625 guaranteed to be zero. */
3626 static IRExpr
* /* ::Ity_I32 */ getGST_field ( PPC_GST reg
, UInt fld
)
3631 vassert( reg
< PPC_GST_MAX
);
3639 return binop(Iop_Or32
,
3641 binop(Iop_Shl32
, getXER_SO_32(), mkU8(3)),
3642 binop(Iop_Shl32
, getXER_OV_32(), mkU8(2))),
3643 binop( Iop_Shl32
, getXER_CA_32(), mkU8(1)));
3648 return getGST_masked( reg
, mask
);
3650 return binop(Iop_Shr32
,
3651 getGST_masked( reg
, mask
),
3652 mkU8(toUChar( shft
)));
3656 static void putGST ( PPC_GST reg
, IRExpr
* src
)
3658 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
3659 IRType ty_src
= typeOfIRExpr(irsb
->tyenv
,src
);
3660 vassert( reg
< PPC_GST_MAX
);
3662 case PPC_GST_IP_AT_SYSCALL
:
3663 vassert( ty_src
== ty
);
3664 stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL
, src
) );
3667 vassert( ty_src
== ty
);
3668 stmt( IRStmt_Put( OFFB_CIA
, src
) );
3671 vassert( ty_src
== ty
);
3672 stmt( IRStmt_Put( OFFB_LR
, src
) );
3675 vassert( ty_src
== ty
);
3676 stmt( IRStmt_Put( OFFB_CTR
, src
) );
3678 case PPC_GST_VRSAVE
:
3679 vassert( ty_src
== Ity_I32
);
3680 stmt( IRStmt_Put( OFFB_VRSAVE
,src
));
3683 vassert( ty_src
== Ity_I32
);
3684 stmt( IRStmt_Put( OFFB_VSCR
,
3685 binop(Iop_And32
, src
,
3686 mkU32(MASK_VSCR_VALID
)) ) );
3689 vassert( ty_src
== Ity_I32
);
3690 putXER_SO( unop(Iop_32to8
, binop(Iop_Shr32
, src
, mkU8(31))) );
3691 putXER_OV( unop(Iop_32to8
, binop(Iop_Shr32
, src
, mkU8(30))) );
3692 putXER_CA( unop(Iop_32to8
, binop(Iop_Shr32
, src
, mkU8(29))) );
3693 putXER_OV32( unop(Iop_32to8
, binop(Iop_Shr32
, src
, mkU8(19))) );
3694 putXER_CA32( unop(Iop_32to8
, binop(Iop_Shr32
, src
, mkU8(18))) );
3695 putXER_BC( unop(Iop_32to8
, src
) );
3698 case PPC_GST_EMWARN
:
3699 vassert( ty_src
== Ity_I32
);
3700 stmt( IRStmt_Put( OFFB_EMNOTE
,src
) );
3703 case PPC_GST_CMSTART
:
3704 vassert( ty_src
== ty
);
3705 stmt( IRStmt_Put( OFFB_CMSTART
, src
) );
3709 vassert( ty_src
== ty
);
3710 stmt( IRStmt_Put( OFFB_CMLEN
, src
) );
3713 case PPC_GST_TEXASR
:
3714 vassert( ty_src
== Ity_I64
);
3715 stmt( IRStmt_Put( OFFB_TEXASR
, src
) );
3718 case PPC_GST_TEXASRU
:
3719 vassert( ty_src
== Ity_I32
);
3720 stmt( IRStmt_Put( OFFB_TEXASRU
, src
) );
3724 vassert( ty_src
== Ity_I64
);
3725 stmt( IRStmt_Put( OFFB_TFIAR
, src
) );
3728 vassert( ty_src
== Ity_I64
);
3729 stmt( IRStmt_Put( OFFB_TFHAR
, src
) );
3735 /* The Program Priority Register (PPR) stores the priority in
3736 * bits [52:50]. The user setable priorities are:
3744 * If the argument is not between 0b001 and 0b100 the priority is set
3745 * to 0b100. The priority can only be set to 0b101 if the the Problem
3746 * State Boost Register is non-zero. The value of the PPR is not
3747 * changed if the input is not valid.
3750 IRTemp not_valid
= newTemp(Ity_I64
);
3751 IRTemp has_perm
= newTemp(Ity_I64
);
3752 IRTemp new_src
= newTemp(Ity_I64
);
3753 IRTemp PSPB_val
= newTemp(Ity_I64
);
3754 IRTemp value
= newTemp(Ity_I64
);
3756 vassert(( ty_src
== Ity_I64
) || ( ty_src
== Ity_I32
));
3757 assign( PSPB_val
, binop( Iop_32HLto64
,
3759 IRExpr_Get( OFFB_PSPB
, Ity_I32
) ) );
3760 if( reg
== PPC_GST_PPR32
) {
3761 vassert( ty_src
== Ity_I32
);
3762 assign( value
, binop( Iop_32HLto64
,
3765 binop( Iop_Shr32
, src
, mkU8( 18 ) ),
3768 vassert( ty_src
== Ity_I64
);
3769 assign( value
, binop( Iop_And64
,
3770 binop( Iop_Shr64
, src
, mkU8( 50 ) ),
3782 mkexpr( value
) ) ) ) );
3790 binop( Iop_CmpLT64U
,
3792 mkexpr( value
) ) ) ) );
3797 mkexpr( not_valid
) ),
3800 mkexpr( not_valid
),
3808 IRExpr_Get( OFFB_PPR
, ty
),
3813 /* make sure we only set the valid bit field [52:50] */
3814 stmt( IRStmt_Put( OFFB_PPR
,
3817 mkU64( 0x1C000000000000) ) ) );
3821 vassert( ty_src
== Ity_I64
);
3822 stmt( IRStmt_Put( OFFB_DSCR
, src
) );
3826 vex_printf("putGST(ppc): reg = %u", reg
);
3827 vpanic("putGST(ppc)");
3831 /* Write masked src to the given reg */
3832 static void putGST_masked ( PPC_GST reg
, IRExpr
* src
, ULong mask
)
3834 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
3835 vassert( reg
< PPC_GST_MAX
);
3836 vassert( typeOfIRExpr( irsb
->tyenv
,src
) == Ity_I64
);
3839 case PPC_GST_FPSCR
: {
3840 /* Allow writes to either binary or decimal floating point
3843 /* If any part of |mask| covers FPSCR.RN, update the bits of
3844 FPSCR.RN by copying in |src| for locations where the
3845 corresponding bit in |mask| is 1, and leaving it unchanged
3846 for corresponding |mask| zero bits. */
3847 if (mask
& MASK_FPSCR_RN
) {
3857 unop(Iop_64to32
, src
),
3858 mkU32(MASK_FPSCR_RN
& mask
)
3862 unop(Iop_8Uto32
, IRExpr_Get(OFFB_FPROUND
,Ity_I8
)),
3863 mkU32(MASK_FPSCR_RN
& ~mask
)
3871 if (mask
& MASK_FPSCR_C_FPCC
) {
3872 /* FPCC bits are in [47:51] */
3883 unop(Iop_64to32
, src
),
3884 mkU32(MASK_FPSCR_C_FPCC
& mask
) ),
3888 IRExpr_Get(OFFB_C_FPCC
,Ity_I8
)),
3889 mkU32(MASK_FPSCR_C_FPCC
& ~mask
)
3895 /* Similarly, update FPSCR.DRN if any bits of |mask|
3896 corresponding to FPSCR.DRN are set. */
3897 if (mask
& MASK_FPSCR_DRN
) {
3907 unop(Iop_64HIto32
, src
),
3908 mkU32((MASK_FPSCR_DRN
& mask
) >> 32)
3912 unop(Iop_8Uto32
, IRExpr_Get(OFFB_DFPROUND
,Ity_I8
)),
3913 mkU32((MASK_FPSCR_DRN
& ~mask
) >> 32)
3921 /* Give EmNote for attempted writes to:
3922 - Exception Controls
3925 if (mask
& 0xFC) { // Exception Control, Non-IEE mode
3926 VexEmNote ew
= EmWarn_PPCexns
;
3928 /* If any of the src::exception_control bits are actually set,
3929 side-exit to the next insn, reporting the warning,
3930 so that Valgrind's dispatcher sees the warning. */
3931 putGST( PPC_GST_EMWARN
, mkU32(ew
) );
3934 binop(Iop_CmpNE32
, mkU32(ew
), mkU32(EmNote_NONE
)),
3936 mkSzConst( ty
, nextInsnAddr()), OFFB_CIA
));
3939 /* Ignore all other writes */
3944 vex_printf("putGST_masked(ppc): reg = %u", reg
);
3945 vpanic("putGST_masked(ppc)");
3949 /* Write the least significant nibble of src to the specified
3950 REG[FLD] (as per IBM/hardware notation). */
3951 static void putGST_field ( PPC_GST reg
, IRExpr
* src
, UInt fld
)
3956 vassert( typeOfIRExpr(irsb
->tyenv
,src
) == Ity_I32
);
3957 vassert( fld
< 16 );
3958 vassert( reg
< PPC_GST_MAX
);
3965 mask
= mask
<< shft
;
3969 putCR0 (fld
, binop(Iop_And8
, mkU8(1 ), unop(Iop_32to8
, src
)));
3970 putCR321(fld
, binop(Iop_And8
, mkU8(7<<1), unop(Iop_32to8
, src
)));
3975 IRExpr
* src64
= unop( Iop_32Uto64
, src
);
3978 putGST_masked( reg
, src64
, mask
);
3981 binop( Iop_Shl64
, src64
, mkU8( toUChar( shft
) ) ),
3988 static void putFPCC ( IRExpr
* e
)
3990 /* The assumption is that the value of the FPCC are passed in the lower
3991 * four bits of a 32 bit value.
3993 * Note, the C and FPCC bits which are a field of the FPSCR
3994 * register are stored in their own "register" in
3995 * memory. The FPCC bits are in the lower 4 bits. We don't need to
3996 * shift it to the bits to their location in the FPSCR register. Note,
3997 * not all of the FPSCR register bits are supported. We are writing all
3998 * of the bits in the FPCC field but not the C field.
4002 vassert( typeOfIRExpr( irsb
->tyenv
, e
) == Ity_I32
);
4003 /* Get the C bit field */
4004 tmp
= binop( Iop_And32
,
4006 unop( Iop_8Uto32
, IRExpr_Get( OFFB_C_FPCC
, Ity_I8
) ) );
4008 stmt( IRStmt_Put( OFFB_C_FPCC
,
4010 binop( Iop_Or32
, tmp
,
4011 binop( Iop_And32
, mkU32( 0xF ), e
) ) ) ) );
4015 static IRExpr
* /* ::Ity_I32 */ getC ( void )
4017 /* Note, the Floating-Point Result Class Descriptor (C) bit is a field of
4018 * the FPSCR registered are stored in its own "register" in guest state
4019 * with the FPCC bit field. C | FPCC
4021 IRTemp val
= newTemp(Ity_I32
);
4023 assign( val
, binop( Iop_Shr32
,
4024 unop( Iop_8Uto32
, IRExpr_Get( OFFB_C_FPCC
, Ity_I8
) ),
4029 static IRExpr
* /* ::Ity_I32 */ getFPCC ( void )
4031 /* Note, the FPCC bits are a field of the FPSCR
4032 * register are stored in their own "register" in
4033 * guest state with the C bit field. C | FPCC
4035 IRTemp val
= newTemp( Ity_I32
);
4037 assign( val
, binop( Iop_And32
, unop( Iop_8Uto32
,
4038 IRExpr_Get( OFFB_C_FPCC
, Ity_I8
) ),
4043 static void put_syscall_flag( IRExpr
* src
)
4045 /* Need to pass a flag indicating if the system call is using the sc or
4046 scv instructions. Because Valgrind does an end-of-block after the
4047 system call, the contents of a gpr can not be saved and restored after
4048 the system call. A custom guest state register guest_syscall_flag is
4049 used to pass the flag so the guest state is not disturbed. */
4051 stmt( IRStmt_Put( offsetofPPCGuestState(guest_syscall_flag
), src
) );
4055 /*-----------------------------------------------------------*/
4056 /* Helpers to access VSX Accumulator register file
4057 *-----------------------------------------------------------*/
4058 static UInt
ACC_offset( UInt index
, UInt reg
)
4060 #define SizeofACC_row 16 /* size of ACC row in bytes */
4061 #define ACC_row_per_entry 4
4062 #define ACC_num_entries 8
4064 vassert(index
< ACC_num_entries
);
4065 vassert(reg
< ACC_row_per_entry
);
4066 return index
* ACC_row_per_entry
* SizeofACC_row
+ reg
* SizeofACC_row
;
4069 static UInt
base_acc_addr( Bool ACC_mapped_on_VSR
)
4071 /* Return base ACC address if ACC mapped over vsrs or as a separate
4073 if ( ACC_mapped_on_VSR
) /* ISA 3.1 implementation */
4074 return offsetofPPCGuestState( guest_VSR0
);
4076 return offsetofPPCGuestState( guest_ACC_0_r0
);
4079 static void putACC( UInt index
, UInt reg
, IRExpr
* src
, Bool ACC_mapped_on_VSR
)
4082 stmt( IRStmt_Put( base_acc_addr( ACC_mapped_on_VSR
)
4083 + ACC_offset( index
, reg
), src
) );
4086 static IRExpr
* /* :: Ity_V128 */ getACC ( UInt index
, UInt reg
,
4087 Bool ACC_mapped_on_VSR
)
4089 vassert( (index
>= 0) && (index
< 8) );
4090 vassert( (reg
>= 0) && (reg
< 4) );
4092 return IRExpr_Get( base_acc_addr( ACC_mapped_on_VSR
)
4093 + ACC_offset( index
, reg
), Ity_V128
);
4097 /*------------------------------------------------------------*/
4098 /* Helpers for VSX instructions that do floating point
4099 * operations and need to determine if a src contains a
4102 *------------------------------------------------------------*/
4104 #define NONZERO_FRAC_MASK 0x000fffffffffffffULL
4105 #define FP_FRAC_PART(x) binop( Iop_And64, \
4107 mkU64( NONZERO_FRAC_MASK ) )
4109 #define NONZERO_FRAC_MASK32 0x007fffffULL
4110 #define FP_FRAC_PART32(x) binop( Iop_And32, \
4112 mkU32( NONZERO_FRAC_MASK32 ) )
4114 // Returns exponent part of floating point src as I32
4115 static IRExpr
* fp_exp_part( IRType size
, IRTemp src
)
4117 IRExpr
*shift_by
, *mask
, *tsrc
;
4119 vassert( ( size
== Ity_I16
) || ( size
== Ity_I32
)
4120 || ( size
== Ity_I64
) );
4122 if( size
== Ity_I16
) {
4123 /* The 16-bit floating point value is in the lower 16-bits
4124 * of the 32-bit input value.
4126 tsrc
= mkexpr( src
);
4127 mask
= mkU32( 0x1F );
4128 shift_by
= mkU8( 10 );
4130 } else if( size
== Ity_I32
) {
4131 tsrc
= mkexpr( src
);
4132 mask
= mkU32( 0xFF );
4133 shift_by
= mkU8( 23 );
4135 } else if( size
== Ity_I64
) {
4136 tsrc
= unop( Iop_64HIto32
, mkexpr( src
) );
4137 mask
= mkU32( 0x7FF );
4138 shift_by
= mkU8( 52 - 32 );
4142 vassert(0); // Stops gcc complaining at "-Og"
4145 return binop( Iop_And32
, binop( Iop_Shr32
, tsrc
, shift_by
), mask
);
4148 /* The following functions check the floating point value to see if it
4149 is zero, infinity, NaN, Normalized, Denormalized.
4151 /* 16-bit floating point number is stored in the lower 16-bits of 32-bit value */
4152 #define I16_EXP_MASK 0x7C00
4153 #define I16_FRACTION_MASK 0x03FF
4154 #define I16_MSB_FRACTION_MASK 0x0200
4155 #define I32_EXP_MASK 0x7F800000
4156 #define I32_FRACTION_MASK 0x007FFFFF
4157 #define I32_MSB_FRACTION_MASK 0x00400000
4158 #define I32_SIGN_MASK 0x80000000
4159 #define I64_EXP_MASK 0x7FF0000000000000ULL
4160 #define I64_FRACTION_MASK 0x000FFFFFFFFFFFFFULL
4161 #define I64_MSB_FRACTION_MASK 0x0008000000000000ULL
4162 #define V128_EXP_MASK 0x7FFF000000000000ULL
4163 #define V128_FRACTION_MASK 0x0000FFFFFFFFFFFFULL /* upper 64-bit fractional mask */
4164 #define V128_MSB_FRACTION_MASK 0x0000800000000000ULL /* upper 64-bit fractional mask */
4166 void setup_value_check_args( IRType size
, IRTemp
*exp_mask
, IRTemp
*frac_mask
,
4167 IRTemp
*msb_frac_mask
, IRTemp
*zero
);
4169 void setup_value_check_args( IRType size
, IRTemp
*exp_mask
, IRTemp
*frac_mask
,
4170 IRTemp
*msb_frac_mask
, IRTemp
*zero
) {
4172 vassert( ( size
== Ity_I16
) || ( size
== Ity_I32
)
4173 || ( size
== Ity_I64
) || ( size
== Ity_V128
) );
4175 if( size
== Ity_I16
) {
4176 /* The 16-bit floating point value is in the lower 16-bits of
4177 the 32-bit input value */
4178 *frac_mask
= newTemp( Ity_I32
);
4179 *msb_frac_mask
= newTemp( Ity_I32
);
4180 *exp_mask
= newTemp( Ity_I32
);
4181 *zero
= newTemp( Ity_I32
);
4182 assign( *exp_mask
, mkU32( I16_EXP_MASK
) );
4183 assign( *frac_mask
, mkU32( I16_FRACTION_MASK
) );
4184 assign( *msb_frac_mask
, mkU32( I16_MSB_FRACTION_MASK
) );
4185 assign( *zero
, mkU32( 0 ) );
4187 } else if( size
== Ity_I32
) {
4188 *frac_mask
= newTemp( Ity_I32
);
4189 *msb_frac_mask
= newTemp( Ity_I32
);
4190 *exp_mask
= newTemp( Ity_I32
);
4191 *zero
= newTemp( Ity_I32
);
4192 assign( *exp_mask
, mkU32( I32_EXP_MASK
) );
4193 assign( *frac_mask
, mkU32( I32_FRACTION_MASK
) );
4194 assign( *msb_frac_mask
, mkU32( I32_MSB_FRACTION_MASK
) );
4195 assign( *zero
, mkU32( 0 ) );
4197 } else if( size
== Ity_I64
) {
4198 *frac_mask
= newTemp( Ity_I64
);
4199 *msb_frac_mask
= newTemp( Ity_I64
);
4200 *exp_mask
= newTemp( Ity_I64
);
4201 *zero
= newTemp( Ity_I64
);
4202 assign( *exp_mask
, mkU64( I64_EXP_MASK
) );
4203 assign( *frac_mask
, mkU64( I64_FRACTION_MASK
) );
4204 assign( *msb_frac_mask
, mkU64( I64_MSB_FRACTION_MASK
) );
4205 assign( *zero
, mkU64( 0 ) );
4208 /* V128 is converted to upper and lower 64 bit values, */
4209 /* uses 64-bit operators and temps */
4210 *frac_mask
= newTemp( Ity_I64
);
4211 *msb_frac_mask
= newTemp( Ity_I64
);
4212 *exp_mask
= newTemp( Ity_I64
);
4213 *zero
= newTemp( Ity_I64
);
4214 assign( *exp_mask
, mkU64( V128_EXP_MASK
) );
4215 /* upper 64-bit fractional mask */
4216 assign( *frac_mask
, mkU64( V128_FRACTION_MASK
) );
4217 assign( *msb_frac_mask
, mkU64( V128_MSB_FRACTION_MASK
) );
4218 assign( *zero
, mkU64( 0 ) );
4222 /* Helper function for the various function which check the value of
4223 the floating point value.
4225 static IRExpr
* exponent_compare( IRType size
, IRTemp src
,
4226 IRTemp exp_mask
, IRExpr
*exp_val
)
4228 IROp opAND
, opCmpEQ
;
4230 if( ( size
== Ity_I16
) || ( size
== Ity_I32
) ) {
4231 /* The 16-bit floating point value is in the lower 16-bits of
4232 the 32-bit input value */
4234 opCmpEQ
= Iop_CmpEQ32
;
4238 opCmpEQ
= Iop_CmpEQ64
;
4241 if( size
== Ity_V128
) {
4242 return binop( opCmpEQ
,
4244 unop( Iop_V128HIto64
, mkexpr( src
) ),
4245 mkexpr( exp_mask
) ),
4248 } else if( ( size
== Ity_I16
) || ( size
== Ity_I32
) ) {
4249 return binop( opCmpEQ
,
4250 binop ( opAND
, mkexpr( src
), mkexpr( exp_mask
) ),
4253 /* 64-bit operands */
4256 return binop( opCmpEQ
,
4257 binop ( opAND
, mkexpr( src
), mkexpr( exp_mask
) ),
4260 /* No support for 64-bit compares in 32-bit mode, need to do upper
4261 * and lower parts using 32-bit compare operators.
4264 mkAND1( binop( Iop_CmpEQ32
,
4266 unop(Iop_64HIto32
, mkexpr( src
) ),
4267 unop(Iop_64HIto32
, mkexpr( exp_mask
) ) ),
4268 unop(Iop_64HIto32
, exp_val
) ),
4271 unop(Iop_64to32
, mkexpr( src
) ),
4272 unop(Iop_64to32
, mkexpr( exp_mask
) ) ),
4273 unop(Iop_64to32
, exp_val
) ) );
4278 static IRExpr
*fractional_part_compare( IRType size
, IRTemp src
,
4279 IRTemp frac_mask
, IRExpr
*zero
)
4281 IROp opAND
, opCmpEQ
;
4283 if( ( size
== Ity_I16
) || ( size
== Ity_I32
) ) {
4284 /*The 16-bit floating point value is in the lower 16-bits of
4285 the 32-bit input value */
4287 opCmpEQ
= Iop_CmpEQ32
;
4291 opCmpEQ
= Iop_CmpEQ64
;
4294 if( size
== Ity_V128
) {
4295 /* 128-bit, note we only care if the fractional part is zero so take upper
4296 52-bits of fractional part and lower 64-bits and OR them together and test
4297 for zero. This keeps the temp variables and operators all 64-bit.
4299 return binop( opCmpEQ
,
4302 unop( Iop_V128HIto64
, mkexpr( src
) ),
4303 mkexpr( frac_mask
) ),
4304 unop( Iop_V128to64
, mkexpr( src
) ) ),
4307 } else if( ( size
== Ity_I16
) || ( size
== Ity_I32
) ) {
4308 return binop( opCmpEQ
,
4309 binop( opAND
, mkexpr( src
), mkexpr( frac_mask
) ),
4313 return binop( opCmpEQ
,
4314 binop( opAND
, mkexpr( src
), mkexpr( frac_mask
) ),
4317 /* No support for 64-bit compares in 32-bit mode, need to do upper
4318 * and lower parts using 32-bit compare operators.
4321 mkAND1( binop( Iop_CmpEQ32
,
4323 unop(Iop_64HIto32
, mkexpr( src
) ),
4324 unop(Iop_64HIto32
, mkexpr( frac_mask
) ) ),
4328 unop(Iop_64to32
, mkexpr( src
) ),
4329 unop(Iop_64to32
, mkexpr( frac_mask
) ) ),
4335 // Infinity: exp has all bits set, and fraction is zero; s = 0/1
4336 static IRExpr
* is_Inf( IRType size
, IRTemp src
)
4338 IRExpr
*max_exp
, *zero_frac
;
4339 IRTemp exp_mask
, frac_mask
, msb_frac_mask
, zero
;
4341 setup_value_check_args( size
, &exp_mask
, &frac_mask
, &msb_frac_mask
,
4344 /* check exponent is all ones, i.e. (exp AND exp_mask) = exp_mask */
4345 max_exp
= exponent_compare( size
, src
, exp_mask
, mkexpr( exp_mask
) );
4347 /* check fractional part is all zeros */
4348 zero_frac
= fractional_part_compare( size
, src
, frac_mask
, mkexpr( zero
) );
4350 return mkAND1( max_exp
, zero_frac
);
4353 // Zero: exp is zero and fraction is zero; s = 0/1
4354 static IRExpr
* is_Zero( IRType size
, IRTemp src
)
4356 IRExpr
*zero_exp
, *zero_frac
;
4357 IRTemp exp_mask
, frac_mask
, msb_frac_mask
, zero
;
4359 setup_value_check_args( size
, &exp_mask
, &frac_mask
, &msb_frac_mask
,
4362 /* check the exponent is all zeros, i.e. (exp AND exp_mask) = zero */
4363 zero_exp
= exponent_compare( size
, src
, exp_mask
, mkexpr( zero
) );
4365 /* check fractional part is all zeros */
4366 zero_frac
= fractional_part_compare( size
, src
, frac_mask
, mkexpr( zero
) );
4368 return mkAND1( zero_exp
, zero_frac
);
4371 /* SNAN: s = 1/0; exp all 1's; fraction is nonzero, with highest bit '1'
4372 * QNAN: s = 1/0; exp all 1's; fraction is nonzero, with highest bit '0'
4374 static IRExpr
* is_NaN( IRType size
, IRTemp src
)
4376 IRExpr
*max_exp
, *not_zero_frac
;
4377 IRTemp exp_mask
, frac_mask
, msb_frac_mask
, zero
;
4379 setup_value_check_args( size
, &exp_mask
, &frac_mask
, &msb_frac_mask
,
4382 /* check exponent is all ones, i.e. (exp AND exp_mask) = exp_mask */
4383 max_exp
= exponent_compare( size
, src
, exp_mask
, mkexpr( exp_mask
) );
4385 /* check fractional part is not zero */
4386 not_zero_frac
= unop( Iop_Not1
,
4387 fractional_part_compare( size
, src
, frac_mask
,
4390 return mkAND1( max_exp
, not_zero_frac
);
4393 static IRExpr
* is_sNaN( IRType size
, IRTemp src
)
4395 IRExpr
*max_exp
, *not_zero_frac
, *msb_zero
;
4396 IRTemp exp_mask
, frac_mask
, msb_frac_mask
, zero
;
4398 setup_value_check_args( size
, &exp_mask
, &frac_mask
, &msb_frac_mask
,
4401 /* check exponent is all ones, i.e. (exp AND exp_mask) = exp_mask */
4402 max_exp
= exponent_compare( size
, src
, exp_mask
, mkexpr( exp_mask
) );
4404 /* Most significant fractional bit is zero for sNaN */
4405 msb_zero
= fractional_part_compare ( size
, src
, msb_frac_mask
,
4408 /* check fractional part is not zero */
4409 not_zero_frac
= unop( Iop_Not1
,
4410 fractional_part_compare( size
, src
, frac_mask
,
4413 return mkAND1( msb_zero
, mkAND1( max_exp
, not_zero_frac
) );
4416 /* Denormalized number has a zero exponent and non zero fraction. */
4417 static IRExpr
* is_Denorm( IRType size
, IRTemp src
)
4419 IRExpr
*zero_exp
, *not_zero_frac
;
4420 IRTemp exp_mask
, frac_mask
, msb_frac_mask
, zero
;
4422 setup_value_check_args( size
, &exp_mask
, &frac_mask
, &msb_frac_mask
,
4425 /* check exponent is all zeros */
4426 zero_exp
= exponent_compare( size
, src
, exp_mask
, mkexpr( zero
) );
4428 /* check fractional part is not zero */
4429 not_zero_frac
= unop( Iop_Not1
,
4430 fractional_part_compare( size
, src
, frac_mask
,
4433 return mkAND1( zero_exp
, not_zero_frac
);
4436 static IRExpr
* is_Zero_Vector( IRType element_size
, IRExpr
*src
)
4438 /* Check elements of a 128-bit floating point vector, with element size are
4439 zero. Return 1's in the elements of the vector which are values. */
4440 IRTemp exp_maskV128
= newTemp( Ity_V128
);
4441 IRTemp exp_zeroV128
= newTemp( Ity_V128
);
4442 IRTemp frac_maskV128
= newTemp( Ity_V128
);
4443 IRTemp frac_zeroV128
= newTemp( Ity_V128
);
4444 IRTemp zeroV128
= newTemp( Ity_V128
);
4446 assign( zeroV128
, mkV128( 0 ) );
4448 if ( element_size
== Ity_I32
) {
4449 assign( exp_maskV128
, unop( Iop_Dup32x4
, mkU32( I32_EXP_MASK
) ) );
4450 assign( frac_maskV128
, unop( Iop_Dup32x4
, mkU32( I32_FRACTION_MASK
) ) );
4453 vpanic("ERROR, is_Zero_Vector: Unknown input size");
4455 /* CmpEQ32x4 returns all 1's in elements where comparison is true */
4456 assign( exp_zeroV128
,
4457 binop( Iop_CmpEQ32x4
,
4459 mkexpr( exp_maskV128
), src
),
4460 mkexpr( zeroV128
) ) );
4462 assign( frac_zeroV128
,
4463 binop( Iop_CmpEQ32x4
,
4465 mkexpr( frac_maskV128
), src
),
4466 mkexpr( zeroV128
) ) );
4468 return binop( Iop_AndV128
, mkexpr( exp_zeroV128
),
4469 mkexpr( frac_zeroV128
) );
4472 static IRExpr
* Abs_Zero_Vector( IRType element_size
, IRExpr
*src
)
4473 /* Vector of four 32-bit elements, convert any negative zeros to
4476 IRTemp result
= newTemp( Ity_V128
);
4478 if ( element_size
== Ity_I32
) {
4479 assign( result
, binop( Iop_AndV128
,
4482 is_Zero_Vector( element_size
, src
) ) ) );
4484 vex_printf("ERROR, Abs_Zero_Vector: Unknown input size\n");
4486 return mkexpr( result
);
4489 static IRExpr
* is_Denorm_Vector( IRType element_size
, IRExpr
*src
)
4491 /* Check elements of a 128-bit floating point vector, with element size
4492 element_size, are Denorm. Return 1's in the elements of the vector
4493 which are denormalized values. */
4494 IRTemp exp_maskV128
= newTemp( Ity_V128
);
4495 IRTemp exp_zeroV128
= newTemp( Ity_V128
);
4496 IRTemp frac_maskV128
= newTemp( Ity_V128
);
4497 IRTemp frac_nonzeroV128
= newTemp( Ity_V128
);
4498 IRTemp zeroV128
= newTemp( Ity_V128
);
4500 assign( zeroV128
, mkV128(0 ) );
4502 if ( element_size
== Ity_I32
) {
4503 assign( exp_maskV128
, unop( Iop_Dup32x4
, mkU32( I32_EXP_MASK
) ) );
4504 assign( frac_maskV128
, unop( Iop_Dup32x4
, mkU32( I32_FRACTION_MASK
) ) );
4507 vpanic("ERROR, is_Denorm_Vector: Unknown input size");
4509 /* CmpEQ32x4 returns all 1's in elements where comparison is true */
4510 assign( exp_zeroV128
,
4511 binop( Iop_CmpEQ32x4
,
4513 mkexpr( exp_maskV128
), src
),
4514 mkexpr( zeroV128
) ) );
4516 assign( frac_nonzeroV128
,
4518 binop( Iop_CmpEQ32x4
,
4520 mkexpr( frac_maskV128
), src
),
4521 mkexpr( zeroV128
) ) ) );
4523 return binop( Iop_AndV128
, mkexpr( exp_zeroV128
),
4524 mkexpr( frac_nonzeroV128
) );
4527 static IRExpr
* is_NaN_Vector( IRType element_size
, IRExpr
*src
)
4529 IRTemp max_expV128
= newTemp( Ity_V128
);
4530 IRTemp not_zero_fracV128
= newTemp( Ity_V128
);
4531 IRTemp zeroV128
= newTemp( Ity_V128
);
4532 IRTemp exp_maskV128
= newTemp( Ity_V128
);
4533 IRTemp frac_maskV128
= newTemp( Ity_V128
);
4534 IROp opCmpEQ
= Iop_INVALID
;
4536 assign( zeroV128
, mkV128( 0 ) );
4538 if ( element_size
== Ity_I32
) {
4539 assign( exp_maskV128
, unop( Iop_Dup32x4
, mkU32( I32_EXP_MASK
) ) );
4540 assign( frac_maskV128
, unop( Iop_Dup32x4
, mkU32( I32_FRACTION_MASK
) ) );
4541 opCmpEQ
= Iop_CmpEQ32x4
;
4544 vpanic("ERROR, is_NaN_Vector: Unknown input size");
4546 /* check exponent is all ones, i.e. (exp AND exp_mask) = exp_mask */
4547 assign( max_expV128
,
4549 binop( Iop_AndV128
, src
, mkexpr( exp_maskV128
) ),
4550 mkexpr( exp_maskV128
) ) );
4552 /* check fractional part is not zero */
4553 assign( not_zero_fracV128
,
4556 binop( Iop_AndV128
, src
, mkexpr( frac_maskV128
) ),
4557 mkexpr( zeroV128
) ) ) );
4559 return binop( Iop_AndV128
, mkexpr( max_expV128
),
4560 mkexpr( not_zero_fracV128
) );
4564 /* Normalized number has exponent between 1 and max_exp -1, or in other words
4565 the exponent is not zero and not equal to the max exponent value. */
4566 Currently
not needed since generate_C_FPCC is now done with a C helper
.
4567 Keep it around
, might be useful in the future
.
4568 static IRExpr
* is_Norm( IRType size
, IRTemp src
)
4570 IRExpr
*not_zero_exp
, *not_max_exp
;
4571 IRTemp exp_mask
, zero
;
4573 vassert( ( size
== Ity_I16
) || ( size
== Ity_I32
)
4574 || ( size
== Ity_I64
) || ( size
== Ity_V128
) );
4576 if( size
== Ity_I16
) {
4577 /* The 16-bit floating point value is in the lower 16-bits of
4578 the 32-bit input value */
4579 exp_mask
= newTemp( Ity_I32
);
4580 zero
= newTemp( Ity_I32
);
4581 assign( exp_mask
, mkU32( I16_EXP_MASK
) );
4582 assign( zero
, mkU32( 0 ) );
4584 } else if( size
== Ity_I32
) {
4585 exp_mask
= newTemp( Ity_I32
);
4586 zero
= newTemp( Ity_I32
);
4587 assign( exp_mask
, mkU32( I32_EXP_MASK
) );
4588 assign( zero
, mkU32( 0 ) );
4590 } else if( size
== Ity_I64
) {
4591 exp_mask
= newTemp( Ity_I64
);
4592 zero
= newTemp( Ity_I64
);
4593 assign( exp_mask
, mkU64( I64_EXP_MASK
) );
4594 assign( zero
, mkU64( 0 ) );
4597 /* V128 is converted to upper and lower 64 bit values, */
4598 /* uses 64-bit operators and temps */
4599 exp_mask
= newTemp( Ity_I64
);
4600 zero
= newTemp( Ity_I64
);
4601 assign( exp_mask
, mkU64( V128_EXP_MASK
) );
4602 assign( zero
, mkU64( 0 ) );
4605 not_zero_exp
= unop( Iop_Not1
,
4606 exponent_compare( size
, src
,
4607 exp_mask
, mkexpr( zero
) ) );
4608 not_max_exp
= unop( Iop_Not1
,
4609 exponent_compare( size
, src
,
4610 exp_mask
, mkexpr( exp_mask
) ) );
4612 return mkAND1( not_zero_exp
, not_max_exp
);
4616 static void generate_store_FPRF( IRType size
, IRTemp src
,
4617 const VexAbiInfo
* vbi
)
4620 /* This function was originally written using IR code. It has been
4621 * replaced with a clean helper due to the large amount of IR code
4622 * needed by this function.
4625 IRTemp tmp
= newTemp( Ity_I64
);
4626 vassert( ( size
== Ity_I16
) || ( size
== Ity_I32
)
4627 || ( size
== Ity_I64
) || ( size
== Ity_F128
) );
4629 vassert( ( typeOfIRExpr(irsb
->tyenv
, mkexpr( src
) ) == Ity_I32
)
4630 || ( typeOfIRExpr(irsb
->tyenv
, mkexpr( src
) ) == Ity_I64
)
4631 || ( typeOfIRExpr(irsb
->tyenv
, mkexpr( src
) ) == Ity_F128
) );
4633 if( size
== Ity_I16
) {
4635 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
4636 "generate_store_C_FPCC_helper",
4637 fnptr_to_fnentry( vbi
, &generate_C_FPCC_helper
),
4638 mkIRExprVec_3( mkU64( size
), mkU64( 0 ),
4639 mkexpr( src
) ) ) );
4640 } else if( size
== Ity_I32
) {
4642 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
4643 "generate_store_C_FPCC_helper",
4644 fnptr_to_fnentry( vbi
, &generate_C_FPCC_helper
),
4645 mkIRExprVec_3( mkU64( size
), mkU64( 0 ),
4646 mkexpr( src
) ) ) );
4647 } else if( size
== Ity_I64
) {
4649 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
4650 "generate_store_C_FPCC_helper",
4651 fnptr_to_fnentry( vbi
, &generate_C_FPCC_helper
),
4652 mkIRExprVec_3( mkU64( size
), mkU64( 0 ),
4653 mkexpr( src
) ) ) );
4654 } else if( size
== Ity_F128
) {
4656 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
4657 "generate_store_C_FPCC_helper",
4658 fnptr_to_fnentry( vbi
, &generate_C_FPCC_helper
),
4659 mkIRExprVec_3( mkU64( size
),
4660 unop( Iop_ReinterpF64asI64
,
4661 unop( Iop_F128HItoF64
,
4663 unop( Iop_ReinterpF64asI64
,
4664 unop( Iop_F128LOtoF64
,
4665 mkexpr( src
) ) ) ) ) );
4668 /* C is in the upper 32-bits, FPCC is in the lower 32-bits of the
4669 * value returned by the helper function
4671 putC( unop( Iop_64HIto32
, mkexpr( tmp
) ) );
4672 putFPCC( unop( Iop_64to32
, mkexpr( tmp
) ) );
4675 /* This function takes an Ity_I32 input argument interpreted
4676 as a single-precision floating point value. If src is a
4677 SNaN, it is changed to a QNaN and returned; otherwise,
4678 the original value is returned. */
4679 static IRExpr
* handle_SNaN_to_QNaN_32(IRExpr
* src
)
4681 #define SNAN_MASK32 0x00400000
4682 IRTemp tmp
= newTemp(Ity_I32
);
4683 IRTemp mask
= newTemp(Ity_I32
);
4684 IRTemp is_SNAN
= newTemp(Ity_I1
);
4686 vassert( typeOfIRExpr(irsb
->tyenv
, src
) == Ity_I32
);
4689 /* check if input is SNaN, if it is convert to QNaN */
4691 mkAND1( is_NaN( Ity_I32
, tmp
),
4693 binop( Iop_And32
, mkexpr( tmp
),
4694 mkU32( SNAN_MASK32
) ),
4696 /* create mask with QNaN bit set to make it a QNaN if tmp is SNaN */
4697 assign ( mask
, binop( Iop_And32
,
4698 unop( Iop_1Sto32
, mkexpr( is_SNAN
) ),
4699 mkU32( SNAN_MASK32
) ) );
4700 return binop( Iop_Or32
, mkexpr( mask
), mkexpr( tmp
) );
4704 /* This helper function performs the negation part of operations of the form:
4705 * "Negate Multiply-<op>"
4706 * where "<op>" is either "Add" or "Sub".
4708 * This function takes one argument -- the floating point intermediate result (converted to
4709 * Ity_I64 via Iop_ReinterpF64asI64) that was obtained from the "Multip-<op>" part of
4710 * the operation described above.
4712 static IRTemp
getNegatedResult(IRTemp intermediateResult
)
4714 ULong signbit_mask
= 0x8000000000000000ULL
;
4715 IRTemp signbit_32
= newTemp(Ity_I32
);
4716 IRTemp resultantSignbit
= newTemp(Ity_I1
);
4717 IRTemp negatedResult
= newTemp(Ity_I64
);
4718 assign( signbit_32
, binop( Iop_Shr32
,
4720 binop( Iop_And64
, mkexpr( intermediateResult
),
4721 mkU64( signbit_mask
) ) ),
4723 /* We negate the signbit if and only if the intermediate result from the
4724 * multiply-<op> was NOT a NaN. This is an XNOR predicate.
4726 assign( resultantSignbit
,
4730 mkexpr( signbit_32
),
4731 unop( Iop_1Uto32
, is_NaN( Ity_I64
,
4732 intermediateResult
) ) ),
4735 assign( negatedResult
,
4738 mkexpr( intermediateResult
),
4739 mkU64( ~signbit_mask
) ),
4740 binop( Iop_32HLto64
,
4742 unop( Iop_1Uto32
, mkexpr( resultantSignbit
) ),
4746 return negatedResult
;
4749 /* This helper function performs the negation part of operations of the form:
4750 * "Negate Multiply-<op>"
4751 * where "<op>" is either "Add" or "Sub".
4753 * This function takes one argument -- the floating point intermediate result (converted to
4754 * Ity_I32 via Iop_ReinterpF32asI32) that was obtained from the "Multip-<op>" part of
4755 * the operation described above.
4757 static IRTemp
getNegatedResult_32(IRTemp intermediateResult
)
4759 UInt signbit_mask
= 0x80000000;
4760 IRTemp signbit_32
= newTemp(Ity_I32
);
4761 IRTemp resultantSignbit
= newTemp(Ity_I1
);
4762 IRTemp negatedResult
= newTemp(Ity_I32
);
4763 assign( signbit_32
, binop( Iop_Shr32
,
4764 binop( Iop_And32
, mkexpr( intermediateResult
),
4765 mkU32( signbit_mask
) ),
4767 /* We negate the signbit if and only if the intermediate result from the
4768 * multiply-<op> was NOT a NaN. This is an XNOR predicate.
4770 assign( resultantSignbit
,
4774 mkexpr( signbit_32
),
4775 unop( Iop_1Uto32
, is_NaN( Ity_I32
,
4776 intermediateResult
) ) ),
4779 assign( negatedResult
,
4782 mkexpr( intermediateResult
),
4783 mkU32( ~signbit_mask
) ),
4785 unop( Iop_1Uto32
, mkexpr( resultantSignbit
) ),
4788 return negatedResult
;
4791 static IRExpr
* negate_Vector ( IRType element_size
, IRExpr
* value
)
4793 /* This function takes a vector of floats. If the value is
4794 not a NaN, the value is negated. */
4796 IRTemp not_nan_mask
= newTemp( Ity_V128
);
4797 IRTemp sign_maskV128
= newTemp( Ity_V128
);
4799 if ( element_size
== Ity_I32
) {
4800 assign( sign_maskV128
, unop( Iop_Dup32x4
, mkU32( I32_SIGN_MASK
) ) );
4803 vpanic("ERROR, negate_Vector: Unknown input size");
4805 /* Determine if vector elementes are not a NaN, negate sign bit
4806 for non NaN elements */
4807 assign ( not_nan_mask
,
4808 unop( Iop_NotV128
, is_NaN_Vector( element_size
, value
) ) );
4810 return binop( Iop_XorV128
,
4812 mkexpr( sign_maskV128
), mkexpr( not_nan_mask
) ),
4816 /* This function takes two quad_precision unsigned/signed integers of type
4817 V128 and return 1 (Ity_Bit) if src_A = src_B, 0 otherwise. */
4818 static IRExpr
* Quad_precision_int_eq ( IRTemp src_A
, IRTemp src_B
)
4820 return mkAND1( binop( Iop_CmpEQ64
,
4821 unop( Iop_V128HIto64
, mkexpr( src_A
) ),
4822 unop( Iop_V128HIto64
, mkexpr( src_B
) ) ),
4824 unop( Iop_V128to64
, mkexpr( src_A
) ),
4825 unop( Iop_V128to64
, mkexpr( src_B
) ) ) );
4828 /* This function takes two quad_precision unsigned integers of type
4829 V128 and return 1 if src_A > src_B, 0 otherwise. */
4830 static IRExpr
* Quad_precision_uint_gt ( IRTemp src_A
, IRTemp src_B
)
4832 IRExpr
* hi_eq
= binop( Iop_CmpEQ64
,
4833 unop( Iop_V128HIto64
, mkexpr( src_A
) ),
4834 unop( Iop_V128HIto64
, mkexpr( src_B
) ) );
4836 IRExpr
* hi_gt
= binop( Iop_CmpLT64U
,
4837 unop( Iop_V128HIto64
, mkexpr( src_B
) ),
4838 unop( Iop_V128HIto64
, mkexpr( src_A
) ) );
4840 IRExpr
* lo_gt
= binop( Iop_CmpLT64U
,
4841 unop( Iop_V128to64
, mkexpr( src_B
) ),
4842 unop( Iop_V128to64
, mkexpr( src_A
) ) );
4844 return mkOR1( hi_gt
, mkAND1( hi_eq
, lo_gt
) );
4847 /* This function takes two quad_precision signed integers of type
4848 V128 and return 1 if src_A > src_B, 0 otherwise. */
4849 static IRExpr
* Quad_precision_sint_gt ( IRTemp src_A
, IRTemp src_B
)
4852 IRExpr
* hi_eq
= binop( Iop_CmpEQ64
,
4853 unop( Iop_V128HIto64
, mkexpr( src_A
) ),
4854 unop( Iop_V128HIto64
, mkexpr( src_B
) ) );
4856 IRExpr
* lo_eq
= binop( Iop_CmpEQ64
,
4857 unop( Iop_V128to64
, mkexpr( src_A
) ),
4858 unop( Iop_V128to64
, mkexpr( src_B
) ) );
4860 IRExpr
* hi_gt
= binop( Iop_CmpLT64S
,
4861 unop( Iop_V128HIto64
, mkexpr( src_B
) ),
4862 unop( Iop_V128HIto64
, mkexpr( src_A
) ) );
4864 /* If srcA and srcB are positive and srcA > srcB then lo_gteq = 1.
4865 If srcA and srcB are negative and srcA > srcB, then the unsigned value
4866 of the lower 64-bits are 2's complemented values means lower bits of srcB
4867 must be less then the lower bits of srcA.
4869 srcA = 8000012380000123 7000000080000000 => (smaller/less negative)
4870 - 7FFFFEDC7FFFFEDD 8FFFFFFF7FFFFFFF
4871 srcB = 8000012380000123 8000012380000123 =>
4872 - 7FFFFEDC7FFFFEDD 7FFFFEDC7FFFFEDD
4874 IRExpr
* lo_gteq
= binop( Iop_CmpLT64U
,
4875 unop( Iop_V128to64
, mkexpr( src_B
) ),
4876 unop( Iop_V128to64
, mkexpr( src_A
) ) );
4878 /* If hi is eq, then lower must be GT and not equal. */
4879 return mkOR1( hi_gt
, mkAND1( hi_eq
, mkAND1( lo_gteq
, mkNOT1 ( lo_eq
) ) ) );
4882 /* This function takes two quad_precision floating point numbers of type
4883 V128 and return 1 if src_A > src_B, 0 otherwise. */
4884 static IRExpr
* Quad_precision_gt ( IRTemp src_A
, IRTemp src_B
)
4886 #define FRAC_MASK64Hi 0x0000ffffffffffffULL
4887 #define MASK 0x7FFFFFFFFFFFFFFFULL /* exclude sign bit in upper 64 bits */
4888 #define EXP_MASK 0x7fff
4890 IRType ty
= Ity_I64
;
4891 IRTemp sign_A
= newTemp( ty
);
4892 IRTemp sign_B
= newTemp( ty
);
4893 IRTemp exp_A
= newTemp( ty
);
4894 IRTemp exp_B
= newTemp( ty
);
4895 IRTemp frac_A_hi
= newTemp( ty
);
4896 IRTemp frac_B_hi
= newTemp( ty
);
4897 IRTemp frac_A_lo
= newTemp( ty
);
4898 IRTemp frac_B_lo
= newTemp( ty
);
4901 /* extract exponents, and fractional parts so they can be compared */
4902 assign( sign_A
, binop( Iop_Shr64
,
4903 unop( Iop_V128HIto64
, mkexpr( src_A
) ),
4905 assign( sign_B
, binop( Iop_Shr64
,
4906 unop( Iop_V128HIto64
, mkexpr( src_B
) ),
4908 assign( exp_A
, binop( Iop_And64
,
4910 unop( Iop_V128HIto64
, mkexpr( src_A
) ),
4912 mkU64( EXP_MASK
) ) );
4913 assign( exp_B
, binop( Iop_And64
,
4915 unop( Iop_V128HIto64
, mkexpr( src_B
) ),
4917 mkU64( EXP_MASK
) ) );
4918 assign( frac_A_hi
, binop( Iop_And64
,
4919 unop( Iop_V128HIto64
, mkexpr( src_A
) ),
4920 mkU64( FRAC_MASK64Hi
) ) );
4921 assign( frac_B_hi
, binop( Iop_And64
,
4922 unop( Iop_V128HIto64
, mkexpr( src_B
) ),
4923 mkU64( FRAC_MASK64Hi
) ) );
4924 assign( frac_A_lo
, unop( Iop_V128to64
, mkexpr( src_A
) ) );
4925 assign( frac_B_lo
, unop( Iop_V128to64
, mkexpr( src_B
) ) );
4927 IRExpr
* A_zero
= mkAND1( binop( Iop_CmpEQ64
,
4929 unop( Iop_V128HIto64
,
4934 unop( Iop_V128to64
, mkexpr( src_A
) ),
4936 IRExpr
* B_zero
= mkAND1( binop( Iop_CmpEQ64
,
4938 unop( Iop_V128HIto64
,
4943 unop( Iop_V128to64
, mkexpr( src_B
) ),
4945 IRExpr
* A_B_zero
= mkAND1( A_zero
, B_zero
);
4947 /* Compare numbers */
4948 IRExpr
* both_pos
= mkAND1( binop( Iop_CmpEQ64
, mkexpr( sign_A
),
4950 binop( Iop_CmpEQ64
, mkexpr( sign_B
),
4952 IRExpr
* both_neg
= mkAND1( binop( Iop_CmpEQ64
, mkexpr( sign_A
),
4954 binop( Iop_CmpEQ64
, mkexpr( sign_B
),
4956 IRExpr
* sign_eq
= binop( Iop_CmpEQ64
, mkexpr( sign_A
), mkexpr( sign_B
) );
4957 IRExpr
* sign_gt
= binop( Iop_CmpLT64U
, mkexpr( sign_A
),
4958 mkexpr( sign_B
) ); /* A pos, B neg */
4960 IRExpr
* exp_eq
= binop( Iop_CmpEQ64
, mkexpr( exp_A
), mkexpr( exp_B
) );
4961 IRExpr
* exp_gt
= binop( Iop_CmpLT64U
, mkexpr( exp_B
), mkexpr( exp_A
) );
4962 IRExpr
* exp_lt
= binop( Iop_CmpLT64U
, mkexpr( exp_A
), mkexpr( exp_B
) );
4964 IRExpr
* frac_hi_eq
= binop( Iop_CmpEQ64
, mkexpr( frac_A_hi
),
4965 mkexpr( frac_B_hi
) );
4966 IRExpr
* frac_hi_gt
= binop( Iop_CmpLT64U
, mkexpr( frac_B_hi
),
4967 mkexpr( frac_A_hi
) );
4968 IRExpr
* frac_hi_lt
= binop( Iop_CmpLT64U
, mkexpr( frac_A_hi
),
4969 mkexpr( frac_B_hi
) );
4971 IRExpr
* frac_lo_gt
= binop( Iop_CmpLT64U
, mkexpr( frac_B_lo
),
4972 mkexpr( frac_A_lo
) );
4973 IRExpr
* frac_lo_lt
= binop( Iop_CmpLT64U
, mkexpr( frac_A_lo
),
4974 mkexpr( frac_B_lo
) );
4976 /* src_A and src_B both positive */
4977 IRExpr
*pos_cmp
= mkOR1( exp_gt
,
4980 mkAND1( frac_hi_eq
, frac_lo_gt
) )
4983 /* src_A and src_B both negative */
4984 IRExpr
*neg_cmp
= mkOR1( exp_lt
,
4987 mkAND1( frac_hi_eq
, frac_lo_lt
) )
4990 /* Need to check the case where one value is a positive
4991 * zero and the other value is a negative zero
4993 return mkAND1( mkNOT1( A_B_zero
),
4996 mkOR1( mkAND1( both_pos
, pos_cmp
),
4997 mkAND1( both_neg
, neg_cmp
) ) ) ) );
5000 /*-----------------------------------------------------------
5001 * Helpers for VX instructions that work on National decimal values,
5002 * Zoned decimal values and BCD values.
5004 *------------------------------------------------------------*/
5005 static IRExpr
* is_National_decimal (IRTemp src
)
5007 /* The src is a 128-bit value containing a sign code in half word 7
5008 * and seven digits in halfwords 0 to 6 (IBM numbering). A valid
5009 * national decimal value has the following:
5010 * - the sign code must be 0x002B (positive) or 0x002D (negative)
5011 * - the digits must be in the range 0x0030 to 0x0039
5014 IRExpr
* valid_pos_sign
;
5015 IRExpr
* valid_neg_sign
;
5016 IRTemp valid_num
[8];
5019 valid_pos_sign
= binop( Iop_CmpEQ64
,
5022 unop( Iop_V128to64
, mkexpr( src
) ) ),
5025 valid_neg_sign
= binop( Iop_CmpEQ64
,
5028 unop( Iop_V128to64
, mkexpr( src
) ) ),
5031 valid_num
[0] = newTemp( Ity_I1
);
5032 digit
[0] = newTemp( Ity_I64
);
5033 assign( valid_num
[0], mkU1( 1 ) ); // Assume true to start
5035 for(i
= 0; i
< 7; i
++) {
5036 valid_num
[i
+1] = newTemp( Ity_I1
);
5037 digit
[i
] = newTemp( Ity_I64
);
5038 assign( digit
[i
], binop( Iop_And64
,
5042 mkU8( (7-i
)*16 ) ) ),
5043 mkU64( 0xFFFF ) ) );
5045 assign( valid_num
[i
+1],
5046 mkAND1( mkexpr( valid_num
[i
] ),
5047 mkAND1( binop( Iop_CmpLE64U
,
5050 binop( Iop_CmpLE64U
,
5052 mkexpr( digit
[i
] ) ) ) ) );
5055 return mkAND1( mkOR1( valid_pos_sign
, valid_neg_sign
),
5056 mkexpr( valid_num
[7] ) );
5059 static IRExpr
* is_Zoned_decimal (IRTemp src
, UChar ps
)
5061 /* The src is a 128-bit value containing a sign code the least significant
5062 * two bytes. The upper pairs of bytes contain digits. A valid Zoned
5063 * decimal value has the following:
5064 * - the sign code must be between 0x0X to 0xFX inclusive (X - don't care)
5065 * - bits [0:3] of each digit must be equal to 0x3
5066 * - bits [4:7] of each digit must be between 0x0 and 0x9
5069 * Positive sign codes are: 0x0, 0x1, 0x2, 0x3, 0x8, 0x9, 0xA, 0xB
5070 * (note 0bX0XX XXXX is positive)
5072 * Negative sign codes are 0x4, 0x5, 0x6, 0x7, 0xC, 0xD, 0xE, 0xF
5073 * (note 0bX1XX XXXX is negative)
5075 * If ps = 1, then the sign code must be in the range 0xA to 0xF
5076 * Positive sign codes are: 0xA, 0xC, 0xE, 0xF
5078 * Negative sign codes are 0xB, 0xD
5080 Int i
, mask_hi
, mask_lo
;
5081 IRExpr
*valid_range
;
5082 IRTemp valid_num
[16];
5085 /* check the range of the sign value based on the value of ps */
5086 valid_range
= mkOR1(
5087 mkAND1( binop( Iop_CmpEQ64
,
5090 mkAND1( binop( Iop_CmpLE64U
,
5097 binop( Iop_CmpLE64U
,
5102 mkexpr( src
) ))))),
5107 valid_num
[0] = newTemp( Ity_I1
);
5108 assign( valid_num
[0], mkU1( 1) ); // Assume true to start
5118 for(i
= 0; i
< 15; i
++) {
5119 valid_num
[i
+1] = newTemp( Ity_I1
);
5120 digit
[i
] = newTemp( Ity_I64
);
5121 assign( digit
[i
], binop( Iop_And64
,
5125 mkU8( (15-i
)*8 ) ) ),
5128 assign( valid_num
[i
+1],
5129 mkAND1( mkexpr( valid_num
[i
] ),
5130 mkAND1( binop( Iop_CmpLE64U
,
5133 binop( Iop_CmpLE64U
,
5135 mkexpr( digit
[i
] ) ) ) ) );
5138 return mkAND1( valid_range
, mkexpr( valid_num
[15] ) );
5141 static IRExpr
* CmpGT128U ( IRExpr
*src1
, IRExpr
*src2
)
5143 /* Unsigend compare of two 128-bit values */
5144 IRExpr
*pos_upper_gt
, *pos_upper_eq
, *pos_lower_gt
;
5146 pos_upper_gt
= binop( Iop_CmpLT64U
,
5147 unop( Iop_V128HIto64
, src2
),
5148 unop( Iop_V128HIto64
, src1
) );
5149 pos_upper_eq
= binop( Iop_CmpEQ64
,
5150 unop( Iop_V128HIto64
, src1
),
5151 unop( Iop_V128HIto64
, src2
) );
5152 pos_lower_gt
= binop( Iop_CmpLT64U
,
5153 unop( Iop_V128to64
, src2
),
5154 unop( Iop_V128to64
, src1
) );
5155 return mkOR1( pos_upper_gt
,
5156 mkAND1( pos_upper_eq
,
5161 static IRExpr
* is_BCDstring128 ( const VexAbiInfo
* vbi
,
5162 UInt Signed
, IRExpr
*src
)
5165 IRTemp valid
= newTemp( Ity_I64
);
5167 /* The src is a 128-bit value containing a MAX_DIGITS BCD digits and
5168 * a sign. The upper bytes are BCD values between 0x0 and 0x9. The sign
5169 * byte is the least significant byte. This function returns 64-bit 1
5170 * value if sign and digits are valid, 0 otherwise.
5172 * This function was originally written using IR code. It has been
5173 * replaced with a clean helper due to the large amount of IR code
5174 * needed by this function.
5177 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
5178 "is_BCDstring128_helper",
5179 fnptr_to_fnentry( vbi
, &is_BCDstring128_helper
),
5180 mkIRExprVec_3( mkU64( Signed
),
5181 unop( Iop_V128HIto64
, src
),
5182 unop( Iop_V128to64
, src
) ) ) );
5183 return mkexpr( valid
);
5186 static IRExpr
* BCDstring_zero (IRExpr
*src
)
5188 /* The src is a 128-bit value containing a BCD string. The function
5189 * returns a 1 if the BCD string values are all zero, 0 otherwise.
5191 IRTemp tsrc
= newTemp( Ity_V128
);
5195 return mkAND1( binop( Iop_CmpEQ64
,
5197 unop( Iop_V128HIto64
,
5202 mkexpr( tsrc
) ) ) );
5204 /* make this work in 32-bit mode */
5206 mkAND1( binop( Iop_CmpEQ32
,
5209 unop( Iop_V128HIto64
,
5210 mkexpr( tsrc
) ) ) ),
5214 unop( Iop_V128HIto64
,
5215 mkexpr( tsrc
) ) ) ) ),
5216 mkAND1( binop( Iop_CmpEQ32
,
5220 mkexpr( tsrc
) ) ) ),
5225 mkexpr( tsrc
) ) ) ) ) );
5229 static IRExpr
* check_BCD_round (IRExpr
*src
, IRTemp shift
)
5231 /* The src is a 128-bit value containing 31 BCD digits with the sign in
5232 * the least significant byte. The bytes are BCD values between 0x0 and 0x9.
5233 * This routine checks the BCD digit in position shift (counting from
5234 * the least significant digit). If the digit is greater then five,
5235 * a 1 is returned indicating the string needs to be rounded up,
5236 * otherwise, 0 is returned. The value of shift (I64) is the index of
5237 * the BCD digit times four bits.
5239 return binop( Iop_CmpLE64U
,
5245 unop( Iop_64to8
, mkexpr( shift
) ) ) ),
5249 static IRTemp
increment_BCDstring ( const VexAbiInfo
* vbi
,
5250 IRExpr
*src
, IRExpr
*carry_in
)
5252 /* The src is a 128-bit value containing 31 BCD digits with the sign in
5253 * the least significant byte. The bytes are BCD values between 0x0 and 0x9.
5254 * This function returns the BCD string incremented by 1.
5256 * Call a clean helper to do the computation as it requires a lot of
5257 * IR code to do this.
5259 * The helper function takes a 32-bit BCD string, in a 64-bit value, and
5260 * increments the string by the 32-bi carry in value.
5262 * The incremented value is returned in the lower 32-bits of the result.
5263 * The carry out is returned in bits [35:32] of the result. The
5264 * helper function will be called for each of the four 32-bit strings
5265 * that make up the src string passing the returned carry out to the
5268 IRTemp bcd_result
= newTemp( Ity_V128
);
5269 IRTemp bcd_result0
= newTemp( Ity_I64
);
5270 IRTemp bcd_result1
= newTemp( Ity_I64
);
5271 IRTemp bcd_result2
= newTemp( Ity_I64
);
5272 IRTemp bcd_result3
= newTemp( Ity_I64
);
5273 IRExpr
*bcd_string0
, *bcd_string1
, *bcd_string2
, *bcd_string3
;
5275 bcd_string0
= binop( Iop_And64
,
5276 mkU64( 0xFFFFFFFF ), unop( Iop_V128to64
, src
) );
5277 bcd_string1
= binop( Iop_Shr64
, unop( Iop_V128to64
, src
), mkU8( 32 ) );
5278 bcd_string2
= binop( Iop_And64
,
5279 mkU64( 0xFFFFFFFF ), unop( Iop_V128HIto64
, src
) );
5280 bcd_string3
= binop( Iop_Shr64
, unop( Iop_V128HIto64
, src
), mkU8( 32 ) );
5282 assign( bcd_result0
,
5283 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
5284 "increment_BCDstring32_helper",
5285 fnptr_to_fnentry( vbi
,
5286 &increment_BCDstring32_helper
),
5287 mkIRExprVec_3( mkU64( True
/*Signed*/ ),
5289 binop( Iop_32HLto64
, mkU32( 0 ),
5292 assign( bcd_result1
,
5293 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
5294 "increment_BCDstring32_helper",
5295 fnptr_to_fnentry( vbi
,
5296 &increment_BCDstring32_helper
),
5297 mkIRExprVec_3( mkU64( False
/*Unsigned*/ ),
5300 mkexpr( bcd_result0
),
5302 assign( bcd_result2
,
5303 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
5304 "increment_BCDstring32_helper",
5305 fnptr_to_fnentry( vbi
,
5306 &increment_BCDstring32_helper
),
5307 mkIRExprVec_3( mkU64( False
/*Unsigned*/ ),
5310 mkexpr( bcd_result1
),
5312 assign( bcd_result3
,
5313 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
5314 "increment_BCDstring32_helper",
5315 fnptr_to_fnentry( vbi
,
5316 &increment_BCDstring32_helper
),
5317 mkIRExprVec_3( mkU64( False
/*Unsigned*/ ),
5320 mkexpr( bcd_result2
),
5323 /* Put the 128-bit result together from the intermediate results. Remember
5324 * to mask out the carry out from the upper 32 bits of the results.
5327 binop( Iop_64HLtoV128
,
5330 mkU64( 0xFFFFFFFF ), mkexpr (bcd_result2
) ),
5332 mkexpr (bcd_result3
), mkU8( 32 ) ) ),
5335 mkU64( 0xFFFFFFFF ), mkexpr (bcd_result0
) ),
5337 mkexpr (bcd_result1
), mkU8( 32 ) ) ) ) );
5341 static IRExpr
* convert_to_zoned ( const VexAbiInfo
* vbi
,
5342 IRExpr
*src
, IRExpr
*upper_byte
)
5344 /* The function takes a V128 packed decimal value and returns
5345 * the value in zoned format. Note, the sign of the value is ignored.
5347 IRTemp result_low
= newTemp( Ity_I64
);
5348 IRTemp result_hi
= newTemp( Ity_I64
);
5349 IRTemp result
= newTemp( Ity_V128
);
5351 /* Since we can only return 64-bits from a clean helper, we will
5352 * have to get the lower and upper 64-bits separately.
5356 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
5357 "convert_to_zoned_helper",
5358 fnptr_to_fnentry( vbi
, &convert_to_zoned_helper
),
5359 mkIRExprVec_4( unop( Iop_V128HIto64
, src
),
5360 unop( Iop_V128to64
, src
),
5365 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
5366 "convert_to_zoned_helper",
5367 fnptr_to_fnentry( vbi
, &convert_to_zoned_helper
),
5368 mkIRExprVec_4( unop( Iop_V128HIto64
, src
),
5369 unop( Iop_V128to64
, src
),
5375 binop( Iop_64HLtoV128
, mkexpr( result_hi
), mkexpr( result_low
) ) );
5377 return mkexpr( result
);
5380 static IRExpr
* convert_to_national ( const VexAbiInfo
* vbi
, IRExpr
*src
) {
5381 /* The function takes 128-bit value which has a 64-bit packed decimal
5382 * value in the lower 64-bits of the source. The packed decimal is
5383 * converted to the national format via a clean helper. The clean
5384 * helper is used to to the large amount of IR code needed to do the
5385 * conversion. The helper returns the upper 64-bits of the 128-bit
5386 * result if return_upper != 0. Otherwise, the lower 64-bits of the
5387 * result is returned.
5389 IRTemp result_low
= newTemp( Ity_I64
);
5390 IRTemp result_hi
= newTemp( Ity_I64
);
5391 IRTemp result
= newTemp( Ity_V128
);
5393 /* Since we can only return 64-bits from a clean helper, we will
5394 * have to get the lower and upper 64-bits separately.
5398 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
5399 "convert_to_national_helper",
5400 fnptr_to_fnentry( vbi
, &convert_to_national_helper
),
5401 mkIRExprVec_2( unop( Iop_V128to64
, src
),
5405 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
5406 "convert_to_national_helper",
5407 fnptr_to_fnentry( vbi
, &convert_to_national_helper
),
5408 mkIRExprVec_2( unop( Iop_V128to64
, src
),
5412 binop( Iop_64HLtoV128
, mkexpr( result_hi
), mkexpr( result_low
) ) );
5414 return mkexpr( result
);
5417 static IRExpr
* convert_from_zoned ( const VexAbiInfo
* vbi
, IRExpr
*src
) {
5418 /* The function takes 128-bit zoned value and returns a signless 64-bit
5419 * packed decimal value in the lower 64-bits of the 128-bit result.
5421 IRTemp result
= newTemp( Ity_V128
);
5425 binop( Iop_64HLtoV128
,
5427 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
5428 "convert_from_zoned_helper",
5429 fnptr_to_fnentry( vbi
,
5430 &convert_from_zoned_helper
),
5431 mkIRExprVec_2( unop( Iop_V128HIto64
,
5437 return mkexpr( result
);
5440 static IRExpr
* convert_from_national ( const VexAbiInfo
* vbi
, IRExpr
*src
) {
5441 /* The function takes 128-bit national value and returns a 64-bit
5442 * packed decimal value.
5444 IRTemp result
= newTemp( Ity_I64
);
5447 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
5448 "convert_from_national_helper",
5449 fnptr_to_fnentry( vbi
,
5450 &convert_from_national_helper
),
5451 mkIRExprVec_2( unop( Iop_V128HIto64
,
5456 return mkexpr( result
);
5459 static IRExpr
* vector_convert_floattobf16 ( const VexAbiInfo
* vbi
,
5461 /* The function takes 128-bit value containing four 32-bit floats and
5462 returns a 128-bit value containint four 16-bit bfloats in the lower
5465 IRTemp resultHi
= newTemp( Ity_I64
);
5466 IRTemp resultLo
= newTemp( Ity_I64
);
5469 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
5470 "vector_convert_floattobf16_helper",
5471 fnptr_to_fnentry( vbi
,
5472 &convert_from_floattobf16_helper
),
5473 mkIRExprVec_1( unop( Iop_V128HIto64
, src
) ) ) );
5476 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
5477 "vector_convert_floattobf16_helper",
5478 fnptr_to_fnentry( vbi
,
5479 &convert_from_floattobf16_helper
),
5480 mkIRExprVec_1( unop( Iop_V128to64
, src
) ) ) );
5482 return binop( Iop_64HLtoV128
, mkexpr( resultHi
), mkexpr( resultLo
) );
5485 static IRExpr
* vector_convert_bf16tofloat ( const VexAbiInfo
* vbi
,
5487 /* The function takes 128-bit value containing four 16-bit bfloats in
5488 the lower halfwords and returns a 128-bit value containint four
5490 IRTemp resultHi
= newTemp( Ity_I64
);
5491 IRTemp resultLo
= newTemp( Ity_I64
);
5494 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
5495 "vector_convert_bf16tofloat_helper",
5496 fnptr_to_fnentry( vbi
,
5497 &convert_from_bf16tofloat_helper
),
5498 mkIRExprVec_1( unop( Iop_V128HIto64
, src
) ) ) );
5501 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
5502 "vector_convert_bf16tofloat_helper",
5503 fnptr_to_fnentry( vbi
,
5504 &convert_from_bf16tofloat_helper
),
5505 mkIRExprVec_1( unop( Iop_V128to64
, src
) ) ) );
5507 return binop( Iop_64HLtoV128
, mkexpr( resultHi
), mkexpr( resultLo
) );
5510 static IRExpr
* popcnt64 ( const VexAbiInfo
* vbi
,
5512 /* The function takes a 64-bit source and counts the number of bits in the
5513 source that are 1's. */
5514 IRTemp result
= newTemp( Ity_I64
);
5517 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
5518 "population_count64_helper",
5519 fnptr_to_fnentry( vbi
,
5520 &population_count64_helper
),
5521 mkIRExprVec_1( src
) ) );
5523 return mkexpr( result
);
5526 static IRExpr
* extract_bits_under_mask ( const VexAbiInfo
* vbi
,
5527 IRExpr
*src
, IRExpr
*mask
,
5530 /* The function takes a 64-bit value and a 64-bit mask. It will extract the
5531 * bits from the source that align with 1's in the mask or it will extract
5532 * the bits from the source that align with 0's in the mask.
5534 IRTemp result
= newTemp( Ity_I64
);
5537 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
5538 "extract_bits_under_mask_helper",
5539 fnptr_to_fnentry( vbi
,
5540 &extract_bits_under_mask_helper
),
5541 mkIRExprVec_3( src
, mask
, flag
) ) );
5543 return mkexpr( result
);
5546 static IRExpr
* count_bits_under_mask ( const VexAbiInfo
* vbi
,
5547 IRExpr
*src
, IRExpr
*mask
,
5550 /* The function takes a 64-bit value and a 64-bit mask. It will count the
5551 * bits from the source that align with 1's in the mask or it will count
5552 * the bits from the source that align with 0's in the mask.
5554 IRTemp result
= newTemp( Ity_I32
);
5557 mkIRExprCCall( Ity_I32
, 0 /*regparms*/,
5558 "count_bits_under_mask_helper",
5559 fnptr_to_fnentry( vbi
,
5560 &count_bits_under_mask_helper
),
5561 mkIRExprVec_3( src
, mask
, flag
) ) );
5563 return mkexpr( result
);
5566 static IRExpr
* deposit_bits_under_mask ( const VexAbiInfo
* vbi
,
5567 IRExpr
*src
, IRExpr
*mask
) {
5569 /* The contents of the rightmost n bits of src are placed into bits_rtn
5570 * under the control of the mask. The LSB (bit 63) of src is placed into
5571 * the bit of bits_rtn corresponding to the right most bit of mask that is
5572 * a 1. The LSB+1 (bit 62) of src is placed into the bit of bits_rtn
5573 * corresponding to the second right most bit of mask that is a 1, etc.
5576 IRTemp result
= newTemp( Ity_I64
);
5579 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
5580 "deposit_bits_under_mask_helper",
5581 fnptr_to_fnentry( vbi
,
5582 &deposit_bits_under_mask_helper
),
5583 mkIRExprVec_2( src
, mask
) ) );
5585 return mkexpr( result
);
5588 static IRExpr
* vector_evaluate_inst ( const VexAbiInfo
* vbi
,
5589 IRExpr
*srcA
, IRExpr
*srcB
,
5590 IRExpr
*srcC
, IRExpr
*IMM
){
5591 /* This function implements the ISA 3.1 instruction xxeval. The
5592 instruction is too complex to do with Iops. */
5594 /* The instruction description, note the IBM bit numbering is left to right:
5596 For each integer value i, 0 to 127, do the following.
5598 Let j be the value of the concatenation of the contents of bit i of
5599 srcA, bit i of srcB, bit i of srcC. (j = srcA[i] | srcB[i] | srcC[i])
5601 The value of bit IMM[j] is placed into bit result[i].
5603 Basically the instruction lets you set each of the 128 bits in the result
5604 by selecting one of the eight bits in the IMM value. */
5606 /* Calling clean helpers with 128-bit args is currently not supported. We
5607 will simply call a 64-bit clean helper to do the upper 64-bits of the
5608 result and then call it do do the lower 64-bits of the result. */
5610 IRTemp result_hi
= newTemp( Ity_I64
);
5611 IRTemp result_lo
= newTemp( Ity_I64
);
5619 srcA_hi
= unop( Iop_V128HIto64
, srcA
);
5620 srcA_lo
= unop( Iop_V128to64
, srcA
);
5621 srcB_hi
= unop( Iop_V128HIto64
, srcB
);
5622 srcB_lo
= unop( Iop_V128to64
, srcB
);
5623 srcC_hi
= unop( Iop_V128HIto64
, srcC
);
5624 srcC_lo
= unop( Iop_V128to64
, srcC
);
5627 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
5628 "vector_evaluate64_helper",
5629 fnptr_to_fnentry( vbi
,
5630 &vector_evaluate64_helper
),
5631 mkIRExprVec_4( srcA_hi
, srcB_hi
, srcC_hi
, IMM
) ) );
5634 mkIRExprCCall( Ity_I64
, 0 /*regparms*/,
5635 "vector_evaluate64_helper",
5636 fnptr_to_fnentry( vbi
,
5637 &vector_evaluate64_helper
),
5638 mkIRExprVec_4( srcA_lo
, srcB_lo
, srcC_lo
, IMM
) ) );
5640 return binop( Iop_64HLtoV128
, mkexpr( result_hi
), mkexpr( result_lo
) );
5643 static void setup_fxstate_struct( IRDirty
* d
, UInt AT
, IREffect AT_fx
,
5644 Bool ACC_mapped_on_VSR
) {
5645 UInt acc_base_address
;
5647 /* declare guest state effects, writing to four ACC 128-bit regs. */
5649 vex_bzero(&d
->fxState
, sizeof(d
->fxState
));
5650 d
->fxState
[0].fx
= AT_fx
;
5651 d
->fxState
[0].size
= sizeof(U128
);
5652 d
->fxState
[1].fx
= AT_fx
;
5653 d
->fxState
[1].size
= sizeof(U128
);
5654 d
->fxState
[2].fx
= AT_fx
;
5655 d
->fxState
[2].size
= sizeof(U128
);
5656 d
->fxState
[3].fx
= AT_fx
;
5657 d
->fxState
[3].size
= sizeof(U128
);
5659 vassert( (AT
>= 0) && (AT
< 8));
5661 acc_base_address
= base_acc_addr( ACC_mapped_on_VSR
);
5663 d
->fxState
[0].offset
= acc_base_address
+ ACC_offset( AT
, 0);
5664 d
->fxState
[1].offset
= acc_base_address
+ ACC_offset( AT
, 1);
5665 d
->fxState
[2].offset
= acc_base_address
+ ACC_offset( AT
, 2);
5666 d
->fxState
[3].offset
= acc_base_address
+ ACC_offset( AT
, 3);
5669 #define MATRIX_4BIT_INT_GER 1
5670 #define MATRIX_8BIT_INT_GER 2
5671 #define MATRIX_16BIT_INT_GER 3
5672 #define MATRIX_16BIT_FLOAT_GER 4
5673 #define MATRIX_32BIT_FLOAT_GER 5
5674 /* Note, the 64-bit float instructions have their caller. */
5676 static void vsx_matrix_ger ( const VexAbiInfo
* vbi
,
5678 IRExpr
*srcA
, IRExpr
*srcB
,
5679 UInt AT
, UInt mask_inst
,
5680 Bool ACC_mapped_on_VSR
) {
5682 UInt acc_base_addr
= base_acc_addr( ACC_mapped_on_VSR
);
5684 /* This helper function does the VSX Matrix 4-bit Signed Integer GER
5685 (Rank-8 Update) instructions xvi4ger8, xvi4ger8pp, pmxvi4ger8,
5686 pmxvi4ger8pp. The instructions work on four V128 values, and three
5689 IRTemp srcA_hi
= newTemp( Ity_I64
);
5690 IRTemp srcA_lo
= newTemp( Ity_I64
);
5691 IRTemp srcB_hi
= newTemp( Ity_I64
);
5692 IRTemp srcB_lo
= newTemp( Ity_I64
);
5694 UInt instruction
= mask_inst
& 0xFF; /* Instruction is lower 8-bits. */
5697 assign( srcA_hi
, unop( Iop_V128HIto64
, srcA
) );
5698 assign( srcA_lo
, unop( Iop_V128to64
, srcA
) );
5699 assign( srcB_hi
, unop( Iop_V128HIto64
, srcB
) );
5700 assign( srcB_lo
, unop( Iop_V128to64
, srcB
) );
5702 /* Using a dirty helper so we can access the contents of the ACC for use in
5703 by the instruction and then write the result directly back to the ACC.
5704 The dirty helper does not return data. */
5705 IRExpr
** args
= mkIRExprVec_7(
5707 mkU32( acc_base_addr
),
5708 mkexpr(srcA_hi
), mkexpr(srcA_lo
),
5709 mkexpr(srcB_hi
), mkexpr(srcB_lo
),
5710 mkU32( (mask_inst
<< 5) | AT
));
5712 /* Set AT_fx to Write if the instruction only writes the ACC. Set
5713 AT_fx to modify if the instruction uses the AT entry and writes
5714 to the ACC entry. */
5715 switch (instruction
) {
5745 vassert(0); /* Unknown instruction */
5748 switch(inst_class
) {
5749 case MATRIX_4BIT_INT_GER
:
5751 d
= unsafeIRDirty_0_N (
5753 "vsx_matrix_4bit_ger_dirty_helper",
5754 fnptr_to_fnentry( vbi
, &vsx_matrix_4bit_ger_dirty_helper
),
5758 case MATRIX_8BIT_INT_GER
:
5760 d
= unsafeIRDirty_0_N (
5762 "vsx_matrix_8bit_ger_dirty_helper",
5763 fnptr_to_fnentry( vbi
, &vsx_matrix_8bit_ger_dirty_helper
),
5767 case MATRIX_16BIT_INT_GER
:
5769 d
= unsafeIRDirty_0_N (
5771 "vsx_matrix_16bit_ger_dirty_helper",
5772 fnptr_to_fnentry( vbi
, &vsx_matrix_16bit_ger_dirty_helper
),
5776 case MATRIX_16BIT_FLOAT_GER
:
5778 d
= unsafeIRDirty_0_N (
5780 "vsx_matrix_16bit_float_ger_dirty_helper",
5781 fnptr_to_fnentry( vbi
, &vsx_matrix_16bit_float_ger_dirty_helper
),
5785 case MATRIX_32BIT_FLOAT_GER
:
5787 d
= unsafeIRDirty_0_N (
5789 "vsx_matrix_32bit_float_ger_dirty_helper",
5790 fnptr_to_fnentry( vbi
, &vsx_matrix_32bit_float_ger_dirty_helper
),
5795 vex_printf("ERROR: Unkown inst_class = %u in vsx_matrix_ger()\n",
5800 setup_fxstate_struct( d
, AT
, AT_fx
, ACC_mapped_on_VSR
);
5802 /* execute the dirty call, side-effecting guest state */
5803 stmt( IRStmt_Dirty(d
) );
5806 static void vsx_matrix_64bit_float_ger ( const VexAbiInfo
* vbi
,
5807 IRExpr
*srcA
, IRExpr
*srcA1
,
5809 UInt AT
, UInt mask_inst
,
5810 Bool ACC_mapped_on_VSR
) {
5812 UInt acc_base_addr
= base_acc_addr( ACC_mapped_on_VSR
);
5814 /* This helper function does the VSX Matrix 64-bit floating-point GER
5815 (Rank-1 Update) instructions xvf64ger, xvf64gerpp, xvf64gerpn,
5816 xvf64gernp, xvf64gernn, pmxvf64ger, pmxvf64gerpp, pmxvf64gerpn,
5817 pmxvf64gernp, pmxvf64gernn. */
5818 IRTemp srcX_hi
= newTemp( Ity_I64
);
5819 IRTemp srcX_lo
= newTemp( Ity_I64
);
5820 IRTemp srcX1_hi
= newTemp( Ity_I64
);
5821 IRTemp srcX1_lo
= newTemp( Ity_I64
);
5822 IRTemp srcY_hi
= newTemp( Ity_I64
);
5823 IRTemp srcY_lo
= newTemp( Ity_I64
);
5826 ULong combined_args
;
5827 UInt instruction
= mask_inst
& 0xFF; /* Instruction is lower 8-bits. */
5830 assign( srcX_lo
, unop( Iop_V128HIto64
, srcA
) );
5831 assign( srcX_hi
, unop( Iop_V128to64
, srcA
) );
5832 assign( srcX1_lo
, unop( Iop_V128HIto64
, srcA1
) );
5833 assign( srcX1_hi
, unop( Iop_V128to64
, srcA1
) );
5834 assign( srcY_lo
, unop( Iop_V128HIto64
, srcB
) );
5835 assign( srcY_hi
, unop( Iop_V128to64
, srcB
) );
5837 /* Using a dirty helper so we can access the contents of the ACC for use in
5838 by the instruction and then write the result directly back to the ACC.
5839 The dirty helper does not return data.
5841 There is a restriction of 8 args in a dirty helper. Can't pass the four
5842 srcX values. So, just do two calls calculating the first two ACC
5843 results then the second two ACC results. */
5846 combined_args
= (mask_inst
<< 8) | (start_i
<< 4) | AT
;
5848 IRExpr
** args1
= mkIRExprVec_7(
5850 mkU32( acc_base_addr
),
5851 mkexpr(srcX1_hi
), mkexpr(srcX1_lo
),
5852 mkexpr(srcY_hi
), mkexpr(srcY_lo
),
5853 mkU32( combined_args
));
5855 /* Set AT_fx to Write if the instruction only writes the ACC. Set
5856 AT_fx to modify if the instruction uses the AT entry and writes
5857 to the ACC entry. */
5858 switch (instruction
) {
5869 vassert(0); /* Unknown instruction */
5872 d
= unsafeIRDirty_0_N (
5874 "vsx_matrix_64bit_float_ger_dirty_helper",
5875 fnptr_to_fnentry( vbi
, &vsx_matrix_64bit_float_ger_dirty_helper
),
5878 setup_fxstate_struct( d
, AT
, AT_fx
, ACC_mapped_on_VSR
);
5880 /* execute the dirty call, side-effecting guest state */
5881 stmt( IRStmt_Dirty(d
) );
5884 combined_args
= (mask_inst
<< 8) | (start_i
<< 4) | AT
;
5886 IRExpr
** args2
= mkIRExprVec_7(
5888 mkU32( acc_base_addr
),
5889 mkexpr(srcX_hi
), mkexpr(srcX_lo
),
5890 mkexpr(srcY_hi
), mkexpr(srcY_lo
),
5891 mkU32( combined_args
));
5893 d
= unsafeIRDirty_0_N (
5895 "vsx_matrix_64bit_float_ger_dirty_helper",
5896 fnptr_to_fnentry( vbi
, &vsx_matrix_64bit_float_ger_dirty_helper
),
5899 setup_fxstate_struct( d
, AT
, AT_fx
, ACC_mapped_on_VSR
);
5901 /* execute the dirty call, side-effecting guest state */
5902 stmt( IRStmt_Dirty(d
) );
5905 static void vector_gen_pvc_mask ( const VexAbiInfo
* vbi
,
5906 IRExpr
*src
, UInt IMM
,
5907 UInt opc2
, UInt VSX_addr
) {
5908 /* The function takes a 64-bit source and an immediate value. The function
5909 calls a helper to execute the xxgenpcvbm, xxgenpcvhm, xxgenpcvwm,
5910 xxgenpcvdm instruction. The instructions are not practical to do with
5911 Iops. The instruction is implemented with a dirty helper that
5912 calculates the 128-bit result and writes it directly into the guest
5915 IRTemp src_hi
= newTemp( Ity_I64
);
5916 IRTemp src_lo
= newTemp( Ity_I64
);
5920 vassert( (VSX_addr
>= 0) && (VSX_addr
< 64) );
5921 UInt reg_offset
= offsetofPPCGuestState( guest_VSR0
)
5922 + sizeof(U128
) * VSX_addr
;
5924 assign( src_hi
, unop( Iop_V128HIto64
, src
) );
5925 assign( src_lo
, unop( Iop_V128to64
, src
) );
5927 IRExpr
** args
= mkIRExprVec_5(
5931 mkU32( reg_offset
),
5935 case 0x394: // xxgenpcvbm
5936 d
= unsafeIRDirty_0_N (
5938 "vector_gen_pvc_byte_mask_dirty_helper",
5939 fnptr_to_fnentry( vbi
,
5940 &vector_gen_pvc_byte_mask_dirty_helper
),
5944 case 0x395: // xxgenpcvhm
5945 d
= unsafeIRDirty_0_N (
5947 "vector_gen_pvc_hword_mask_dirty_helper",
5948 fnptr_to_fnentry( vbi
,
5949 &vector_gen_pvc_hword_mask_dirty_helper
),
5953 case 0x3B4: // xxgenpcvwm
5954 d
= unsafeIRDirty_0_N (
5956 "vector_gen_pvc_word_mask_dirty_helper",
5957 fnptr_to_fnentry( vbi
,
5958 &vector_gen_pvc_word_mask_dirty_helper
),
5962 case 0x3B5: // xxgenpcvdm
5963 d
= unsafeIRDirty_0_N (
5965 "vector_gen_pvc_dword_mask_dirty_helper",
5966 fnptr_to_fnentry( vbi
,
5967 &vector_gen_pvc_dword_mask_dirty_helper
),
5971 vex_printf("ERROR: Unkown instruction = %u in vector_gen_pvc_mask()\n",
5977 vex_bzero(&d
->fxState
, sizeof(d
->fxState
));
5978 d
->fxState
[0].fx
= Ifx_Modify
;
5979 d
->fxState
[0].size
= sizeof(U128
);
5980 d
->fxState
[0].offset
= reg_offset
;
5982 /* execute the dirty call, side-effecting guest state */
5983 stmt( IRStmt_Dirty(d
) );
5986 static IRExpr
* UNSIGNED_CMP_GT_V128 ( IRExpr
*vA
, IRExpr
*vB
) {
5987 /* This function does an unsigned compare of two V128 values. The
5988 * function is for use in 32-bit mode only as it is expensive. The
5989 * issue is that compares (GT, LT, EQ) are not supported for operands
5990 * larger then 32-bits when running in 32-bit mode. The function returns
5991 * a 1-bit expression, 1 for TRUE and 0 for FALSE.
5993 IRTemp vA_word0
= newTemp( Ity_I32
);
5994 IRTemp vA_word1
= newTemp( Ity_I32
);
5995 IRTemp vA_word2
= newTemp( Ity_I32
);
5996 IRTemp vA_word3
= newTemp( Ity_I32
);
5997 IRTemp vB_word0
= newTemp( Ity_I32
);
5998 IRTemp vB_word1
= newTemp( Ity_I32
);
5999 IRTemp vB_word2
= newTemp( Ity_I32
);
6000 IRTemp vB_word3
= newTemp( Ity_I32
);
6002 IRTemp eq_word1
= newTemp( Ity_I1
);
6003 IRTemp eq_word2
= newTemp( Ity_I1
);
6004 IRTemp eq_word3
= newTemp( Ity_I1
);
6007 IRExpr
*gt_word0
, *gt_word1
, *gt_word2
, *gt_word3
;
6008 IRExpr
*eq_word3_2
, *eq_word3_2_1
;
6009 IRTemp result
= newTemp( Ity_I1
);
6011 assign( vA_word0
, unop( Iop_64to32
, unop( Iop_V128to64
, vA
) ) );
6012 assign( vA_word1
, unop( Iop_64HIto32
, unop( Iop_V128to64
, vA
) ) );
6013 assign( vA_word2
, unop( Iop_64to32
, unop( Iop_V128HIto64
, vA
) ) );
6014 assign( vA_word3
, unop( Iop_64HIto32
, unop( Iop_V128HIto64
, vA
) ) );
6016 assign( vB_word0
, unop( Iop_64to32
, unop( Iop_V128to64
, vB
) ) );
6017 assign( vB_word1
, unop( Iop_64HIto32
, unop( Iop_V128to64
, vB
) ) );
6018 assign( vB_word2
, unop( Iop_64to32
, unop( Iop_V128HIto64
, vB
) ) );
6019 assign( vB_word3
, unop( Iop_64HIto32
, unop( Iop_V128HIto64
, vB
) ) );
6021 assign( eq_word3
, binop( Iop_CmpEQ32
, mkexpr( vA_word3
),
6022 mkexpr( vB_word3
) ) );
6023 assign( eq_word2
, binop( Iop_CmpEQ32
, mkexpr( vA_word2
),
6024 mkexpr( vB_word2
) ) );
6025 assign( eq_word1
, binop( Iop_CmpEQ32
, mkexpr( vA_word1
),
6026 mkexpr( vB_word1
) ) );
6028 gt_word3
= binop( Iop_CmpLT32U
, mkexpr( vB_word3
), mkexpr( vA_word3
) );
6029 gt_word2
= binop( Iop_CmpLT32U
, mkexpr( vB_word2
), mkexpr( vA_word2
) );
6030 gt_word1
= binop( Iop_CmpLT32U
, mkexpr( vB_word1
), mkexpr( vA_word1
) );
6031 gt_word0
= binop( Iop_CmpLT32U
, mkexpr( vB_word0
), mkexpr( vA_word0
) );
6033 eq_word3_2
= mkAND1( mkexpr( eq_word3
), mkexpr( eq_word2
) );
6034 eq_word3_2_1
= mkAND1( mkexpr( eq_word1
), eq_word3_2
);
6036 assign( result
, mkOR1(
6038 mkAND1( mkexpr( eq_word3
), gt_word2
) ),
6039 mkOR1( mkAND1( eq_word3_2
, gt_word1
),
6040 mkAND1( eq_word3_2_1
, gt_word0
) ) ) );
6041 return mkexpr( result
);
6044 /*------------------------------------------------------------*/
6045 /*--- FP Helpers ---*/
6046 /*------------------------------------------------------------*/
6048 static IRExpr
* /* :: Ity_I32 */ get_IR_roundingmode ( void ); // prototype
6050 /* Produce the 32-bit pattern corresponding to the supplied
6052 static UInt
float_to_bits ( Float f
)
6054 union { UInt i
; Float f
; } u
;
6055 vassert(4 == sizeof(UInt
));
6056 vassert(4 == sizeof(Float
));
6057 vassert(4 == sizeof(u
));
6062 static IRExpr
* dnorm_adj_Vector ( IRExpr
* src
)
6064 /* This function takes a vector of 32-bit floats. It does the required
6065 adjustment on denormalized values based on the setting of the
6068 The VSCR[NJ] bit controlls how subnormal (denormalized) results for
6069 vector floating point operations are handled. VSCR[NJ] is bit 17
6070 (bit 111 IBM numbering).
6072 VSCR[NJ] = 0 Denormalized values are handled as
6073 specified by Java and the IEEE standard.
6075 VSCR[NJ] = 1 If an element in a source VR contains a denormalized
6076 value, the value 0 is used instead. If an instruction
6077 causes an Underflow Exception, the corresponding element
6078 in the target VR is set to 0. In both cases the 0 has
6079 the same sign as the denormalized or underflowing value.
6080 Convert negative zero to positive zero.
6082 The ABI for LE requires VSCR[NJ] = 0. For BE mode, VSCR[NJ] = 1 by
6083 default. The PPC guest state is initialized to match the HW setup.
6085 IRTemp sign_bit_maskV128
= newTemp( Ity_V128
);
6086 IRTemp ones_maskV128
= newTemp( Ity_V128
);
6087 IRTemp clear_dnorm_maskV128
= newTemp( Ity_V128
);
6088 IRTemp adj_valueV128
= newTemp( Ity_V128
);
6089 IRTemp dnormV128
= newTemp( Ity_V128
);
6090 IRTemp zeroV128
= newTemp( Ity_V128
);
6091 IRTemp VSCR_NJ
= newTemp( Ity_I64
);
6092 IRTemp VSCR_NJ_mask
= newTemp( Ity_V128
);
6093 IRTemp resultV128
= newTemp( Ity_V128
);
6095 /* get the VSCR[NJ] bit */
6100 getGST( PPC_GST_VSCR
),
6103 assign ( VSCR_NJ_mask
, binop( Iop_64HLtoV128
,
6105 mkexpr( VSCR_NJ
) ) );
6107 /* Create the masks to do the rounding of dnorm values and absolute
6109 assign( dnormV128
, is_Denorm_Vector( Ity_I32
, src
) );
6110 assign( zeroV128
, is_Zero_Vector( Ity_I32
, src
) );
6112 /* If the value is dnorm, then we need to clear the significand and
6113 exponent but leave the sign bit. Put 1'x in elements that are not
6114 denormalized values. */
6115 assign( sign_bit_maskV128
, unop( Iop_Dup32x4
, mkU32( 0x80000000 ) ) );
6117 assign( clear_dnorm_maskV128
,
6120 mkexpr( dnormV128
),
6121 mkexpr( sign_bit_maskV128
) ),
6122 unop( Iop_NotV128
, mkexpr( dnormV128
) ) ) );
6124 assign( ones_maskV128
, mkV128( 0xFFFF ) );
6126 assign( adj_valueV128
, binop( Iop_AndV128
,
6127 mkexpr( clear_dnorm_maskV128
),
6130 mkexpr( ones_maskV128
) ) ) );
6132 /* If the VSCR[NJ] bit is 1, then clear the denormalized values,
6133 otherwise just return the input unchanged. */
6137 mkexpr( VSCR_NJ_mask
),
6138 mkexpr( adj_valueV128
) ),
6140 unop( Iop_NotV128
, mkexpr( VSCR_NJ_mask
) ),
6143 return mkexpr(resultV128
);
6146 /*------------------------------------------------------------*/
6147 /* Transactional memory helpers
6149 *------------------------------------------------------------*/
6151 static ULong
generate_TMreason( UInt failure_code
,
6157 ( (ULong
) 0) << (63-6) /* Failure code */
6158 | ( (ULong
) persistant
) << (63-7) /* Failure persistant */
6159 | ( (ULong
) 0) << (63-8) /* Disallowed */
6160 | ( (ULong
) nest_overflow
) << (63-9) /* Nesting Overflow */
6161 | ( (ULong
) 0) << (63-10) /* Footprint Overflow */
6162 | ( (ULong
) 0) << (63-11) /* Self-Induced Conflict */
6163 | ( (ULong
) 0) << (63-12) /* Non-Transactional Conflict */
6164 | ( (ULong
) 0) << (63-13) /* Transactional Conflict */
6165 | ( (ULong
) 0) << (63-14) /* Translation Invalidation Conflict */
6166 | ( (ULong
) 0) << (63-15) /* Implementation-specific */
6167 | ( (ULong
) 0) << (63-16) /* Instruction Fetch Conflict */
6168 | ( (ULong
) 0) << (63-30) /* Reserved */
6169 | ( (ULong
) 0) << (63-31) /* Abort */
6170 | ( (ULong
) 0) << (63-32) /* Suspend */
6171 | ( (ULong
) 0) << (63-33) /* Reserved */
6172 | ( (ULong
) 0) << (63-35) /* Privilege */
6173 | ( (ULong
) 0) << (63-36) /* Failure Summary */
6174 | ( (ULong
) tm_exact
) << (63-37) /* TFIAR Exact */
6175 | ( (ULong
) 0) << (63-38) /* ROT */
6176 | ( (ULong
) 0) << (63-51) /* Reserved */
6177 | ( (ULong
) 0) << (63-63); /* Transaction Level */
6182 static void storeTMfailure( Addr64 err_address
, ULong tm_reason
,
6183 Addr64 handler_address
)
6185 putGST( PPC_GST_TFIAR
, mkU64( err_address
) );
6186 putGST( PPC_GST_TEXASR
, mkU64( tm_reason
) );
6187 putGST( PPC_GST_TEXASRU
, mkU32( 0 ) );
6188 putGST( PPC_GST_TFHAR
, mkU64( handler_address
) );
6191 /*------------------------------------------------------------*/
6192 /*--- Integer Instruction Translation --- */
6193 /*------------------------------------------------------------*/
6196 Byte reverse instructions
6198 static Bool
dis_byte_reverse ( UInt prefixInstr
, UInt theInstr
)
6200 UChar rS_addr
= ifieldRegDS( theInstr
);
6201 UChar rA_addr
= ifieldRegA( theInstr
);
6202 UInt opc2
= IFIELD( theInstr
, 1, 10 );
6203 IRTemp rS
= newTemp( Ity_I64
);
6204 IRTemp tmp_0
= newTemp( Ity_I64
);
6205 IRTemp tmp_1
= newTemp( Ity_I64
);
6206 IRTemp result
= newTemp( Ity_I64
);
6208 assign( rS
, getIReg( rS_addr
) );
6210 /* NOTE: rA is the destination and rS is the source. Reverse of the normal usage. */
6212 case 0xDB: // brh Byte-Reverse half word X-form
6213 DIP("brh r%u,r%u\n", rA_addr
, rS_addr
);
6215 binop( Iop_And64
, mkexpr( rS
), mkU64( 0xFF00FF00FF00FF00 ) ) );
6217 binop( Iop_And64
, mkexpr( rS
), mkU64( 0x00FF00FF00FF00FF ) ) );
6220 binop( Iop_Shr64
, mkexpr( tmp_0
), mkU8( 8 ) ),
6221 binop( Iop_Shl64
, mkexpr( tmp_1
), mkU8( 8 ) ) ) );
6224 case 0x9B: { // brw Byte-Reverse word X-form
6225 IRTemp tmp_2
= newTemp( Ity_I64
);
6226 IRTemp tmp_3
= newTemp( Ity_I64
);
6228 DIP("brw r%u,r%u\n", rA_addr
, rS_addr
);
6230 binop( Iop_And64
, mkexpr( rS
), mkU64( 0xFF000000FF000000 ) ) );
6232 binop( Iop_And64
, mkexpr( rS
), mkU64( 0x00FF000000FF0000 ) ) );
6234 binop( Iop_And64
, mkexpr( rS
), mkU64( 0x0000FF000000FF00 ) ) );
6236 binop( Iop_And64
, mkexpr( rS
), mkU64( 0x000000FF000000FF ) ) );
6240 binop( Iop_Shl64
, mkexpr( tmp_3
), mkU8( 24 ) ),
6241 binop( Iop_Shl64
, mkexpr( tmp_2
), mkU8( 8 ) ) ),
6243 binop( Iop_Shr64
, mkexpr( tmp_1
), mkU8( 8 ) ),
6244 binop( Iop_Shr64
, mkexpr( tmp_0
), mkU8( 24 ) ) )
6249 case 0xBB: { // brd Byte-Reverse double word X-form
6250 IRTemp tmp_2
= newTemp( Ity_I64
);
6251 IRTemp tmp_3
= newTemp( Ity_I64
);
6252 IRTemp tmp_4
= newTemp( Ity_I64
);
6253 IRTemp tmp_5
= newTemp( Ity_I64
);
6254 IRTemp tmp_6
= newTemp( Ity_I64
);
6255 IRTemp tmp_7
= newTemp( Ity_I64
);
6257 DIP("brd r%u,r%u\n", rA_addr
, rS_addr
);
6259 binop( Iop_And64
, mkexpr( rS
), mkU64( 0xFF00000000000000 ) ) );
6261 binop( Iop_And64
, mkexpr( rS
), mkU64( 0x00FF000000000000 ) ) );
6263 binop( Iop_And64
, mkexpr( rS
), mkU64( 0x0000FF0000000000 ) ) );
6265 binop( Iop_And64
, mkexpr( rS
), mkU64( 0x000000FF00000000 ) ) );
6267 binop( Iop_And64
, mkexpr( rS
), mkU64( 0x00000000FF000000 ) ) );
6269 binop( Iop_And64
, mkexpr( rS
), mkU64( 0x0000000000FF0000 ) ) );
6271 binop( Iop_And64
, mkexpr( rS
), mkU64( 0x000000000000FF00 ) ) );
6273 binop( Iop_And64
, mkexpr( rS
), mkU64( 0x00000000000000FF ) ) );
6278 binop( Iop_Shl64
, mkexpr( tmp_7
), mkU8( 56 ) ),
6279 binop( Iop_Shl64
, mkexpr( tmp_6
), mkU8( 40 ) ) ),
6281 binop( Iop_Shl64
, mkexpr( tmp_5
), mkU8( 24 ) ),
6282 binop( Iop_Shl64
, mkexpr( tmp_4
), mkU8( 8 ) ) ) ),
6285 binop( Iop_Shr64
, mkexpr( tmp_3
), mkU8( 8 ) ),
6286 binop( Iop_Shr64
, mkexpr( tmp_2
), mkU8( 24 ) ) ),
6288 binop( Iop_Shr64
, mkexpr( tmp_1
), mkU8( 40 ) ),
6289 binop( Iop_Shr64
, mkexpr( tmp_0
), mkU8( 56 ) ) ) )
6295 vex_printf("dis_byte_reverse(ppc): unrecognized instruction\n");
6299 putIReg( rA_addr
, mkexpr( result
) );
6304 Integer Arithmetic Instructions
6306 static Bool
dis_int_mult_add ( UInt prefix
, UInt theInstr
)
6309 UChar rD_addr
= ifieldRegDS( theInstr
);
6310 UChar rA_addr
= ifieldRegA( theInstr
);
6311 UChar rB_addr
= ifieldRegB( theInstr
);
6312 UChar rC_addr
= ifieldRegC( theInstr
);
6313 UInt opc2
= IFIELD( theInstr
, 0, 6 );
6314 IRType ty
= Ity_I64
;
6315 IRTemp rA
= newTemp( ty
);
6316 IRTemp rB
= newTemp( ty
);
6317 IRTemp rC
= newTemp( ty
);
6318 IRTemp rD
= newTemp( ty
);
6319 IRTemp tmpLo
= newTemp( Ity_I64
);
6320 IRTemp tmpHi
= newTemp( Ity_I64
);
6321 IRTemp tmp2Hi
= newTemp( Ity_I64
);
6322 IRTemp result
= newTemp( Ity_I128
);
6323 IRTemp resultLo
= newTemp( Ity_I64
);
6326 assign( rA
, getIReg( rA_addr
) );
6327 assign( rB
, getIReg( rB_addr
) );
6328 assign( rC
, getIReg( rC_addr
) );
6330 /* There is no prefixed version of these instructions. */
6334 case 0x30: // maddhd multiply-add High doubleword signed
6335 DIP("maddhd r%u,r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
, rC_addr
);
6337 assign( result
, binop( Iop_MullS64
, mkexpr( rA
), mkexpr( rB
) ) );
6338 assign( tmpLo
, unop( Iop_128to64
, mkexpr( result
) ) );
6339 assign( tmpHi
, unop( Iop_128HIto64
, mkexpr( result
) ) );
6341 /* Multiply rA and rB then add rC. If the lower 32-bits of the result
6342 * is less then rC and the result rA * rB, a carry out of the lower 32
6343 * bits occurred and the upper 32 bits must be incremented by 1. Sign
6344 * extend rC and do the add to the upper 64 bits to handle the
6345 * negative case for rC.
6347 assign( resultLo
, binop( Iop_Add64
, mkexpr( tmpLo
), mkexpr( rC
) ) );
6348 assign( tmp2Hi
, binop( Iop_Add64
,
6354 mkU8( 63 ) ) ) ) ) );
6356 /* need to do calculation for the upper 32 bit result */
6357 carryout
= mkAND1( binop( Iop_CmpLT64U
,
6358 mkexpr( resultLo
), mkexpr( rC
) ),
6359 binop( Iop_CmpLT64U
,
6360 mkexpr( resultLo
), mkexpr( tmpLo
) ) );
6361 assign( rD
, binop( Iop_Add64
,
6363 unop( Iop_1Uto64
, carryout
) ) );
6366 case 0x31: // maddhdu multiply-add High doubleword unsigned
6367 DIP("maddhdu r%u,r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
, rC_addr
);
6369 assign( result
, binop( Iop_MullU64
, mkexpr( rA
), mkexpr( rB
) ) );
6370 assign( tmpLo
, unop( Iop_128to64
, mkexpr( result
) ) );
6371 assign( tmpHi
, unop( Iop_128HIto64
, mkexpr( result
) ) );
6373 /* Add rC, if the lower 32-bits of the result is less then rC and
6374 * tmpLo, a carry out of the lower 32 bits occurred. Upper 32 bits
6375 * must be incremented by 1.
6377 assign( resultLo
, binop( Iop_Add64
, mkexpr( tmpLo
), mkexpr( rC
) ) );
6379 /* need to do calculation for the upper 32 bit result */
6380 carryout
= mkAND1( binop( Iop_CmpLT64U
,
6381 mkexpr(resultLo
), mkexpr( rC
) ),
6382 binop( Iop_CmpLT64U
,
6383 mkexpr(resultLo
), mkexpr( tmpLo
) ) );
6384 assign( rD
, binop( Iop_Add64
,
6386 unop( Iop_1Uto64
, carryout
) ) );
6389 case 0x33: // maddld multiply-add Low doubleword
6390 DIP("maddld r%u,r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
, rC_addr
);
6392 assign( result
, binop( Iop_MullS64
, mkexpr( rA
), mkexpr( rB
) ) );
6393 assign( tmpLo
, unop( Iop_128to64
, mkexpr( result
) ) );
6394 assign( tmpHi
, unop( Iop_128HIto64
, mkexpr( result
) ) );
6396 assign( rD
, binop( Iop_Add64
, mkexpr( tmpLo
), mkexpr( rC
) ) );
6400 vex_printf("dis_int_mult(ppc): unrecognized instruction\n");
6404 putIReg( rD_addr
, mkexpr(rD
) );
6409 static Bool
dis_int_arith_prefix ( UInt prefix
, UInt theInstr
)
6412 UChar opc1
= ifieldOPC(theInstr
);
6413 UChar rT_addr
= ifieldRegDS(theInstr
);
6414 UChar rA_addr
= ifieldRegA(theInstr
);
6415 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
6416 IRTemp rA
= newTemp(ty
);
6417 IRTemp rT
= newTemp(ty
);
6418 IRTemp tmp
= newTemp(ty
);
6419 IRTemp value
= newTemp(ty
);
6420 ULong si0
= ifieldUIMM18(prefix
);
6421 ULong si1
= ifieldUIMM16(theInstr
); // AKA, SI
6422 UInt ptype
= PrefixType(prefix
);
6423 Long simm16
= extend_s_16to64(si1
);
6424 Bool is_prefix
= prefix_instruction( prefix
);
6425 UInt R
= 0; // must be zero for word instruction
6428 assign( value
, mkSzExtendS16( ty
, si1
));
6431 vassert( ty
== Ity_I64
); // prefix instructions must be 64-bit
6432 vassert( ptype
== pType2
);
6434 R
= ifieldR(prefix
);
6435 assign( value
, mkSzExtendS34( CONCAT( si0
, si1
, 16 )));
6438 assign( rA
, getIReg(rA_addr
) );
6443 case 0x0E: // addi (Add Immediate, PPC32 p350)
6444 // li rD,val == addi rD,0,val
6445 // la disp(rA) == addi rD,rA,disp
6447 if ( rA_addr
== 0 ) {
6448 pDIP(is_prefix
, "li r%u,%d", rT_addr
, (Int
)simm16
);
6450 assign( tmp
, mkexpr( value
) );
6453 pDIP(is_prefix
, "addi r%u,r%u,%d", rT_addr
, rA_addr
, (Int
)simm16
);
6454 DIPp(is_prefix
, ",%u", R
);
6455 assign( tmp
, binop( mkSzOp(ty
, Iop_Add8
), mkexpr( rA
), mkexpr( value
) ) );
6459 assign( rT
, mkexpr( tmp
) );
6461 /* Add immediate value from instruction to the current instruction addr.
6462 guest_CIA_curr_instr is pointing at the prefix, use address of the
6463 instruction prefix. */
6464 assign( rT
, binop( Iop_Add64
,
6465 mkU64( mkSzAddr( Ity_I64
, guest_CIA_curr_instr
) ),
6471 vex_printf("dis_int_arith_prefix(ppc)(opc1)\n");
6475 putIReg( rT_addr
, mkexpr(rT
) );
6480 static Bool
dis_int_arith ( UInt prefix
, UInt theInstr
)
6482 /* D-Form, XO-Form */
6483 UChar opc1
= ifieldOPC(theInstr
);
6484 UChar rD_addr
= ifieldRegDS(theInstr
);
6485 UChar rA_addr
= ifieldRegA(theInstr
);
6486 UInt uimm16
= ifieldUIMM16(theInstr
);
6487 UChar rB_addr
= ifieldRegB(theInstr
);
6488 UChar flag_OE
= ifieldBIT10(theInstr
);
6489 UInt opc2
= ifieldOPClo9(theInstr
);
6490 UChar flag_rC
= ifieldBIT0(theInstr
);
6492 Long simm16
= extend_s_16to64(uimm16
);
6493 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
6494 IRTemp rA
= newTemp(ty
);
6495 IRTemp rB
= newTemp(ty
);
6496 IRTemp rD
= newTemp(ty
);
6500 /* There is no prefixed version of these instructions. */
6503 assign( rA
, getIReg(rA_addr
) );
6504 assign( rB
, getIReg(rB_addr
) ); // XO-Form: rD, rA, rB
6508 case 0x0C: // addic (Add Immediate Carrying, PPC32 p351
6509 DIP("addic r%u,r%u,%d\n", rD_addr
, rA_addr
, (Int
)simm16
);
6510 assign( rD
, binop( mkSzOp(ty
, Iop_Add8
), mkexpr(rA
),
6511 mkSzExtendS16(ty
, uimm16
) ) );
6512 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_ADD
,
6513 mkexpr(rD
), mkexpr(rA
), mkSzExtendS16(ty
, uimm16
),
6514 mkSzImm(ty
, 0)/*old xer.ca, which is ignored*/ );
6517 case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352)
6518 DIP("addic. r%u,r%u,%d\n", rD_addr
, rA_addr
, (Int
)simm16
);
6519 assign( rD
, binop( mkSzOp(ty
, Iop_Add8
), mkexpr(rA
),
6520 mkSzExtendS16(ty
, uimm16
) ) );
6521 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_ADD
,
6522 mkexpr(rD
), mkexpr(rA
), mkSzExtendS16(ty
, uimm16
),
6523 mkSzImm(ty
, 0)/*old xer.ca, which is ignored*/ );
6524 do_rc
= True
; // Always record to CR
6528 case 0x0E: // addi (Add Immediate, PPC32 p350)
6529 // li rD,val == addi rD,0,val
6530 // la disp(rA) == addi rD,rA,disp
6531 if ( rA_addr
== 0 ) {
6532 DIP("li r%u,%d\n", rD_addr
, (Int
)simm16
);
6533 assign( rD
, mkSzExtendS16(ty
, uimm16
) );
6535 DIP("addi r%u,r%u,%d\n", rD_addr
, rA_addr
, (Int
)simm16
);
6536 assign( rD
, binop( mkSzOp(ty
, Iop_Add8
), mkexpr(rA
),
6537 mkSzExtendS16(ty
, uimm16
) ) );
6541 case 0x0F: // addis (Add Immediate Shifted, PPC32 p353)
6542 // lis rD,val == addis rD,0,val
6543 if ( rA_addr
== 0 ) {
6544 DIP("lis r%u,%d\n", rD_addr
, (Int
)simm16
);
6545 assign( rD
, mkSzExtendS32(ty
, uimm16
<< 16) );
6547 DIP("addis r%u,r%u,0x%x\n", rD_addr
, rA_addr
, (UInt
)simm16
);
6548 assign( rD
, binop( mkSzOp(ty
, Iop_Add8
), mkexpr(rA
),
6549 mkSzExtendS32(ty
, uimm16
<< 16) ) );
6553 case 0x07: // mulli (Multiply Low Immediate, PPC32 p490)
6554 DIP("mulli r%u,r%u,%d\n", rD_addr
, rA_addr
, (Int
)simm16
);
6556 assign( rD
, unop(Iop_128to64
,
6557 binop(Iop_MullS64
, mkexpr(rA
),
6558 mkSzExtendS16(ty
, uimm16
))) );
6560 assign( rD
, unop(Iop_64to32
,
6561 binop(Iop_MullS32
, mkexpr(rA
),
6562 mkSzExtendS16(ty
, uimm16
))) );
6565 case 0x08: // subfic (Subtract from Immediate Carrying, PPC32 p540)
6566 DIP("subfic r%u,r%u,%d\n", rD_addr
, rA_addr
, (Int
)simm16
);
6568 assign( rD
, binop( mkSzOp(ty
, Iop_Sub8
),
6569 mkSzExtendS16(ty
, uimm16
),
6571 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_SUBFI
,
6572 mkexpr(rD
), mkexpr(rA
), mkSzExtendS16(ty
, uimm16
),
6573 mkSzImm(ty
, 0)/*old xer.ca, which is ignored*/ );
6578 do_rc
= True
; // All below record to CR
6581 case 0x10A: // add (Add, PPC32 p347)
6582 DIP("add%s%s r%u,r%u,r%u\n",
6583 flag_OE
? "o" : "", flag_rC
? ".":"",
6584 rD_addr
, rA_addr
, rB_addr
);
6585 assign( rD
, binop( mkSzOp(ty
, Iop_Add8
),
6586 mkexpr(rA
), mkexpr(rB
) ) );
6588 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_ADD
,
6589 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
) );
6593 case 0x00A: // addc (Add Carrying, PPC32 p348)
6594 DIP("addc%s%s r%u,r%u,r%u\n",
6595 flag_OE
? "o" : "", flag_rC
? ".":"",
6596 rD_addr
, rA_addr
, rB_addr
);
6597 assign( rD
, binop( mkSzOp(ty
, Iop_Add8
),
6598 mkexpr(rA
), mkexpr(rB
)) );
6599 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_ADD
,
6600 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
),
6601 mkSzImm(ty
, 0)/*old xer.ca, which is ignored*/ );
6603 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_ADD
,
6604 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
) );
6608 case 0x08A: { // adde (Add Extended, PPC32 p349)
6609 IRTemp old_xer_ca
= newTemp(ty
);
6610 DIP("adde%s%s r%u,r%u,r%u\n",
6611 flag_OE
? "o" : "", flag_rC
? ".":"",
6612 rD_addr
, rA_addr
, rB_addr
);
6613 // rD = rA + rB + XER[CA]
6614 assign( old_xer_ca
, mkWidenFrom32(ty
, getXER_CA_32(), False
) );
6615 assign( rD
, binop( mkSzOp(ty
, Iop_Add8
), mkexpr(rA
),
6616 binop( mkSzOp(ty
, Iop_Add8
),
6617 mkexpr(rB
), mkexpr(old_xer_ca
))) );
6618 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_ADDE
,
6619 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
),
6620 mkexpr(old_xer_ca
) );
6622 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_ADDE
,
6623 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
) );
6628 case 0xAA: {// addex (Add Extended alternate carry bit Z23-form)
6629 IRTemp old_xer_ov
= newTemp(ty
);
6630 DIP("addex r%u,r%u,r%u,%d\n", rD_addr
, rA_addr
, rB_addr
, (Int
)flag_OE
);
6631 assign( old_xer_ov
, mkWidenFrom32(ty
, getXER_OV_32(), False
) );
6632 assign( rD
, binop( mkSzOp(ty
, Iop_Add8
), mkexpr(rA
),
6633 binop( mkSzOp(ty
, Iop_Add8
), mkexpr(rB
),
6634 mkexpr(old_xer_ov
) ) ) );
6636 /* CY bit is same as OE bit */
6638 /* Exception, do not set SO bit and set OV from carry. */
6639 set_XER_OV_OV32_ADDEX( ty
, mkexpr(rD
), mkexpr(rA
), mkexpr(rB
),
6640 mkexpr(old_xer_ov
) );
6642 /* CY=1, 2 and 3 (AKA flag_OE) are reserved */
6643 vex_printf("addex instruction, CY = %d is reserved.\n", flag_OE
);
6644 vpanic("addex instruction\n");
6649 case 0x0EA: { // addme (Add to Minus One Extended, PPC32 p354)
6650 IRTemp old_xer_ca
= newTemp(ty
);
6653 vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n");
6656 DIP("addme%s%s r%u,r%u,r%u\n",
6657 flag_OE
? "o" : "", flag_rC
? ".":"",
6658 rD_addr
, rA_addr
, rB_addr
);
6659 // rD = rA + (-1) + XER[CA]
6660 // => Just another form of adde
6661 assign( old_xer_ca
, mkWidenFrom32(ty
, getXER_CA_32(), False
) );
6662 min_one
= mkSzImm(ty
, (Long
)-1);
6663 assign( rD
, binop( mkSzOp(ty
, Iop_Add8
), mkexpr(rA
),
6664 binop( mkSzOp(ty
, Iop_Add8
),
6665 min_one
, mkexpr(old_xer_ca
)) ));
6666 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_ADDE
,
6667 mkexpr(rD
), mkexpr(rA
), min_one
,
6668 mkexpr(old_xer_ca
) );
6670 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_ADDE
,
6671 mkexpr(rD
), mkexpr(rA
), min_one
);
6676 case 0x0CA: { // addze (Add to Zero Extended, PPC32 p355)
6677 IRTemp old_xer_ca
= newTemp(ty
);
6679 vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n");
6682 DIP("addze%s%s r%u,r%u,r%u\n",
6683 flag_OE
? "o" : "", flag_rC
? ".":"",
6684 rD_addr
, rA_addr
, rB_addr
);
6685 // rD = rA + (0) + XER[CA]
6686 // => Just another form of adde
6687 assign( old_xer_ca
, mkWidenFrom32(ty
, getXER_CA_32(), False
) );
6688 assign( rD
, binop( mkSzOp(ty
, Iop_Add8
),
6689 mkexpr(rA
), mkexpr(old_xer_ca
)) );
6690 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_ADDE
,
6691 mkexpr(rD
), mkexpr(rA
), mkSzImm(ty
, 0),
6692 mkexpr(old_xer_ca
) );
6694 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_ADDE
,
6695 mkexpr(rD
), mkexpr(rA
), mkSzImm(ty
, 0) );
6700 case 0x1EB: // divw (Divide Word, PPC32 p388)
6701 DIP("divw%s%s r%u,r%u,r%u\n",
6702 flag_OE
? "o" : "", flag_rC
? ".":"",
6703 rD_addr
, rA_addr
, rB_addr
);
6706 XER settings are mode independent, and reflect the
6707 overflow of the low-order 32bit result
6708 CR0[LT|GT|EQ] are undefined if flag_rC && mode64
6710 /* rD[hi32] are undefined: setting them to sign of lo32
6711 - makes set_CR0 happy */
6712 IRExpr
* dividend
= mk64lo32Sto64( mkexpr(rA
) );
6713 IRExpr
* divisor
= mk64lo32Sto64( mkexpr(rB
) );
6714 assign( rD
, mk64lo32Uto64( binop(Iop_DivS64
, dividend
,
6717 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_DIVW
,
6718 mkexpr(rD
), dividend
, divisor
);
6721 assign( rD
, binop(Iop_DivS32
, mkexpr(rA
), mkexpr(rB
)) );
6723 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_DIVW
,
6724 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
) );
6728 if (0x8000_0000 / -1) or (x / 0)
6729 => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
6730 => But _no_ exception raised. */
6733 case 0x1CB: // divwu (Divide Word Unsigned, PPC32 p389)
6734 DIP("divwu%s%s r%u,r%u,r%u\n",
6735 flag_OE
? "o" : "", flag_rC
? ".":"",
6736 rD_addr
, rA_addr
, rB_addr
);
6739 XER settings are mode independent, and reflect the
6740 overflow of the low-order 32bit result
6741 CR0[LT|GT|EQ] are undefined if flag_rC && mode64
6743 IRExpr
* dividend
= mk64lo32Uto64( mkexpr(rA
) );
6744 IRExpr
* divisor
= mk64lo32Uto64( mkexpr(rB
) );
6745 assign( rD
, mk64lo32Uto64( binop(Iop_DivU64
, dividend
,
6748 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_DIVWU
,
6749 mkexpr(rD
), dividend
, divisor
);
6752 assign( rD
, binop(Iop_DivU32
, mkexpr(rA
), mkexpr(rB
)) );
6754 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_DIVWU
,
6755 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
) );
6758 /* Note: ditto comment divw, for (x / 0) */
6761 case 0x04B: // mulhw (Multiply High Word, PPC32 p488)
6763 vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n");
6766 DIP("mulhw%s r%u,r%u,r%u\n", flag_rC
? ".":"",
6767 rD_addr
, rA_addr
, rB_addr
);
6769 /* rD[hi32] are undefined: setting them to sign of lo32
6770 - makes set_CR0 happy */
6771 assign( rD
, binop(Iop_Sar64
,
6773 mk64lo32Sto64( mkexpr(rA
) ),
6774 mk64lo32Sto64( mkexpr(rB
) )),
6777 assign( rD
, unop(Iop_64HIto32
,
6779 mkexpr(rA
), mkexpr(rB
))) );
6783 case 0x00B: // mulhwu (Multiply High Word Unsigned, PPC32 p489)
6785 vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n");
6788 DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC
? ".":"",
6789 rD_addr
, rA_addr
, rB_addr
);
6791 /* rD[hi32] are undefined: setting them to sign of lo32
6792 - makes set_CR0 happy */
6793 assign( rD
, binop(Iop_Sar64
,
6795 mk64lo32Uto64( mkexpr(rA
) ),
6796 mk64lo32Uto64( mkexpr(rB
) ) ),
6799 assign( rD
, unop(Iop_64HIto32
,
6801 mkexpr(rA
), mkexpr(rB
))) );
6805 case 0x0EB: // mullw (Multiply Low Word, PPC32 p491)
6806 DIP("mullw%s%s r%u,r%u,r%u\n",
6807 flag_OE
? "o" : "", flag_rC
? ".":"",
6808 rD_addr
, rA_addr
, rB_addr
);
6810 /* rD[hi32] are undefined: setting them to sign of lo32
6811 - set_XER_OV() and set_CR0() depend on this */
6812 IRExpr
*a
= unop(Iop_64to32
, mkexpr(rA
) );
6813 IRExpr
*b
= unop(Iop_64to32
, mkexpr(rB
) );
6814 assign( rD
, binop(Iop_MullS32
, a
, b
) );
6816 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_MULLW
,
6818 unop(Iop_32Uto64
, a
), unop(Iop_32Uto64
, b
) );
6821 assign( rD
, unop(Iop_64to32
,
6823 mkexpr(rA
), mkexpr(rB
))) );
6825 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_MULLW
,
6826 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
) );
6831 case 0x068: // neg (Negate, PPC32 p493)
6833 vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n");
6836 DIP("neg%s%s r%u,r%u\n",
6837 flag_OE
? "o" : "", flag_rC
? ".":"",
6840 assign( rD
, binop( mkSzOp(ty
, Iop_Add8
),
6841 unop( mkSzOp(ty
, Iop_Not8
), mkexpr(rA
) ),
6844 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_NEG
,
6845 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
) );
6849 case 0x028: // subf (Subtract From, PPC32 p537)
6850 DIP("subf%s%s r%u,r%u,r%u\n",
6851 flag_OE
? "o" : "", flag_rC
? ".":"",
6852 rD_addr
, rA_addr
, rB_addr
);
6854 assign( rD
, binop( mkSzOp(ty
, Iop_Sub8
),
6855 mkexpr(rB
), mkexpr(rA
)) );
6857 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_SUBF
,
6858 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
) );
6862 case 0x008: // subfc (Subtract from Carrying, PPC32 p538)
6863 DIP("subfc%s%s r%u,r%u,r%u\n",
6864 flag_OE
? "o" : "", flag_rC
? ".":"",
6865 rD_addr
, rA_addr
, rB_addr
);
6867 assign( rD
, binop( mkSzOp(ty
, Iop_Sub8
),
6868 mkexpr(rB
), mkexpr(rA
)) );
6869 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_SUBFC
,
6870 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
),
6871 mkSzImm(ty
, 0)/*old xer.ca, which is ignored*/ );
6873 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_SUBFC
,
6874 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
) );
6878 case 0x088: {// subfe (Subtract from Extended, PPC32 p539)
6879 IRTemp old_xer_ca
= newTemp(ty
);
6880 DIP("subfe%s%s r%u,r%u,r%u\n",
6881 flag_OE
? "o" : "", flag_rC
? ".":"",
6882 rD_addr
, rA_addr
, rB_addr
);
6883 // rD = (log not)rA + rB + XER[CA]
6885 // rD = rB - rA - (XER[CA] ^ 1)
6886 assign( old_xer_ca
, mkWidenFrom32(ty
, getXER_CA_32(), False
) );
6887 assign( rD
, binop( mkSzOp(ty
, Iop_Sub8
),
6888 binop( mkSzOp(ty
, Iop_Sub8
),
6889 mkexpr(rB
), mkexpr(rA
)),
6890 binop(mkSzOp(ty
, Iop_Xor8
),
6893 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_SUBFE
,
6894 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
),
6895 mkexpr(old_xer_ca
) );
6897 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_SUBFE
,
6898 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
) );
6903 case 0x0E8: { // subfme (Subtract from -1 Extended, PPC32 p541)
6904 IRTemp old_xer_ca
= newTemp(ty
);
6907 vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n");
6910 DIP("subfme%s%s r%u,r%u\n",
6911 flag_OE
? "o" : "", flag_rC
? ".":"",
6913 // rD = (log not)rA + (-1) + XER[CA]
6914 // => Just another form of subfe
6915 assign( old_xer_ca
, mkWidenFrom32(ty
, getXER_CA_32(), False
) );
6916 min_one
= mkSzImm(ty
, (Long
)-1);
6917 assign( rD
, binop( mkSzOp(ty
, Iop_Add8
),
6918 unop( mkSzOp(ty
, Iop_Not8
), mkexpr(rA
)),
6919 binop( mkSzOp(ty
, Iop_Add8
),
6920 min_one
, mkexpr(old_xer_ca
))) );
6921 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_SUBFE
,
6922 mkexpr(rD
), mkexpr(rA
), min_one
,
6923 mkexpr(old_xer_ca
) );
6925 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_SUBFE
,
6926 mkexpr(rD
), mkexpr(rA
), min_one
);
6931 case 0x0C8: { // subfze (Subtract from Zero Extended, PPC32 p542)
6932 IRTemp old_xer_ca
= newTemp(ty
);
6934 vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n");
6937 DIP("subfze%s%s r%u,r%u\n",
6938 flag_OE
? "o" : "", flag_rC
? ".":"",
6940 // rD = (log not)rA + (0) + XER[CA]
6941 // => Just another form of subfe
6942 assign( old_xer_ca
, mkWidenFrom32(ty
, getXER_CA_32(), False
) );
6943 assign( rD
, binop( mkSzOp(ty
, Iop_Add8
),
6944 unop( mkSzOp(ty
, Iop_Not8
),
6945 mkexpr(rA
)), mkexpr(old_xer_ca
)) );
6946 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_SUBFE
,
6947 mkexpr(rD
), mkexpr(rA
), mkSzImm(ty
, 0),
6948 mkexpr(old_xer_ca
) );
6950 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_SUBFE
,
6951 mkexpr(rD
), mkexpr(rA
), mkSzImm(ty
, 0) );
6957 /* 64bit Arithmetic */
6958 case 0x49: // mulhd (Multiply High DWord, PPC64 p539)
6960 vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n");
6963 DIP("mulhd%s r%u,r%u,r%u\n", flag_rC
? ".":"",
6964 rD_addr
, rA_addr
, rB_addr
);
6965 assign( rD
, unop(Iop_128HIto64
,
6967 mkexpr(rA
), mkexpr(rB
))) );
6971 case 0x9: // mulhdu (Multiply High DWord Unsigned, PPC64 p540)
6973 vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n");
6976 DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC
? ".":"",
6977 rD_addr
, rA_addr
, rB_addr
);
6978 assign( rD
, unop(Iop_128HIto64
,
6980 mkexpr(rA
), mkexpr(rB
))) );
6983 case 0xE9: // mulld (Multiply Low DWord, PPC64 p543)
6984 DIP("mulld%s%s r%u,r%u,r%u\n",
6985 flag_OE
? "o" : "", flag_rC
? ".":"",
6986 rD_addr
, rA_addr
, rB_addr
);
6987 assign( rD
, binop(Iop_Mul64
, mkexpr(rA
), mkexpr(rB
)) );
6989 set_XER_OV_64( PPCG_FLAG_OP_MULLD
,
6990 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
) );
6991 /* OV is set to 1 if product isn't representable.
6992 * In this case also need to set OV32 and SO to 1,
6993 * i.e. copy OV to OV32 and SO.
7000 case 0x1E9: // divd (Divide DWord, PPC64 p419)
7001 DIP("divd%s%s r%u,r%u,r%u\n",
7002 flag_OE
? "o" : "", flag_rC
? ".":"",
7003 rD_addr
, rA_addr
, rB_addr
);
7004 assign( rD
, binop(Iop_DivS64
, mkexpr(rA
), mkexpr(rB
)) );
7006 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_DIVW
,
7007 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
) );
7011 if (0x8000_0000_0000_0000 / -1) or (x / 0)
7012 => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
7013 => But _no_ exception raised. */
7015 case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420)
7016 DIP("divdu%s%s r%u,r%u,r%u\n",
7017 flag_OE
? "o" : "", flag_rC
? ".":"",
7018 rD_addr
, rA_addr
, rB_addr
);
7019 assign( rD
, binop(Iop_DivU64
, mkexpr(rA
), mkexpr(rB
)) );
7021 set_XER_OV_OV32_SO( ty
, PPCG_FLAG_OP_DIVWU
,
7022 mkexpr(rD
), mkexpr(rA
), mkexpr(rB
) );
7025 /* Note: ditto comment divd, for (x / 0) */
7027 case 0x18B: // divweu (Divide Word Extended Unsigned)
7030 * If (RA) >= (RB), or if an attempt is made to perform the division
7032 * then the contents of register RD are undefined as are (if Rc=1) the contents of
7033 * the LT, GT, and EQ bits of CR Field 0. In these cases, if OE=1 then OV is set
7036 IRTemp res
= newTemp(Ity_I32
);
7037 IRExpr
* dividend
, * divisor
;
7038 DIP("divweu%s%s r%u,r%u,r%u\n",
7039 flag_OE
? "o" : "", flag_rC
? ".":"",
7040 rD_addr
, rA_addr
, rB_addr
);
7042 dividend
= unop( Iop_64to32
, mkexpr( rA
) );
7043 divisor
= unop( Iop_64to32
, mkexpr( rB
) );
7044 assign( res
, binop( Iop_DivU32E
, dividend
, divisor
) );
7045 assign( rD
, binop( Iop_32HLto64
, mkU32( 0 ), mkexpr( res
) ) );
7047 dividend
= mkexpr( rA
);
7048 divisor
= mkexpr( rB
);
7049 assign( res
, binop( Iop_DivU32E
, dividend
, divisor
) );
7050 assign( rD
, mkexpr( res
) );
7054 set_XER_OV_OV32_32( PPCG_FLAG_OP_DIVWEU
,
7055 mkexpr(res
), dividend
, divisor
);
7061 case 0x1AB: // divwe (Divide Word Extended)
7064 * If the quotient cannot be represented in 32 bits, or if an
7065 * attempt is made to perform the division
7067 * then the contents of register RD are undefined as are (if
7068 * Rc=1) the contents of the LT, GT, and EQ bits of CR
7069 * Field 0. In these cases, if OE=1 then OV is set to 1.
7072 IRTemp res
= newTemp(Ity_I32
);
7073 IRExpr
* dividend
, * divisor
;
7074 DIP("divwe%s%s r%u,r%u,r%u\n",
7075 flag_OE
? "o" : "", flag_rC
? ".":"",
7076 rD_addr
, rA_addr
, rB_addr
);
7078 dividend
= unop( Iop_64to32
, mkexpr( rA
) );
7079 divisor
= unop( Iop_64to32
, mkexpr( rB
) );
7080 assign( res
, binop( Iop_DivS32E
, dividend
, divisor
) );
7081 assign( rD
, binop( Iop_32HLto64
, mkU32( 0 ), mkexpr( res
) ) );
7083 dividend
= mkexpr( rA
);
7084 divisor
= mkexpr( rB
);
7085 assign( res
, binop( Iop_DivS32E
, dividend
, divisor
) );
7086 assign( rD
, mkexpr( res
) );
7090 set_XER_OV_OV32_32( PPCG_FLAG_OP_DIVWE
,
7091 mkexpr(res
), dividend
, divisor
);
7098 case 0x1A9: // divde (Divide Doubleword Extended)
7100 * If the quotient cannot be represented in 64 bits, or if an
7101 * attempt is made to perform the division
7103 * then the contents of register RD are undefined as are (if
7104 * Rc=1) the contents of the LT, GT, and EQ bits of CR
7105 * Field 0. In these cases, if OE=1 then OV is set to 1.
7107 DIP("divde%s%s r%u,r%u,r%u\n",
7108 flag_OE
? "o" : "", flag_rC
? ".":"",
7109 rD_addr
, rA_addr
, rB_addr
);
7110 assign( rD
, binop(Iop_DivS64E
, mkexpr(rA
), mkexpr(rB
)) );
7112 set_XER_OV_64( PPCG_FLAG_OP_DIVDE
, mkexpr( rD
),
7113 mkexpr( rA
), mkexpr( rB
) );
7119 case 0x189: // divdeuo (Divide Doubleword Extended Unsigned)
7120 // Same CR and OV rules as given for divweu above
7121 DIP("divdeu%s%s r%u,r%u,r%u\n",
7122 flag_OE
? "o" : "", flag_rC
? ".":"",
7123 rD_addr
, rA_addr
, rB_addr
);
7124 assign( rD
, binop(Iop_DivU64E
, mkexpr(rA
), mkexpr(rB
)) );
7126 set_XER_OV_64( PPCG_FLAG_OP_DIVDEU
, mkexpr( rD
),
7127 mkexpr( rA
), mkexpr( rB
) );
7134 vex_printf("dis_int_arith(ppc)(opc2)\n");
7140 vex_printf("dis_int_arith(ppc)(opc1)\n");
7144 putIReg( rD_addr
, mkexpr(rD
) );
7146 if (do_rc
&& flag_rC
) {
7147 set_CR0( mkexpr(rD
) );
7152 static Bool
dis_modulo_int ( UInt prefix
, UInt theInstr
)
7155 UChar opc1
= ifieldOPC( theInstr
);
7156 UInt opc2
= ifieldOPClo10( theInstr
);
7157 UChar rA_addr
= ifieldRegA( theInstr
);
7158 UChar rB_addr
= ifieldRegB( theInstr
);
7159 UChar rD_addr
= ifieldRegDS( theInstr
);
7160 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
7161 IRTemp rD
= newTemp( ty
);
7163 /* There is no prefixed version of these instructions. */
7170 case 0x109: // modud Modulo Unsigned Double Word
7172 IRTemp rA
= newTemp( Ity_I64
);
7173 IRTemp rB
= newTemp( Ity_I64
);
7174 IRTemp quotient
= newTemp( Ity_I64
);
7175 IRTemp quotientTimesDivisor
= newTemp( Ity_I64
);
7176 IRTemp remainder
= newTemp( Ity_I64
);
7177 IRTemp rB_0
= newTemp( Ity_I64
); /* all 1's if rB = 0 */
7179 DIP("modud r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
7181 assign( rA
, getIReg( rA_addr
) );
7182 assign( rB
, getIReg( rB_addr
) );
7185 binop( Iop_DivU64
, mkexpr( rA
), mkexpr( rB
) ) );
7187 assign( quotientTimesDivisor
,
7195 mkexpr( quotientTimesDivisor
) ) );
7197 /* Need to match the HW for these special cases
7198 * rB = 0 result all zeros
7200 assign( rB_0
, unop( Iop_1Sto64
,
7205 assign (rD
, binop( Iop_And64
,
7206 unop( Iop_Not64
, mkexpr( rB_0
) ),
7207 mkexpr( remainder
) ) );
7211 case 0x10B: // moduw Modulo Unsigned Word
7213 IRTemp quotient
= newTemp( Ity_I32
);
7214 IRTemp quotientTimesDivisor
= newTemp( Ity_I32
);
7215 IRTemp remainder
= newTemp( Ity_I32
);
7217 IRTemp rA
= newTemp( Ity_I32
);
7218 IRTemp rB
= newTemp( Ity_I32
);
7219 IRTemp rB_0
= newTemp( Ity_I32
); /* all 1's if rB = 0 */
7221 DIP("moduw r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
7223 if ( ty
== Ity_I64
) {
7224 /* rA and rB are 32 bit values in bits 32:63 of the
7227 assign( rA
, unop( Iop_64to32
, getIReg( rA_addr
) ) );
7228 assign( rB
, unop( Iop_64to32
, getIReg( rB_addr
) ) );
7231 assign( rA
, getIReg( rA_addr
) );
7232 assign( rB
, getIReg( rB_addr
) );
7236 binop( Iop_DivU32
, mkexpr( rA
), mkexpr( rB
) ) );
7238 assign( quotientTimesDivisor
,
7247 mkexpr( quotientTimesDivisor
) ) );
7249 /* Need to match the HW for these special cases
7250 * rB = 0 result all zeros
7252 assign( rB_0
, unop( Iop_1Sto32
,
7257 assign (rD
, binop( Iop_32HLto64
,
7260 unop( Iop_Not32
, mkexpr( rB_0
) ),
7261 mkexpr( remainder
) ) ) );
7265 case 0x21A: // cnttzw, cnttzw. Count Trailing Zero Word
7267 /* Note cnttzw RA, RS - RA is dest, RS is source. But the
7268 * order of the operands in theInst is opc1 RS RA opc2 which has
7269 * the operand fields backwards to what the standard order.
7271 UChar rA_address
= ifieldRegA(theInstr
);
7272 UChar rS_address
= ifieldRegDS(theInstr
);
7273 IRTemp rA
= newTemp(Ity_I64
);
7274 IRTemp rS
= newTemp(Ity_I64
);
7275 UChar flag_rC
= ifieldBIT0(theInstr
);
7276 IRTemp result
= newTemp(Ity_I32
);
7278 DIP("cnttzw%s r%u,r%u\n", flag_rC
? "." : "",
7279 rA_address
, rS_address
);
7281 assign( rS
, getIReg( rS_address
) );
7282 assign( result
, unop( Iop_CtzNat32
,
7283 unop( Iop_64to32
, mkexpr( rS
) ) ) );
7284 assign( rA
, binop( Iop_32HLto64
, mkU32( 0 ), mkexpr( result
) ) );
7287 set_CR0( mkexpr( rA
) );
7289 putIReg( rA_address
, mkexpr( rA
) );
7291 return True
; /* Return here since this inst is not consistent
7292 * with the other instructions
7297 case 0x23A: // cnttzd, cnttzd. Count Trailing Zero Double word
7299 /* Note cnttzd RA, RS - RA is dest, RS is source. But the
7300 * order of the operands in theInst is opc1 RS RA opc2 which has
7301 * the operand order listed backwards to what is standard.
7303 UChar rA_address
= ifieldRegA(theInstr
);
7304 UChar rS_address
= ifieldRegDS(theInstr
);
7305 IRTemp rA
= newTemp(Ity_I64
);
7306 IRTemp rS
= newTemp(Ity_I64
);
7307 UChar flag_rC
= ifieldBIT0(theInstr
);
7309 DIP("cnttzd%s r%u,r%u\n", flag_rC
? "." : "",
7310 rA_address
, rS_address
);
7312 assign( rS
, getIReg( rS_address
) );
7313 assign( rA
, unop( Iop_CtzNat64
, mkexpr( rS
) ) );
7316 set_CR0( mkexpr( rA
) );
7318 putIReg( rA_address
, mkexpr( rA
) );
7320 return True
; /* Return here since this inst is not consistent
7321 * with the other instructions
7326 case 0x309: // modsd Modulo Signed Double Word
7328 IRTemp rA
= newTemp( Ity_I64
);
7329 IRTemp rB
= newTemp( Ity_I64
);
7330 IRTemp rA2_63
= newTemp( Ity_I64
); /* all 1's if rA != -2^63 */
7331 IRTemp rB_0
= newTemp( Ity_I1
); /* 1 if rB = 0 */
7332 IRTemp rB_1
= newTemp( Ity_I1
); /* 1 if rB = 1 */
7333 IRTemp rB_m1
= newTemp( Ity_I1
); /* 1 if rB = -1 */
7334 IRTemp rA_m1
= newTemp( Ity_I1
); /* 1 if rA = -1 */
7335 IRTemp resultis0
= newTemp( Ity_I64
);
7336 IRTemp quotient
= newTemp( Ity_I64
);
7337 IRTemp quotientTimesDivisor
= newTemp( Ity_I64
);
7338 IRTemp remainder
= newTemp( Ity_I64
);
7340 DIP("modsd r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
7342 assign( rA
, getIReg( rA_addr
) );
7343 assign( rB
, getIReg( rB_addr
) );
7345 assign( rA2_63
, unop ( Iop_1Sto64
,
7348 mkU64( 0x8000000000000000 ) ) ) );
7349 assign( rB_0
, binop( Iop_CmpEQ64
,
7353 assign( rB_1
, binop( Iop_CmpEQ64
,
7357 assign( rB_m1
, binop( Iop_CmpEQ64
,
7359 mkU64( 0xFFFFFFFFFFFFFFFF ) ) );
7361 assign( rA_m1
, binop( Iop_CmpEQ64
,
7363 mkU64( 0xFFFFFFFFFFFFFFFF ) ) );
7365 /* Need to match the HW for these special cases
7366 rA = -2^31 and rB = -1 result all zeros
7367 rA = -1 and rB = -1 result all zeros
7369 if an attempt is made to perform any of the divisions:
7372 result is undefined. Force result to zero to match the
7380 unop( Iop_1Sto64
, mkexpr( rA_m1
) ),
7381 unop( Iop_1Sto64
, mkexpr( rB_1
) ) ),
7382 /* rA % 0 (division by zero) */
7383 unop( Iop_1Sto64
, mkexpr( rB_0
) ) ),
7389 mkexpr( rB_m1
) ) ),
7392 unop( Iop_1Sto64
, mkexpr( rA_m1
) ),
7393 unop( Iop_1Sto64
, mkexpr( rB_m1
) )
7396 /* The following remainder computation works as long as
7397 * rA != -2^63 and rB != -1.
7400 binop( Iop_DivS64
, mkexpr( rA
), mkexpr( rB
) ) );
7402 assign( quotientTimesDivisor
,
7410 mkexpr( quotientTimesDivisor
) ) );
7412 assign( rD
, binop( Iop_And64
,
7413 mkexpr( remainder
),
7415 mkexpr( resultis0
) ) ) );
7418 case 0x30B: // modsw Modulo Signed Word
7420 IRTemp rA
= newTemp( Ity_I32
);
7421 IRTemp rB
= newTemp( Ity_I32
);
7422 IRTemp rA2_32
= newTemp( Ity_I32
); /* all 1's if rA = -2^32 */
7423 IRTemp rB_0
= newTemp( Ity_I1
); /* 1 if rB = 0 */
7424 IRTemp rB_1
= newTemp( Ity_I1
); /* 1 if rB = 1 */
7425 IRTemp rB_m1
= newTemp( Ity_I1
); /* 1 if rB = -1, 0xFFFFFFFF */
7426 IRTemp rA_m1
= newTemp( Ity_I1
); /* 1 if rA = -1, 0xFFFFFFFF */
7427 IRTemp resultis0
= newTemp( Ity_I32
);
7428 IRTemp quotient
= newTemp( Ity_I32
);
7429 IRTemp quotientTimesDivisor
= newTemp( Ity_I32
);
7430 IRTemp remainder
= newTemp( Ity_I32
);
7432 DIP("modsw r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
7434 if ( ty
== Ity_I64
) {
7435 /* rA and rB are 32 bit values in bits 32:63 of the
7438 assign( rA
, unop(Iop_64to32
, getIReg(rA_addr
) ) );
7439 assign( rB
, unop(Iop_64to32
, getIReg(rB_addr
) ) );
7442 assign( rA
, getIReg(rA_addr
) );
7443 assign( rB
, getIReg(rB_addr
) );
7446 assign( rA2_32
, unop( Iop_1Sto32
,
7449 mkU32( 0x80000000 ) ) ) );
7450 /* If the divisor is zero, then the result is undefined.
7451 * However, we will make the result be zero to match what
7452 * the hardware does.
7454 assign( rB_0
, binop( Iop_CmpEQ32
,
7458 assign( rB_1
, binop( Iop_CmpEQ32
,
7460 mkU32( 0x00000001 ) ) );
7462 assign( rB_m1
, binop( Iop_CmpEQ32
,
7464 mkU32( 0xFFFFFFFF ) ) );
7466 assign( rA_m1
, binop( Iop_CmpEQ32
,
7468 mkU32( 0xFFFFFFFF ) ) );
7470 /* Need to match the HW for these special cases
7471 rA = -2^31 and rB = -1 result all zeros
7472 rA = -1 and rB = -1 result all zeros
7473 rA = -1 and rB = 1 result all zeros
7475 if an attempt is made to perform any of the divisions:
7478 result is undefined. Force result to zero to match the
7486 unop( Iop_1Sto32
, mkexpr( rA_m1
) ),
7487 unop( Iop_1Sto32
, mkexpr( rB_1
) ) ),
7488 /* rA % 0 (division by zero) */
7489 unop( Iop_1Sto32
, mkexpr( rB_0
) ) ),
7492 /* 0x8000000 % -1 */
7496 mkexpr( rB_m1
) ) ),
7499 unop( Iop_1Sto32
, mkexpr( rA_m1
) ),
7500 unop( Iop_1Sto32
, mkexpr( rB_m1
) )
7503 /* The following remainder computation works as long as
7504 * rA != -2^31 and rB != -1.
7507 binop( Iop_DivS32
, mkexpr( rA
), mkexpr( rB
) ) );
7509 assign( quotientTimesDivisor
,
7518 mkexpr( quotientTimesDivisor
) ) );
7520 assign( rD
, binop( Iop_32HLto64
,
7523 mkexpr( remainder
),
7525 mkexpr( resultis0
) ) ) ) );
7530 vex_printf("dis_modulo_int(ppc)(opc2)\n");
7536 vex_printf("dis_modulo_int(ppc)(opc1)\n");
7540 putIReg( rD_addr
, mkexpr( rD
) );
7547 Byte Compare Instructions
7549 static Bool
dis_byte_cmp ( UInt prefix
, UInt theInstr
)
7552 UChar opc1
= ifieldOPC(theInstr
);
7553 UInt opc2
= ifieldOPClo10(theInstr
);
7554 UChar rA_addr
= ifieldRegA(theInstr
);
7555 UChar rB_addr
= ifieldRegB(theInstr
);
7556 IRTemp rA
= newTemp(Ity_I64
);
7557 IRTemp rB
= newTemp(Ity_I64
);
7558 UChar L
= toUChar( IFIELD( theInstr
, 21, 1 ) );
7559 UChar BF
= toUChar( IFIELD( theInstr
, 23, 3 ) );
7561 /* There is no prefixed version of these instructions. */
7564 assign( rA
, getIReg(rA_addr
) );
7565 assign( rB
, getIReg(rB_addr
) );
7568 vex_printf("dis_byte_cmp(ppc)(opc1)\n");
7573 case 0xc0: // cmprb (Compare Ranged Byte)
7576 IRExpr
*hi_1
, *lo_1
, *hi_2
, *lo_2
;
7577 IRExpr
*inrange_1
, *inrange_2
;
7579 DIP("cmprb %u,%u,r%u,r%u\n", BF
, L
, rA_addr
, rB_addr
);
7581 hi_1
= binop( Iop_Shr64
,
7584 mkU64( 0xFF000000 ) ),
7586 lo_1
= binop( Iop_Shr64
,
7589 mkU64( 0xFF0000 ) ) ,
7591 hi_2
= binop( Iop_Shr64
,
7596 lo_2
= binop( Iop_And64
,
7599 value
= binop( Iop_And64
,
7603 inrange_1
= mkAND1( binop( Iop_CmpLE64U
, value
, hi_1
),
7604 mkNOT1( binop( Iop_CmpLT64U
, value
, lo_1
) ) );
7605 inrange_2
= mkAND1( binop( Iop_CmpLE64U
, value
, hi_2
),
7606 mkNOT1( binop( Iop_CmpLT64U
, value
, lo_2
) ) );
7608 putGST_field( PPC_GST_CR
,
7611 unop( Iop_1Uto32
, inrange_2
),
7614 unop( Iop_1Uto32
, inrange_1
) ) ),
7620 case 0xE0: // cmpeqb (Compare Equal Byte)
7626 DIP("cmpeqb %u,r%u,r%u\n", BF
, rA_addr
, rB_addr
);
7628 value
= binop( Iop_And64
,
7632 tmp
[0] = newTemp(Ity_I32
);
7633 assign( tmp
[0], mkU32( 0 ) );
7635 for(i
= 0; i
< 8; i
++) {
7636 tmp
[i
+1] = newTemp(Ity_I32
);
7637 assign( tmp
[i
+1], binop( Iop_Or32
,
7645 mkU64( 0xFF ) ) ) ),
7646 mkexpr( tmp
[i
] ) ) );
7649 putGST_field( PPC_GST_CR
,
7652 mkNOT1( binop( Iop_CmpEQ32
,
7661 vex_printf("dis_byte_cmp(ppc)(opc2)\n");
7668 * Integer Miscellaneous instructions
7670 static Bool
dis_int_misc ( UInt prefix
, UInt theInstr
)
7672 Int wc
= IFIELD(theInstr
, 21, 2);
7673 UChar opc1
= ifieldOPC(theInstr
);
7674 UInt opc2
= ifieldOPClo10(theInstr
);
7676 /* There is no prefixed version of these instructions. */
7679 if ( opc1
!= 0x1F ) {
7680 vex_printf("dis_modulo_int(ppc)(opc1)\n");
7685 case 0x01E: // wait, (X-from)
7686 DIP("wait %d\n", wc
);
7688 /* The wait instruction causes instruction fetching and execution
7689 * to be suspended. Instruction fetching and execution are resumed
7690 * when the events specified by the WC field occur.
7692 * 0b00 Resume instruction fetching and execution when an
7693 * exception or an event-based branch exception occurs,
7694 * or a resume signal from the platform is recieved.
7698 * For our purposes, we will just assume the contition is always
7699 * immediately satisfied.
7703 vex_printf("dis_int_misc(ppc)(opc2)\n");
7711 Integer Compare Instructions
7713 static Bool
dis_int_cmp ( UInt prefix
, UInt theInstr
)
7715 /* D-Form, X-Form */
7716 UChar opc1
= ifieldOPC(theInstr
);
7717 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) );
7718 UChar b22
= toUChar( IFIELD( theInstr
, 22, 1 ) );
7719 UChar flag_L
= toUChar( IFIELD( theInstr
, 21, 1 ) );
7720 UChar rA_addr
= ifieldRegA(theInstr
);
7721 UInt uimm16
= ifieldUIMM16(theInstr
);
7722 UChar rB_addr
= ifieldRegB(theInstr
);
7723 UInt opc2
= ifieldOPClo10(theInstr
);
7724 UChar b0
= ifieldBIT0(theInstr
);
7726 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
7727 IRExpr
*a
= getIReg(rA_addr
);
7730 /* There is no prefixed version of these instructions. */
7733 if (!mode64
&& flag_L
==1) { // L==1 invalid for 32 bit.
7734 vex_printf("dis_int_cmp(ppc)(flag_L)\n");
7738 if (( b22
!= 0 ) && ( opc2
!= 0x080 ) ) { // setb case exception
7739 vex_printf("dis_int_cmp(ppc)(b22)\n");
7744 case 0x0B: // cmpi (Compare Immediate, PPC32 p368)
7745 DIP("cmpi cr%u,%u,r%u,%d\n", crfD
, flag_L
, rA_addr
,
7746 (Int
)extend_s_16to32(uimm16
));
7747 b
= mkSzExtendS16( ty
, uimm16
);
7749 putCR321(crfD
, unop(Iop_64to8
, binop(Iop_CmpORD64S
, a
, b
)));
7751 a
= mkNarrowTo32( ty
, a
);
7752 b
= mkNarrowTo32( ty
, b
);
7753 putCR321(crfD
, unop(Iop_32to8
, binop(Iop_CmpORD32S
, a
, b
)));
7755 putCR0( crfD
, getXER_SO() );
7758 case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370)
7759 DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD
, flag_L
, rA_addr
, uimm16
);
7760 b
= mkSzImm( ty
, uimm16
);
7762 putCR321(crfD
, unop(Iop_64to8
, binop(Iop_CmpORD64U
, a
, b
)));
7764 a
= mkNarrowTo32( ty
, a
);
7765 b
= mkNarrowTo32( ty
, b
);
7766 putCR321(crfD
, unop(Iop_32to8
, binop(Iop_CmpORD32U
, a
, b
)));
7768 putCR0( crfD
, getXER_SO() );
7774 vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n");
7777 b
= getIReg(rB_addr
);
7780 case 0x000: // cmp (Compare, PPC32 p367)
7781 DIP("cmp cr%u,%u,r%u,r%u\n", crfD
, flag_L
, rA_addr
, rB_addr
);
7782 /* Comparing a reg with itself produces a result which
7783 doesn't depend on the contents of the reg. Therefore
7784 remove the false dependency, which has been known to cause
7785 memcheck to produce false errors. */
7786 if (rA_addr
== rB_addr
)
7787 a
= b
= typeOfIRExpr(irsb
->tyenv
,a
) == Ity_I64
7788 ? mkU64(0) : mkU32(0);
7790 putCR321(crfD
, unop(Iop_64to8
, binop(Iop_CmpORD64S
, a
, b
)));
7792 a
= mkNarrowTo32( ty
, a
);
7793 b
= mkNarrowTo32( ty
, b
);
7794 putCR321(crfD
, unop(Iop_32to8
,binop(Iop_CmpORD32S
, a
, b
)));
7796 putCR0( crfD
, getXER_SO() );
7799 case 0x020: // cmpl (Compare Logical, PPC32 p369)
7800 DIP("cmpl cr%u,%u,r%u,r%u\n", crfD
, flag_L
, rA_addr
, rB_addr
);
7801 /* Comparing a reg with itself produces a result which
7802 doesn't depend on the contents of the reg. Therefore
7803 remove the false dependency, which has been known to cause
7804 memcheck to produce false errors. */
7805 if (rA_addr
== rB_addr
)
7806 a
= b
= typeOfIRExpr(irsb
->tyenv
,a
) == Ity_I64
7807 ? mkU64(0) : mkU32(0);
7809 putCR321(crfD
, unop(Iop_64to8
, binop(Iop_CmpORD64U
, a
, b
)));
7811 a
= mkNarrowTo32( ty
, a
);
7812 b
= mkNarrowTo32( ty
, b
);
7813 putCR321(crfD
, unop(Iop_32to8
, binop(Iop_CmpORD32U
, a
, b
)));
7815 putCR0( crfD
, getXER_SO() );
7818 case 0x080: // setb (Set Boolean)
7820 /* Set Boolean Condition in result register. The result register
7821 is set to all ones if the condition is true and all zeros
7823 UChar rT_addr
= ifieldRegDS(theInstr
);
7824 Int bfa
= IFIELD(theInstr
, 18, 3);
7825 IRTemp cr
= newTemp(Ity_I32
);
7826 IRTemp cr0
= newTemp(Ity_I32
);
7827 IRTemp cr1
= newTemp(Ity_I32
);
7828 IRTemp result
= newTemp(Ity_I64
);
7830 DIP("setb r%u,%d\n", rT_addr
, bfa
);
7832 /* Fetch the entire condition code value */
7833 assign( cr
, getGST( PPC_GST_CR
) );
7835 /* Get bit zero (IBM numbering) of the CR field specified
7838 assign( cr0
, binop( Iop_And32
,
7841 mkU8( (7-bfa
)*4 ) ),
7843 assign( cr1
, binop( Iop_And32
,
7846 mkU8( (7-bfa
)*4 ) ),
7848 assign( result
, binop( Iop_Or64
,
7853 binop( Iop_32HLto64
,
7858 mkU32( 0x4 ) ) ) ) ) );
7859 if ( ty
== Ity_I64
)
7860 putIReg( rT_addr
, mkexpr( result
) );
7862 putIReg( rT_addr
, unop( Iop_64to32
, mkexpr(result
) ) );
7866 vex_printf("dis_int_cmp(ppc)(opc2)\n");
7872 vex_printf("dis_int_cmp(ppc)(opc1)\n");
7881 Integer Logical Instructions
7883 static Bool
dis_int_logic ( UInt prefix
, UInt theInstr
)
7885 /* D-Form, X-Form */
7886 UChar opc1
= ifieldOPC(theInstr
);
7887 UChar rS_addr
= ifieldRegDS(theInstr
);
7888 UChar rA_addr
= ifieldRegA(theInstr
);
7889 UInt uimm16
= ifieldUIMM16(theInstr
);
7890 UChar rB_addr
= ifieldRegB(theInstr
);
7891 UInt opc2
= ifieldOPClo10(theInstr
);
7892 UChar flag_rC
= ifieldBIT0(theInstr
);
7894 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
7895 IRTemp rS
= newTemp(ty
);
7896 IRTemp rA
= newTemp(ty
);
7897 IRTemp rB
= newTemp(ty
);
7900 /* There is no prefixed version of these instructions. */
7903 assign( rS
, getIReg(rS_addr
) );
7904 assign( rB
, getIReg(rB_addr
) );
7907 case 0x1C: // andi. (AND Immediate, PPC32 p358)
7908 DIP("andi. r%u,r%u,0x%x\n", rA_addr
, rS_addr
, uimm16
);
7909 assign( rA
, binop( mkSzOp(ty
, Iop_And8
), mkexpr(rS
),
7910 mkSzImm(ty
, uimm16
)) );
7911 do_rc
= True
; // Always record to CR
7915 case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359)
7916 DIP("andis r%u,r%u,0x%x\n", rA_addr
, rS_addr
, uimm16
);
7917 assign( rA
, binop( mkSzOp(ty
, Iop_And8
), mkexpr(rS
),
7918 mkSzImm(ty
, uimm16
<< 16)) );
7919 do_rc
= True
; // Always record to CR
7923 case 0x18: // ori (OR Immediate, PPC32 p497)
7924 DIP("ori r%u,r%u,0x%x\n", rA_addr
, rS_addr
, uimm16
);
7925 assign( rA
, binop( mkSzOp(ty
, Iop_Or8
), mkexpr(rS
),
7926 mkSzImm(ty
, uimm16
)) );
7929 case 0x19: // oris (OR Immediate Shifted, PPC32 p498)
7930 DIP("oris r%u,r%u,0x%x\n", rA_addr
, rS_addr
, uimm16
);
7931 assign( rA
, binop( mkSzOp(ty
, Iop_Or8
), mkexpr(rS
),
7932 mkSzImm(ty
, uimm16
<< 16)) );
7935 case 0x1A: // xori (XOR Immediate, PPC32 p550)
7936 DIP("xori r%u,r%u,0x%x\n", rA_addr
, rS_addr
, uimm16
);
7937 assign( rA
, binop( mkSzOp(ty
, Iop_Xor8
), mkexpr(rS
),
7938 mkSzImm(ty
, uimm16
)) );
7941 case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551)
7942 DIP("xoris r%u,r%u,0x%x\n", rA_addr
, rS_addr
, uimm16
);
7943 assign( rA
, binop( mkSzOp(ty
, Iop_Xor8
), mkexpr(rS
),
7944 mkSzImm(ty
, uimm16
<< 16)) );
7950 opc2
= IFIELD( theInstr
, 2, 9 );
7953 case 0x1BD: // extswsli (Extend Sign Word shift left)
7955 /* sh[5] is in bit 1, sh[0:4] is in bits [14:10] of theInstr */
7956 UChar sh
= IFIELD( theInstr
, 11, 5 ) | (IFIELD(theInstr
, 1, 1) << 5);
7957 IRTemp temp
= newTemp( ty
);
7959 DIP("extswsli%s r%u,r%u,%u\n", flag_rC
? ".":"",
7960 rA_addr
, rS_addr
, sh
);
7962 assign( temp
, unop( Iop_32Sto64
,
7963 unop( Iop_64to32
, mkexpr( rS
) ) ) );
7964 assign( rA
, binop( Iop_Shl64
, mkexpr( temp
), mkU8( sh
) ) );
7965 putIReg( rA_addr
, mkexpr( rA
) );
7968 set_CR0( mkexpr( rA
) );
7973 break; // drop to next opc2 check
7976 do_rc
= True
; // All below record to CR, except for where we return at case end.
7978 opc2
= ifieldOPClo10( theInstr
);
7981 case 0x01C: // and (AND, PPC32 p356)
7982 DIP("and%s r%u,r%u,r%u\n",
7983 flag_rC
? ".":"", rA_addr
, rS_addr
, rB_addr
);
7984 assign(rA
, binop( mkSzOp(ty
, Iop_And8
),
7985 mkexpr(rS
), mkexpr(rB
)));
7988 case 0x03C: // andc (AND with Complement, PPC32 p357)
7989 DIP("andc%s r%u,r%u,r%u\n",
7990 flag_rC
? ".":"", rA_addr
, rS_addr
, rB_addr
);
7991 assign(rA
, binop( mkSzOp(ty
, Iop_And8
), mkexpr(rS
),
7992 unop( mkSzOp(ty
, Iop_Not8
),
7996 case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371)
7998 vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n");
8001 DIP("cntlzw%s r%u,r%u\n", flag_rC
? ".":"", rA_addr
, rS_addr
);
8003 // mode64: count in low word only
8004 IRExpr
* lo32
= mode64
? unop(Iop_64to32
, mkexpr(rS
)) : mkexpr(rS
);
8005 IRExpr
* res32
= unop(Iop_ClzNat32
, lo32
);
8006 assign(rA
, mode64
? unop(Iop_32Uto64
, res32
) : res32
);
8010 case 0x11C: // eqv (Equivalent, PPC32 p396)
8011 DIP("eqv%s r%u,r%u,r%u\n",
8012 flag_rC
? ".":"", rA_addr
, rS_addr
, rB_addr
);
8013 assign( rA
, unop( mkSzOp(ty
, Iop_Not8
),
8014 binop( mkSzOp(ty
, Iop_Xor8
),
8015 mkexpr(rS
), mkexpr(rB
))) );
8018 case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397
8020 vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n");
8023 DIP("extsb%s r%u,r%u\n",
8024 flag_rC
? ".":"", rA_addr
, rS_addr
);
8026 assign( rA
, unop(Iop_8Sto64
, unop(Iop_64to8
, mkexpr(rS
))) );
8028 assign( rA
, unop(Iop_8Sto32
, unop(Iop_32to8
, mkexpr(rS
))) );
8031 case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398)
8033 vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n");
8036 DIP("extsh%s r%u,r%u\n",
8037 flag_rC
? ".":"", rA_addr
, rS_addr
);
8039 assign( rA
, unop(Iop_16Sto64
,
8040 unop(Iop_64to16
, mkexpr(rS
))) );
8042 assign( rA
, unop(Iop_16Sto32
,
8043 unop(Iop_32to16
, mkexpr(rS
))) );
8046 case 0x1DC: // nand (NAND, PPC32 p492)
8047 DIP("nand%s r%u,r%u,r%u\n",
8048 flag_rC
? ".":"", rA_addr
, rS_addr
, rB_addr
);
8049 assign( rA
, unop( mkSzOp(ty
, Iop_Not8
),
8050 binop( mkSzOp(ty
, Iop_And8
),
8051 mkexpr(rS
), mkexpr(rB
))) );
8054 case 0x07C: // nor (NOR, PPC32 p494)
8055 DIP("nor%s r%u,r%u,r%u\n",
8056 flag_rC
? ".":"", rA_addr
, rS_addr
, rB_addr
);
8057 assign( rA
, unop( mkSzOp(ty
, Iop_Not8
),
8058 binop( mkSzOp(ty
, Iop_Or8
),
8059 mkexpr(rS
), mkexpr(rB
))) );
8062 case 0x1BC: // or (OR, PPC32 p495)
8063 if ((!flag_rC
) && rS_addr
== rB_addr
) {
8064 DIP("mr r%u,r%u\n", rA_addr
, rS_addr
);
8065 assign( rA
, mkexpr(rS
) );
8067 DIP("or%s r%u,r%u,r%u\n",
8068 flag_rC
? ".":"", rA_addr
, rS_addr
, rB_addr
);
8069 assign( rA
, binop( mkSzOp(ty
, Iop_Or8
),
8070 mkexpr(rS
), mkexpr(rB
)) );
8074 case 0x19C: // orc (OR with Complement, PPC32 p496)
8075 DIP("orc%s r%u,r%u,r%u\n",
8076 flag_rC
? ".":"", rA_addr
, rS_addr
, rB_addr
);
8077 assign( rA
, binop( mkSzOp(ty
, Iop_Or8
), mkexpr(rS
),
8078 unop(mkSzOp(ty
, Iop_Not8
), mkexpr(rB
))));
8081 case 0x13C: // xor (XOR, PPC32 p549)
8082 DIP("xor%s r%u,r%u,r%u\n",
8083 flag_rC
? ".":"", rA_addr
, rS_addr
, rB_addr
);
8084 assign( rA
, binop( mkSzOp(ty
, Iop_Xor8
),
8085 mkexpr(rS
), mkexpr(rB
)) );
8089 /* 64bit Integer Logical Instructions */
8090 case 0x3DA: // extsw (Extend Sign Word, PPC64 p430)
8092 vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n");
8095 DIP("extsw%s r%u,r%u\n", flag_rC
? ".":"", rA_addr
, rS_addr
);
8096 assign(rA
, unop(Iop_32Sto64
, unop(Iop_64to32
, mkexpr(rS
))));
8099 case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401)
8101 vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n");
8104 DIP("cntlzd%s r%u,r%u\n", flag_rC
? ".":"", rA_addr
, rS_addr
);
8105 assign(rA
, unop(Iop_ClzNat64
, mkexpr(rS
)));
8108 case 0x1FC: // cmpb (Power6: compare bytes)
8109 DIP("cmpb r%u,r%u,r%u\n", rA_addr
, rS_addr
, rB_addr
);
8112 assign( rA
, unop( Iop_V128to64
,
8113 binop( Iop_CmpEQ8x16
,
8114 binop( Iop_64HLtoV128
, mkU64(0), mkexpr(rS
) ),
8115 binop( Iop_64HLtoV128
, mkU64(0), mkexpr(rB
) )
8118 assign( rA
, unop( Iop_V128to32
,
8119 binop( Iop_CmpEQ8x16
,
8120 unop( Iop_32UtoV128
, mkexpr(rS
) ),
8121 unop( Iop_32UtoV128
, mkexpr(rB
) )
8125 case 0x2DF: { // mftgpr (move floating-point to general purpose register)
8126 /* The mftgpr instruction was deprecated in Power 7, 2009 timeframe.
8127 Leaving support in Valgrind for now (9/10/2021). Can remove the
8128 mftgpr support in Valgrind if the opcode ever gets reused. */
8129 IRTemp frB
= newTemp(Ity_F64
);
8130 DIP("mftgpr r%u,fr%u\n", rS_addr
, rB_addr
);
8132 assign( frB
, getFReg(rB_addr
)); // always F64
8134 assign( rA
, unop( Iop_ReinterpF64asI64
, mkexpr(frB
)) );
8136 assign( rA
, unop( Iop_64to32
, unop( Iop_ReinterpF64asI64
, mkexpr(frB
))) );
8138 putIReg( rS_addr
, mkexpr(rA
));
8142 case 0x25F: { // mffgpr (move floating-point from general purpose register)
8143 /* The mffgpr instruction was deprecated in Power 7, 2009 timeframe.
8144 Leaving support in Valgrind for now (9/10/2021). Can remove the
8145 mftgpr support in Valgrind if the opcode ever gets reused. */
8146 IRTemp frA
= newTemp(Ity_F64
);
8147 DIP("mffgpr fr%u,r%u\n", rS_addr
, rB_addr
);
8150 assign( frA
, unop( Iop_ReinterpI64asF64
, mkexpr(rB
)) );
8152 assign( frA
, unop( Iop_ReinterpI64asF64
, unop( Iop_32Uto64
, mkexpr(rB
))) );
8154 putFReg( rS_addr
, mkexpr(frA
));
8157 case 0x1FA: // popcntd (population count doubleword)
8160 DIP("popcntd r%u,r%u\n", rA_addr
, rS_addr
);
8161 IRTemp result
= gen_POPCOUNT(ty
, rS
, DWORD
);
8162 putIReg( rA_addr
, mkexpr(result
) );
8165 case 0x17A: // popcntw (Population Count Words)
8167 DIP("popcntw r%u,r%u\n", rA_addr
, rS_addr
);
8169 IRTemp resultHi
, resultLo
;
8170 IRTemp argLo
= newTemp(Ity_I32
);
8171 IRTemp argHi
= newTemp(Ity_I32
);
8172 assign(argLo
, unop(Iop_64to32
, mkexpr(rS
)));
8173 assign(argHi
, unop(Iop_64HIto32
, mkexpr(rS
)));
8174 resultLo
= gen_POPCOUNT(Ity_I32
, argLo
, WORD
);
8175 resultHi
= gen_POPCOUNT(Ity_I32
, argHi
, WORD
);
8176 putIReg( rA_addr
, binop(Iop_32HLto64
, mkexpr(resultHi
), mkexpr(resultLo
)));
8178 IRTemp result
= gen_POPCOUNT(ty
, rS
, WORD
);
8179 putIReg( rA_addr
, mkexpr(result
) );
8183 case 0x7A: // popcntb (Population Count Byte)
8185 DIP("popcntb r%u,r%u\n", rA_addr
, rS_addr
);
8188 IRTemp resultHi
, resultLo
;
8189 IRTemp argLo
= newTemp(Ity_I32
);
8190 IRTemp argHi
= newTemp(Ity_I32
);
8191 assign(argLo
, unop(Iop_64to32
, mkexpr(rS
)));
8192 assign(argHi
, unop(Iop_64HIto32
, mkexpr(rS
)));
8193 resultLo
= gen_POPCOUNT(Ity_I32
, argLo
, BYTE
);
8194 resultHi
= gen_POPCOUNT(Ity_I32
, argHi
, BYTE
);
8195 putIReg( rA_addr
, binop(Iop_32HLto64
, mkexpr(resultHi
),
8198 IRTemp result
= gen_POPCOUNT(ty
, rS
, BYTE
);
8199 putIReg( rA_addr
, mkexpr(result
) );
8203 case 0x0FC: // bpermd (Bit Permute Doubleword)
8205 /* This is a lot of rigmarole to emulate bpermd like this, as it
8206 * could be done much faster by implementing a call to the native
8207 * instruction. However, where possible I want to avoid using new
8208 * native instructions so that we can use valgrind to emulate those
8209 * instructions on older PPC64 hardware.
8211 #define BPERMD_IDX_MASK 0x00000000000000FFULL
8212 #define BPERMD_BIT_MASK 0x8000000000000000ULL
8214 IRExpr
* rS_expr
= mkexpr(rS
);
8215 IRExpr
* res
= binop(Iop_And64
, mkU64(0), mkU64(0));
8216 DIP("bpermd r%u,r%u,r%u\n", rA_addr
, rS_addr
, rB_addr
);
8217 for (i
= 0; i
< 8; i
++) {
8218 IRTemp idx_tmp
= newTemp( Ity_I64
);
8219 IRTemp perm_bit
= newTemp( Ity_I64
);
8220 IRTemp idx
= newTemp( Ity_I8
);
8221 IRTemp idx_LT64
= newTemp( Ity_I1
);
8222 IRTemp idx_LT64_ity64
= newTemp( Ity_I64
);
8225 binop( Iop_And64
, mkU64( BPERMD_IDX_MASK
), rS_expr
) );
8227 binop( Iop_CmpLT64U
, mkexpr( idx_tmp
), mkU64( 64 ) ) );
8232 unop( Iop_64to8
, mkexpr( idx_tmp
) ) ) );
8233 /* If idx_LT64 == 0, we must force the perm bit to '0'. Below, we se idx
8234 * to determine which bit of rB to use for the perm bit, and then we shift
8235 * that bit to the MSB position. We AND that with a 64-bit-ized idx_LT64
8236 * to set the final perm bit.
8238 assign( idx_LT64_ity64
,
8239 unop( Iop_32Uto64
, unop( Iop_1Uto32
, mkexpr(idx_LT64
) ) ) );
8242 mkexpr( idx_LT64_ity64
),
8245 mkU64( BPERMD_BIT_MASK
),
8250 res
= binop( Iop_Or64
,
8255 rS_expr
= binop( Iop_Shr64
, rS_expr
, mkU8( 8 ) );
8257 putIReg(rA_addr
, res
);
8262 vex_printf("dis_int_logic(ppc)(opc2)\n");
8268 vex_printf("dis_int_logic(ppc)(opc1)\n");
8272 putIReg( rA_addr
, mkexpr(rA
) );
8274 if (do_rc
&& flag_rC
) {
8275 set_CR0( mkexpr(rA
) );
8281 Integer Parity Instructions
8283 static Bool
dis_int_parity ( UInt prefix
, UInt theInstr
)
8286 UChar opc1
= ifieldOPC(theInstr
);
8287 UChar rS_addr
= ifieldRegDS(theInstr
);
8288 UChar rA_addr
= ifieldRegA(theInstr
);
8289 UChar rB_addr
= ifieldRegB(theInstr
);
8290 UInt opc2
= ifieldOPClo10(theInstr
);
8291 UChar b0
= ifieldBIT0(theInstr
);
8292 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
8294 IRTemp rS
= newTemp(ty
);
8295 IRTemp rA
= newTemp(ty
);
8296 IRTemp iTot1
= newTemp(Ity_I32
);
8297 IRTemp iTot2
= newTemp(Ity_I32
);
8298 IRTemp iTot3
= newTemp(Ity_I32
);
8299 IRTemp iTot4
= newTemp(Ity_I32
);
8300 IRTemp iTot5
= newTemp(Ity_I32
);
8301 IRTemp iTot6
= newTemp(Ity_I32
);
8302 IRTemp iTot7
= newTemp(Ity_I32
);
8303 IRTemp iTot8
= newTemp(Ity_I32
);
8304 IRTemp rS1
= newTemp(ty
);
8305 IRTemp rS2
= newTemp(ty
);
8306 IRTemp rS3
= newTemp(ty
);
8307 IRTemp rS4
= newTemp(ty
);
8308 IRTemp rS5
= newTemp(ty
);
8309 IRTemp rS6
= newTemp(ty
);
8310 IRTemp rS7
= newTemp(ty
);
8311 IRTemp iHi
= newTemp(Ity_I32
);
8312 IRTemp iLo
= newTemp(Ity_I32
);
8313 IROp to_bit
= (mode64
? Iop_64to1
: Iop_32to1
);
8314 IROp shr_op
= (mode64
? Iop_Shr64
: Iop_Shr32
);
8316 /* There is no prefixed version of these instructions. */
8319 if (opc1
!= 0x1f || rB_addr
|| b0
) {
8320 vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n");
8324 assign( rS
, getIReg(rS_addr
) );
8327 case 0xba: // prtyd (Parity Doubleword, ISA 2.05 p320)
8328 DIP("prtyd r%u,r%u\n", rA_addr
, rS_addr
);
8329 assign( iTot1
, unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS
))) );
8330 assign( rS1
, binop(shr_op
, mkexpr(rS
), mkU8(8)) );
8331 assign( iTot2
, binop(Iop_Add32
,
8332 unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS1
))),
8334 assign( rS2
, binop(shr_op
, mkexpr(rS1
), mkU8(8)) );
8335 assign( iTot3
, binop(Iop_Add32
,
8336 unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS2
))),
8338 assign( rS3
, binop(shr_op
, mkexpr(rS2
), mkU8(8)) );
8339 assign( iTot4
, binop(Iop_Add32
,
8340 unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS3
))),
8343 assign( rS4
, binop(shr_op
, mkexpr(rS3
), mkU8(8)) );
8344 assign( iTot5
, binop(Iop_Add32
,
8345 unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS4
))),
8347 assign( rS5
, binop(shr_op
, mkexpr(rS4
), mkU8(8)) );
8348 assign( iTot6
, binop(Iop_Add32
,
8349 unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS5
))),
8351 assign( rS6
, binop(shr_op
, mkexpr(rS5
), mkU8(8)) );
8352 assign( iTot7
, binop(Iop_Add32
,
8353 unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS6
))),
8355 assign( rS7
, binop(shr_op
, mkexpr(rS6
), mkU8(8)) );
8356 assign( iTot8
, binop(Iop_Add32
,
8357 unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS7
))),
8359 assign( rA
, unop(Iop_32Uto64
,
8360 binop(Iop_And32
, mkexpr(iTot8
), mkU32(1))) );
8362 assign( rA
, mkexpr(iTot4
) );
8365 case 0x9a: // prtyw (Parity Word, ISA 2.05 p320)
8366 assign( iTot1
, unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS
))) );
8367 assign( rS1
, binop(shr_op
, mkexpr(rS
), mkU8(8)) );
8368 assign( iTot2
, binop(Iop_Add32
,
8369 unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS1
))),
8371 assign( rS2
, binop(shr_op
, mkexpr(rS1
), mkU8(8)) );
8372 assign( iTot3
, binop(Iop_Add32
,
8373 unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS2
))),
8375 assign( rS3
, binop(shr_op
, mkexpr(rS2
), mkU8(8)) );
8376 assign( iTot4
, binop(Iop_Add32
,
8377 unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS3
))),
8379 assign( iLo
, unop(Iop_1Uto32
, unop(Iop_32to1
, mkexpr(iTot4
) )) );
8382 assign( rS4
, binop(shr_op
, mkexpr(rS3
), mkU8(8)) );
8383 assign( iTot5
, unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS4
))) );
8384 assign( rS5
, binop(shr_op
, mkexpr(rS4
), mkU8(8)) );
8385 assign( iTot6
, binop(Iop_Add32
,
8386 unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS5
))),
8388 assign( rS6
, binop(shr_op
, mkexpr(rS5
), mkU8(8)) );
8389 assign( iTot7
, binop(Iop_Add32
,
8390 unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS6
))),
8392 assign( rS7
, binop(shr_op
, mkexpr(rS6
), mkU8(8)));
8393 assign( iTot8
, binop(Iop_Add32
,
8394 unop(Iop_1Uto32
, unop(to_bit
, mkexpr(rS7
))),
8396 assign( iHi
, binop(Iop_And32
, mkU32(1), mkexpr(iTot8
)) ),
8397 assign( rA
, binop(Iop_32HLto64
, mkexpr(iHi
), mkexpr(iLo
)) );
8399 assign( rA
, binop(Iop_Or32
, mkU32(0), mkexpr(iLo
)) );
8402 vex_printf("dis_int_parity(ppc)(opc2)\n");
8406 putIReg( rA_addr
, mkexpr(rA
) );
8413 Integer Rotate Instructions
8415 static Bool
dis_int_rot ( UInt prefix
, UInt theInstr
)
8417 /* M-Form, MDS-Form */
8418 UChar opc1
= ifieldOPC(theInstr
);
8419 UChar rS_addr
= ifieldRegDS(theInstr
);
8420 UChar rA_addr
= ifieldRegA(theInstr
);
8421 UChar rB_addr
= ifieldRegB(theInstr
);
8422 UChar sh_imm
= rB_addr
;
8423 UChar MaskBeg
= toUChar( IFIELD( theInstr
, 6, 5 ) );
8424 UChar MaskEnd
= toUChar( IFIELD( theInstr
, 1, 5 ) );
8425 UChar msk_imm
= toUChar( IFIELD( theInstr
, 5, 6 ) );
8426 UChar opc2
= toUChar( IFIELD( theInstr
, 2, 3 ) );
8427 UChar b1
= ifieldBIT1(theInstr
);
8428 UChar flag_rC
= ifieldBIT0(theInstr
);
8430 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
8431 IRTemp rS
= newTemp(ty
);
8432 IRTemp rA
= newTemp(ty
);
8433 IRTemp rB
= newTemp(ty
);
8434 IRTemp rot
= newTemp(ty
);
8439 /* There is no prefixed version of these instructions. */
8442 assign( rS
, getIReg(rS_addr
) );
8443 assign( rB
, getIReg(rB_addr
) );
8447 // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500)
8448 DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC
? ".":"",
8449 rA_addr
, rS_addr
, sh_imm
, MaskBeg
, MaskEnd
);
8451 // tmp32 = (ROTL(rS_Lo32, Imm)
8452 // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64)
8453 mask64
= MASK64(31-MaskEnd
, 31-MaskBeg
);
8454 r
= ROTL( unop(Iop_64to32
, mkexpr(rS
) ), mkU8(sh_imm
) );
8455 r
= unop(Iop_32Uto64
, r
);
8456 assign( rot
, binop(Iop_Or64
, r
,
8457 binop(Iop_Shl64
, r
, mkU8(32))) );
8460 binop(Iop_And64
, mkexpr(rot
), mkU64(mask64
)),
8461 binop(Iop_And64
, getIReg(rA_addr
), mkU64(~mask64
))) );
8464 // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask);
8465 mask32
= MASK32(31-MaskEnd
, 31-MaskBeg
);
8466 r
= ROTL(mkexpr(rS
), mkU8(sh_imm
));
8469 binop(Iop_And32
, mkU32(mask32
), r
),
8470 binop(Iop_And32
, getIReg(rA_addr
), mkU32(~mask32
))) );
8476 // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501)
8477 vassert(MaskBeg
< 32);
8478 vassert(MaskEnd
< 32);
8479 vassert(sh_imm
< 32);
8482 IRTemp rTmp
= newTemp(Ity_I64
);
8483 mask64
= MASK64(31-MaskEnd
, 31-MaskBeg
);
8484 DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC
? ".":"",
8485 rA_addr
, rS_addr
, sh_imm
, MaskBeg
, MaskEnd
);
8486 // tmp32 = (ROTL(rS_Lo32, Imm)
8487 // rA = ((tmp32 || tmp32) & mask64)
8488 r
= ROTL( unop(Iop_64to32
, mkexpr(rS
) ), mkU8(sh_imm
) );
8489 r
= unop(Iop_32Uto64
, r
);
8492 assign( rot
, binop(Iop_Or64
, mkexpr(rTmp
),
8493 binop(Iop_Shl64
, mkexpr(rTmp
), mkU8(32))) );
8494 assign( rA
, binop(Iop_And64
, mkexpr(rot
), mkU64(mask64
)) );
8497 if (MaskBeg
== 0 && sh_imm
+MaskEnd
== 31) {
8498 /* Special-case the ,n,0,31-n form as that is just n-bit
8499 shift left, PPC32 p501 */
8500 DIP("slwi%s r%u,r%u,%d\n", flag_rC
? ".":"",
8501 rA_addr
, rS_addr
, sh_imm
);
8502 assign( rA
, binop(Iop_Shl32
, mkexpr(rS
), mkU8(sh_imm
)) );
8504 else if (MaskEnd
== 31 && sh_imm
+MaskBeg
== 32) {
8505 /* Special-case the ,32-n,n,31 form as that is just n-bit
8506 unsigned shift right, PPC32 p501 */
8507 DIP("srwi%s r%u,r%u,%d\n", flag_rC
? ".":"",
8508 rA_addr
, rS_addr
, MaskBeg
);
8509 assign( rA
, binop(Iop_Shr32
, mkexpr(rS
), mkU8(MaskBeg
)) );
8513 mask32
= MASK32(31-MaskEnd
, 31-MaskBeg
);
8514 DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC
? ".":"",
8515 rA_addr
, rS_addr
, sh_imm
, MaskBeg
, MaskEnd
);
8516 // rA = ROTL(rS, Imm) & mask
8517 assign( rA
, binop(Iop_And32
,
8518 ROTL(mkexpr(rS
), mkU8(sh_imm
)),
8526 // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503
8527 DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC
? ".":"",
8528 rA_addr
, rS_addr
, rB_addr
, MaskBeg
, MaskEnd
);
8530 mask64
= MASK64(31-MaskEnd
, 31-MaskBeg
);
8531 /* weird insn alert!
8532 tmp32 = (ROTL(rS_Lo32, rB[0-4])
8533 rA = ((tmp32 || tmp32) & mask64)
8535 // note, ROTL does the masking, so we don't do it here
8536 r
= ROTL( unop(Iop_64to32
, mkexpr(rS
)),
8537 unop(Iop_64to8
, mkexpr(rB
)) );
8538 r
= unop(Iop_32Uto64
, r
);
8539 assign(rot
, binop(Iop_Or64
, r
, binop(Iop_Shl64
, r
, mkU8(32))));
8540 assign( rA
, binop(Iop_And64
, mkexpr(rot
), mkU64(mask64
)) );
8542 mask32
= MASK32(31-MaskEnd
, 31-MaskBeg
);
8543 // rA = ROTL(rS, rB[0-4]) & mask
8544 // note, ROTL does the masking, so we don't do it here
8545 assign( rA
, binop(Iop_And32
,
8547 unop(Iop_32to8
, mkexpr(rB
))),
8553 /* 64bit Integer Rotates */
8555 msk_imm
= ((msk_imm
& 1) << 5) | (msk_imm
>> 1);
8558 vassert( msk_imm
< 64 );
8559 vassert( sh_imm
< 64 );
8563 /* r = ROTL64( rS, rB_lo6) */
8564 r
= ROTL( mkexpr(rS
), unop(Iop_64to8
, mkexpr(rB
)) );
8566 if (b1
== 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555)
8567 DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC
? ".":"",
8568 rA_addr
, rS_addr
, rB_addr
, msk_imm
);
8569 // note, ROTL does the masking, so we don't do it here
8570 mask64
= MASK64(0, 63-msk_imm
);
8571 assign( rA
, binop(Iop_And64
, r
, mkU64(mask64
)) );
8573 } else { // rldcr (Rotl DWord, Clear Right, PPC64 p556)
8574 DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC
? ".":"",
8575 rA_addr
, rS_addr
, rB_addr
, msk_imm
);
8576 mask64
= MASK64(63-msk_imm
, 63);
8577 assign( rA
, binop(Iop_And64
, r
, mkU64(mask64
)) );
8582 case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557)
8583 DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC
? ".":"",
8584 rA_addr
, rS_addr
, sh_imm
, msk_imm
);
8585 r
= ROTL(mkexpr(rS
), mkU8(sh_imm
));
8586 mask64
= MASK64(sh_imm
, 63-msk_imm
);
8587 assign( rA
, binop(Iop_And64
, r
, mkU64(mask64
)) );
8589 // later: deal with special case: (msk_imm==0) => SHL(sh_imm)
8591 Hmm... looks like this'll do the job more simply:
8593 m = ~(1 << (63-msk_imm))
8597 case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558)
8599 && sh_imm
+ msk_imm
== 64 && msk_imm
>= 1 && msk_imm
<= 63) {
8600 /* special-case the ,64-n,n form as that is just
8601 unsigned shift-right by n */
8602 DIP("srdi%s r%u,r%u,%u\n",
8603 flag_rC
? ".":"", rA_addr
, rS_addr
, msk_imm
);
8604 assign( rA
, binop(Iop_Shr64
, mkexpr(rS
), mkU8(msk_imm
)) );
8606 DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC
? ".":"",
8607 rA_addr
, rS_addr
, sh_imm
, msk_imm
);
8608 r
= ROTL(mkexpr(rS
), mkU8(sh_imm
));
8609 mask64
= MASK64(0, 63-msk_imm
);
8610 assign( rA
, binop(Iop_And64
, r
, mkU64(mask64
)) );
8614 case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559)
8616 && sh_imm
+ msk_imm
== 63 && sh_imm
>= 1 && sh_imm
<= 63) {
8617 /* special-case the ,n,63-n form as that is just
8619 DIP("sldi%s r%u,r%u,%u\n",
8620 flag_rC
? ".":"", rA_addr
, rS_addr
, sh_imm
);
8621 assign( rA
, binop(Iop_Shl64
, mkexpr(rS
), mkU8(sh_imm
)) );
8623 DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC
? ".":"",
8624 rA_addr
, rS_addr
, sh_imm
, msk_imm
);
8625 r
= ROTL(mkexpr(rS
), mkU8(sh_imm
));
8626 mask64
= MASK64(63-msk_imm
, 63);
8627 assign( rA
, binop(Iop_And64
, r
, mkU64(mask64
)) );
8631 case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560)
8632 IRTemp rA_orig
= newTemp(ty
);
8633 DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC
? ".":"",
8634 rA_addr
, rS_addr
, sh_imm
, msk_imm
);
8635 r
= ROTL(mkexpr(rS
), mkU8(sh_imm
));
8636 mask64
= MASK64(sh_imm
, 63-msk_imm
);
8637 assign( rA_orig
, getIReg(rA_addr
) );
8638 assign( rA
, binop(Iop_Or64
,
8639 binop(Iop_And64
, mkU64(mask64
), r
),
8640 binop(Iop_And64
, mkU64(~mask64
),
8641 mkexpr(rA_orig
))) );
8645 vex_printf("dis_int_rot(ppc)(opc2)\n");
8652 vex_printf("dis_int_rot(ppc)(opc1)\n");
8656 putIReg( rA_addr
, mkexpr(rA
) );
8659 set_CR0( mkexpr(rA
) );
8666 Integer Load Instructions
8668 static Bool
dis_int_load_ds_form_prefix ( UInt prefix
,
8671 /* DS-Form Prefixed versions */
8672 UChar opc1
= ifieldOPC(theInstr
);
8673 UChar rT_addr
= ifieldRegDS(theInstr
);
8674 UChar rA_addr
= ifieldRegA(theInstr
);
8675 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
8676 UChar b0
= ifieldBIT0(theInstr
);
8677 UChar b1
= ifieldBIT1(theInstr
);
8678 IRTemp EA
= newTemp(ty
);
8679 UInt ptype
= PrefixType(prefix
);
8680 Bool is_prefix
= prefix_instruction( prefix
);
8681 ULong immediate_val
= 0;
8684 /* Some of these instructions have different encodings for their word
8685 versions and their prefix versions. */
8687 if (opc1
== 0x29) { //plwa
8688 pDIP( is_prefix
, "lwa r%u,%llu(r%u)", rT_addr
, immediate_val
, rA_addr
);
8689 DIPp( is_prefix
, ",%u", R
);
8690 assign( EA
, calculate_prefix_EA( prefix
, theInstr
, rA_addr
,
8691 ptype
, DSFORM_IMMASK
,
8692 &immediate_val
, &R
) );
8695 unop(Iop_32Sto64
, load( Ity_I32
, mkexpr( EA
) ) ) );
8698 } else if (opc1
== 0x39) { // pld
8699 pDIP( is_prefix
, "ld r%u,%llu(r%u)", rT_addr
, immediate_val
, rA_addr
);
8701 assign( EA
, calculate_prefix_EA( prefix
, theInstr
,
8702 rA_addr
, ptype
, DFORM_IMMASK
,
8703 &immediate_val
, &R
) );
8705 putIReg( rT_addr
, load( Ity_I64
, mkexpr( EA
) ) );
8708 } else if (opc1
== 0x3A) {
8709 /* Word version DS Form - 64bit Loads. In each case EA will have been
8710 formed with the lowest 2 bits masked off the immediate offset. */
8711 UInt uimm16
= ifieldUIMM16(theInstr
);
8712 Int simm16
= extend_s_16to32(uimm16
);
8714 simm16
= simm16
& DSFORM_IMMASK
;
8715 assign( EA
, ea_rAor0_simm( rA_addr
, simm16
) );
8717 switch ((b1
<<1) | b0
) {
8718 case 0x0: // ld (Load DWord, PPC64 p472)
8719 DIP("ld r%u,%llu(r%u)", rT_addr
, immediate_val
, rA_addr
);
8720 putIReg( rT_addr
, load( Ity_I64
, mkexpr( EA
) ) );
8723 case 0x1: // ldu (Load DWord, Update, PPC64 p474)
8724 /* There is no prefixed version of this instructions. */
8725 if (rA_addr
== 0 || rA_addr
== rT_addr
) {
8726 vex_printf("dis_int_load_ds_form_prefix(ppc)(ldu,rA_addr|rT_addr)\n");
8729 DIP("ldu r%u,%llu(r%u)\n", rT_addr
, immediate_val
, rA_addr
);
8731 putIReg( rT_addr
, load( Ity_I64
, mkexpr( EA
) ) );
8732 putIReg( rA_addr
, mkexpr( EA
) );
8735 case 0x2: // lwa (Load Word Alg, PPC64 p499)
8736 pDIP( is_prefix
, "lwa r%u,%llu(r%u)", rT_addr
, immediate_val
, rA_addr
);
8737 DIPp( is_prefix
, ",%u", R
);
8740 unop(Iop_32Sto64
, load( Ity_I32
, mkexpr( EA
) ) ) );
8744 vex_printf("dis_int_load_ds_form_prefix(ppc)(0x3A, opc2)\n");
8752 static Bool
dis_int_load_prefix ( UInt prefix
, UInt theInstr
)
8754 /* D-Form, X-Form, Prefixed versions */
8755 UChar opc1
= ifieldOPC(theInstr
);
8756 UChar rT_addr
= ifieldRegDS(theInstr
);
8757 UChar rA_addr
= ifieldRegA(theInstr
);
8759 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
8760 IRTemp EA
= newTemp(ty
);
8761 UInt ptype
= PrefixType(prefix
);
8762 Bool is_prefix
= prefix_instruction( prefix
);
8764 ULong immediate_val
= 0;
8771 assign( EA
, calculate_prefix_EA( prefix
, theInstr
,
8772 rA_addr
, ptype
, DFORM_IMMASK
,
8773 &immediate_val
, &R
) );
8775 } else if ( opc1
== 0x28 ) {
8776 // half word loads lhz, plhz
8778 assign( EA
, calculate_prefix_EA( prefix
, theInstr
,
8779 rA_addr
, ptype
, DFORM_IMMASK
,
8780 &immediate_val
, &R
) );
8782 } else if ( opc1
== 0x2A ) {
8783 // half word loads lha, plha
8785 assign( EA
, calculate_prefix_EA( prefix
, theInstr
,
8786 rA_addr
, ptype
, DFORM_IMMASK
,
8787 &immediate_val
, &R
) );
8789 } else if (opc1
== 0x20 ) {
8790 // word load lwz, plwz
8792 assign( EA
, calculate_prefix_EA( prefix
, theInstr
,
8793 rA_addr
, ptype
, DFORM_IMMASK
,
8794 &immediate_val
, &R
) );
8796 } else if (opc1
== 0x38 ) { // lq, plq
8801 assign( EA
, calculate_prefix_EA( prefix
, theInstr
,
8802 rA_addr
, ptype
, DQFORM_IMMASK
,
8803 &immediate_val
, &R
) );
8806 assign( EA
, calculate_prefix_EA( prefix
, theInstr
,
8807 rA_addr
, ptype
, DFORM_IMMASK
,
8808 &immediate_val
, &R
) );
8811 val
= load( size
, mkexpr( EA
) );
8813 /* Store the load value in the destination and print the instruction
8816 case 0x20: // lwz (Load W & Zero, PPC32 p460)
8817 pDIP( is_prefix
, "lwz r%u,%llu(r%u)", rT_addr
, immediate_val
, rA_addr
);
8818 DIPp( is_prefix
, ",%u", R
);
8820 putIReg( rT_addr
, mkWidenFrom32(ty
, val
, False
) );
8823 case 0x22: // lbz (Load B & Zero, PPC32 p433)
8824 pDIP( is_prefix
, "lbz r%u,%llu(r%u)", rT_addr
, immediate_val
, rA_addr
);
8825 DIPp( is_prefix
, ",%u", R
);
8827 putIReg( rT_addr
, mkWidenFrom8( ty
, val
, False
) );
8830 case 0x28: // lhz (Load HW & Zero, PPC32 p450)
8831 pDIP( is_prefix
, "lhz r%u,%llu(r%u)", rT_addr
, immediate_val
, rA_addr
);
8832 DIPp( is_prefix
, ",%u", R
);
8834 putIReg( rT_addr
, mkWidenFrom16( ty
, val
, False
) );
8837 case 0x2A: // lha (Load HW Alg, PPC32 p445)
8838 pDIP( is_prefix
, "lha r%u,%llu(r%u)", rT_addr
, immediate_val
, rA_addr
);
8839 DIPp( is_prefix
, ",%u", R
);
8840 putIReg( rT_addr
, mkWidenFrom16(ty
, val
, True
) );
8843 case 0x38: { // lq, plq
8844 IRTemp high
= newTemp(ty
);
8845 IRTemp low
= newTemp(ty
);
8846 /* DQ Form - 128bit Loads. Lowest bits [1:0] are the PT field. */
8847 pDIP( is_prefix
, "lq r%u,%llu(r%u)", rT_addr
, immediate_val
, rA_addr
);
8848 DIPp( is_prefix
, ",%u", R
);
8849 /* NOTE: there are some changes to XER[41:42] that have not been
8852 //trap if EA misaligned on 16 byte address
8854 if (host_endness
== VexEndnessBE
) {
8855 assign(high
, load(ty
, mkexpr( EA
) ) );
8856 assign(low
, load(ty
, binop( Iop_Add64
,
8860 assign(low
, load(ty
, mkexpr( EA
) ) );
8861 assign(high
, load(ty
, binop( Iop_Add64
,
8866 assign(high
, load(ty
, binop( Iop_Add32
,
8869 assign(low
, load(ty
, binop( Iop_Add32
,
8874 /* Note, the load order for lq is the same for BE and LE. However,
8875 plq does an endian aware load. */
8876 if (is_prefix
&&( host_endness
== VexEndnessLE
)) {
8877 putIReg( rT_addr
, mkexpr( low
) );
8878 putIReg( rT_addr
+1, mkexpr( high
) );
8880 putIReg( rT_addr
, mkexpr( high
) );
8881 putIReg( rT_addr
+1, mkexpr( low
) );
8887 vex_printf("dis_int_load_prefix(ppc)(opc1)\n");
8893 static Bool
dis_int_load ( UInt prefix
, UInt theInstr
)
8895 /* D-Form, X-Form, DS-Form */
8896 UChar opc1
= ifieldOPC(theInstr
);
8897 UChar rD_addr
= ifieldRegDS(theInstr
);
8898 UChar rA_addr
= ifieldRegA(theInstr
);
8899 UInt uimm16
= ifieldUIMM16(theInstr
);
8900 UChar rB_addr
= ifieldRegB(theInstr
);
8901 UInt opc2
= ifieldOPClo10(theInstr
);
8902 UChar b0
= ifieldBIT0(theInstr
);
8904 Int simm16
= extend_s_16to32(uimm16
);
8905 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
8906 IRTemp EA
= newTemp(ty
);
8909 /* There is no prefixed version of these instructions. */
8913 case 0x1F: // register offset
8914 assign( EA
, ea_rAor0_idxd( rA_addr
, rB_addr
) );
8916 case 0x38: // immediate offset: 64bit: lq: maskoff
8917 // lowest 4 bits of immediate before forming EA
8918 simm16
= simm16
& 0xFFFFFFF0;
8919 assign( EA
, ea_rAor0_simm( rA_addr
, simm16
) );
8921 default: // immediate offset
8922 assign( EA
, ea_rAor0_simm( rA_addr
, simm16
) );
8927 case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434)
8928 if (rA_addr
== 0 || rA_addr
== rD_addr
) {
8929 vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n");
8932 DIP("lbzu r%u,%d(r%u)\n", rD_addr
, (Int
)simm16
, rA_addr
);
8933 val
= load(Ity_I8
, mkexpr(EA
));
8934 putIReg( rD_addr
, mkWidenFrom8(ty
, val
, False
) );
8935 putIReg( rA_addr
, mkexpr(EA
) );
8938 case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446)
8939 if (rA_addr
== 0 || rA_addr
== rD_addr
) {
8940 vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n");
8943 DIP("lhau r%u,%d(r%u)\n", rD_addr
, (Int
)simm16
, rA_addr
);
8944 val
= load(Ity_I16
, mkexpr(EA
));
8945 putIReg( rD_addr
, mkWidenFrom16(ty
, val
, True
) );
8946 putIReg( rA_addr
, mkexpr(EA
) );
8949 case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451)
8950 if (rA_addr
== 0 || rA_addr
== rD_addr
) {
8951 vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n");
8954 DIP("lhzu r%u,%d(r%u)\n", rD_addr
, (Int
)simm16
, rA_addr
);
8955 val
= load(Ity_I16
, mkexpr(EA
));
8956 putIReg( rD_addr
, mkWidenFrom16(ty
, val
, False
) );
8957 putIReg( rA_addr
, mkexpr(EA
) );
8960 case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461))
8961 if (rA_addr
== 0 || rA_addr
== rD_addr
) {
8962 vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n");
8965 DIP("lwzu r%u,%d(r%u)\n", rD_addr
, (Int
)simm16
, rA_addr
);
8966 val
= load(Ity_I32
, mkexpr(EA
));
8967 putIReg( rD_addr
, mkWidenFrom32(ty
, val
, False
) );
8968 putIReg( rA_addr
, mkexpr(EA
) );
8974 vex_printf("dis_int_load(ppc)(Ox1F,b0)\n");
8979 case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435)
8980 DIP("lbzux r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
8981 if (rA_addr
== 0 || rA_addr
== rD_addr
) {
8982 vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
8985 val
= load(Ity_I8
, mkexpr(EA
));
8986 putIReg( rD_addr
, mkWidenFrom8(ty
, val
, False
) );
8987 putIReg( rA_addr
, mkexpr(EA
) );
8990 case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436)
8991 DIP("lbzx r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
8992 val
= load(Ity_I8
, mkexpr(EA
));
8993 putIReg( rD_addr
, mkWidenFrom8(ty
, val
, False
) );
8996 case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447)
8997 if (rA_addr
== 0 || rA_addr
== rD_addr
) {
8998 vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n");
9001 DIP("lhaux r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
9002 val
= load(Ity_I16
, mkexpr(EA
));
9003 putIReg( rD_addr
, mkWidenFrom16(ty
, val
, True
) );
9004 putIReg( rA_addr
, mkexpr(EA
) );
9007 case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448)
9008 DIP("lhax r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
9009 val
= load(Ity_I16
, mkexpr(EA
));
9010 putIReg( rD_addr
, mkWidenFrom16(ty
, val
, True
) );
9013 case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452)
9014 if (rA_addr
== 0 || rA_addr
== rD_addr
) {
9015 vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n");
9018 DIP("lhzux r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
9019 val
= load(Ity_I16
, mkexpr(EA
));
9020 putIReg( rD_addr
, mkWidenFrom16(ty
, val
, False
) );
9021 putIReg( rA_addr
, mkexpr(EA
) );
9024 case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453)
9025 DIP("lhzx r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
9026 val
= load(Ity_I16
, mkexpr(EA
));
9027 putIReg( rD_addr
, mkWidenFrom16(ty
, val
, False
) );
9030 case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462)
9031 if (rA_addr
== 0 || rA_addr
== rD_addr
) {
9032 vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
9035 DIP("lwzux r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
9036 val
= load(Ity_I32
, mkexpr(EA
));
9037 putIReg( rD_addr
, mkWidenFrom32(ty
, val
, False
) );
9038 putIReg( rA_addr
, mkexpr(EA
) );
9041 case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463)
9042 DIP("lwzx r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
9043 val
= load(Ity_I32
, mkexpr(EA
));
9044 putIReg( rD_addr
, mkWidenFrom32(ty
, val
, False
) );
9049 case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475)
9050 if (rA_addr
== 0 || rA_addr
== rD_addr
) {
9051 vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n");
9054 DIP("ldux r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
9055 putIReg( rD_addr
, load(Ity_I64
, mkexpr(EA
)) );
9056 putIReg( rA_addr
, mkexpr(EA
) );
9059 case 0x015: // ldx (Load DWord, Indexed, PPC64 p476)
9060 DIP("ldx r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
9061 putIReg( rD_addr
, load(Ity_I64
, mkexpr(EA
)) );
9064 case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501)
9065 if (rA_addr
== 0 || rA_addr
== rD_addr
) {
9066 vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n");
9069 DIP("lwaux r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
9071 unop(Iop_32Sto64
, load(Ity_I32
, mkexpr(EA
))) );
9072 putIReg( rA_addr
, mkexpr(EA
) );
9075 case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502)
9076 DIP("lwax r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
9078 unop(Iop_32Sto64
, load(Ity_I32
, mkexpr(EA
))) );
9082 vex_printf("dis_int_load(ppc)(opc2)\n");
9088 vex_printf("dis_int_load(ppc)(opc1)\n");
9095 VSX Vector Splat Immediate Word 8RR:D-form
9097 static Bool
dis_vector_splat_imm_prefix ( UInt prefix
, UInt theInstr
)
9099 UChar opc1
= ifieldOPC(theInstr
);
9100 UChar opc2
= IFIELD(theInstr
, (31-(46-32)), 4); // bits[43:46]
9102 UInt imm0
= ifield_imm_8RR_D(prefix
);
9103 UInt imm1
= ifield_imm_8RR_D(theInstr
);
9104 UInt IMM32
= (imm0
<< 16) | imm1
;
9106 UInt XT_addr
= ifieldRegXT_8RR_D(theInstr
);
9108 if (opc1
!= 0x20) return False
;
9110 /* These are prefix instructions, no equivalent word instruction. */
9115 /* VSX Vector Splat Immediate32 Doubleword Indexed 8RR:D-form */
9116 UInt IX
= IFIELD(theInstr
, (31-(46-32)), 1); // bit[46]
9117 IRTemp tmp
= newTemp(Ity_V128
);
9118 IRTemp mask
= newTemp(Ity_V128
);
9119 IRTemp new_elements
= newTemp(Ity_V128
);
9121 DIP("xxsplti32dx %u,%u,%u\n", XT_addr
, IX
, IMM32
);
9123 assign( tmp
, getVSReg( XT_addr
) );
9126 assign( mask
, binop( Iop_64HLtoV128
,
9127 binop( Iop_32HLto64
,
9128 mkU32( 0 ), mkU32( 0xFFFFFFFF ) ),
9129 binop( Iop_32HLto64
,
9130 mkU32( 0 ), mkU32( 0xFFFFFFFF ) ) ) );
9131 assign( new_elements
, binop( Iop_64HLtoV128
,
9132 binop( Iop_32HLto64
,
9133 mkU32( IMM32
), mkU32( 0 ) ),
9134 binop( Iop_32HLto64
,
9135 mkU32( IMM32
), mkU32( 0 ) ) ) );
9137 assign( mask
, binop( Iop_64HLtoV128
,
9138 binop( Iop_32HLto64
,
9139 mkU32( 0xFFFFFFFF ), mkU32( 0 ) ),
9140 binop( Iop_32HLto64
,
9141 mkU32( 0xFFFFFFFF ), mkU32( 0 ) ) ) );
9142 assign( new_elements
, binop( Iop_64HLtoV128
,
9143 binop( Iop_32HLto64
,
9144 mkU32( 0 ), mkU32( IMM32
) ),
9145 binop( Iop_32HLto64
,
9146 mkU32( 0 ), mkU32( IMM32
) ) ) );
9151 binop( Iop_AndV128
, mkexpr( tmp
), mkexpr( mask
) ),
9152 mkexpr( new_elements
) ) );
9157 IRTemp result
= newTemp(Ity_I64
);
9159 /* VSX Vector Splat Immediate Double-precision 8RR:D-form */
9160 DIP("xxspltidp %u,%u\n", XT_addr
, IMM32
);
9163 unop( Iop_ReinterpF64asI64
,
9165 unop( Iop_ReinterpI32asF32
,
9166 mkU32( IMM32
) ) ) ) );
9167 putVSReg( XT_addr
, binop( Iop_64HLtoV128
,
9168 mkexpr( result
), mkexpr( result
) ) );
9173 /* VSX Vector Splat Immediate Word 8RR:D-form */
9174 DIP("xxspltiw %u,%u\n", XT_addr
, IMM32
);
9177 binop( Iop_64HLtoV128
,
9178 binop( Iop_32HLto64
,
9179 mkU32( IMM32
), mkU32( IMM32
) ),
9180 binop( Iop_32HLto64
,
9181 mkU32( IMM32
), mkU32( IMM32
) ) ) );
9184 vex_printf("dis_vector_splat_imm_prefix (opc2)\n");
9192 VSX Vector Permute Extended 8RR:D-form
9194 static Bool
dis_vector_permute_prefix ( UInt prefix
, UInt theInstr
,
9195 const VexAbiInfo
* vbi
)
9198 UChar opc1
= ifieldOPC(theInstr
);
9199 UChar opc2
= IFIELD(theInstr
, (63-59), 2); // bits[58:59]
9200 UChar rXT_addr
= ifieldRegXT_8RR_XX4( theInstr
);
9201 UChar rXA_addr
= ifieldRegXA_8RR_XX4( theInstr
);
9202 UChar rXB_addr
= ifieldRegXB_8RR_XX4( theInstr
);
9203 UChar rXC_addr
= ifieldRegXC_8RR_XX4( theInstr
);
9206 IRTemp rXA
= newTemp(Ity_V128
);
9207 IRTemp rXB
= newTemp(Ity_V128
);
9208 IRTemp rXC
= newTemp(Ity_V128
);
9209 IRTemp cmp_mask
= newTemp(Ity_I64
);
9210 IRTemp eidx_mask
= newTemp(Ity_I64
);
9211 IRTemp result
[MAX_ELE
+1];
9212 IRTemp result_mask
[MAX_ELE
];
9213 IRTemp byte
[MAX_ELE
];
9214 IRTemp eidx
[MAX_ELE
];
9216 /* These are prefix instructions, no equivalent word instruction. */
9217 if ((opc1
!= 0x22) && (opc2
!= 0)) return False
;
9219 assign( rXA
, getVSReg( rXA_addr
) );
9220 assign( rXB
, getVSReg( rXB_addr
) );
9221 assign( rXC
, getVSReg( rXC_addr
) );
9226 UInt UIM
= IFIELD(prefix
, 0, 3); // bit [29:31] of the prefix
9228 DIP("xxpermx v%u,v%u,v%u,v%u,%u\n",
9229 rXT_addr
, rXA_addr
, rXB_addr
, rXC_addr
, UIM
);
9231 result
[MAX_ELE
] = newTemp(Ity_V128
);
9232 assign( eidx_mask
, mkU64( 0x1F ) );
9233 assign( cmp_mask
, mkU64( 0x7 ) );
9234 assign( result
[MAX_ELE
], binop( Iop_64HLtoV128
, mkU64( 0 ),
9237 for (i
= MAX_ELE
-1; i
>= 0; i
--) {
9238 eidx
[i
] = newTemp( Ity_I64
);
9239 byte
[i
] = newTemp( Ity_I64
);
9240 result
[i
] = newTemp( Ity_V128
);
9241 result_mask
[i
] = newTemp( Ity_I64
);
9243 /* The eidx is left based, make index right based for
9244 extractBytefromV256(). */
9250 mkexpr( eidx_mask
),
9252 unop( Iop_V128HIto64
, mkexpr( rXC
) ),
9253 mkU8( (i
- 8)*8 ) ) ) ) );
9254 assign( result_mask
[i
],
9259 mkexpr ( cmp_mask
),
9260 // bits 0:2 of ith byte
9262 unop( Iop_V128HIto64
,
9264 mkU8( (i
- 8)*8 + 5 ) ) )
9271 mkexpr( eidx_mask
),
9273 unop( Iop_V128to64
, mkexpr( rXC
) ),
9274 mkU8( i
*8 ) ) ) ) );
9275 assign( result_mask
[i
],
9280 mkexpr ( cmp_mask
),
9281 // bits 0:2 of ith byte
9285 mkU8( i
*8 + 5 ) ) ) ) ) );
9290 mkexpr( result_mask
[i
] ),
9291 extractBytefromV256( rXA
, rXB
, eidx
[i
] ) ) );
9293 assign( result
[i
], insert_field_into_vector( result
[i
+1],
9298 putVSReg( rXT_addr
, mkexpr( result
[0] ) );
9304 UInt IMM
= IFIELD(prefix
, 0, 8); // bit [24:31] of the prefix
9305 DIP("xxeval v%u,v%u,v%u,v%u,%u\n",
9306 rXT_addr
, rXA_addr
, rXB_addr
, rXC_addr
, IMM
);
9308 vector_evaluate_inst ( vbi
, mkexpr( rXA
), mkexpr( rXB
),
9309 mkexpr( rXC
), mkU64( IMM
) ) );
9314 vex_printf("dis_vector_permute_prefix(ppc)(opc2)\n");
9323 VSX Vector Splat Immediate Word 8RR:D-form
9325 static Bool
dis_vector_blend_prefix ( UInt prefix
, UInt theInstr
)
9327 UChar opc1
= ifieldOPC(theInstr
);
9328 UChar opc2
= IFIELD(theInstr
, (63-59), 2); // bits[58:59]
9329 UChar rXT_addr
= ifieldRegXT_8RR_XX4( theInstr
);
9330 UChar rXA_addr
= ifieldRegXA_8RR_XX4( theInstr
);
9331 UChar rXB_addr
= ifieldRegXB_8RR_XX4( theInstr
);
9332 UChar rXC_addr
= ifieldRegXC_8RR_XX4( theInstr
);
9334 IRTemp rXA
= newTemp(Ity_V128
);
9335 IRTemp rXB
= newTemp(Ity_V128
);
9336 IRTemp rXC
= newTemp(Ity_V128
);
9337 IRTemp bit_mask
= newTemp(Ity_V128
);
9338 IRTemp mask_gen
= newTemp(Ity_V128
);
9339 IRTemp mask
= newTemp(Ity_V128
);
9341 /* These are prefix instructions, no equivalent word instruction. */
9342 if (opc1
!= 0x21) return False
;
9344 /* Generate the mask to select the elements from rXA or rXB. Use a vector
9345 multiply to generate the mask to select the elments. Take the selctor
9346 bit for the element (rXC & bit_mask) and multiply it by all 1's
9347 (mask_gen). If the selector bit was 0, then we get zero bits for that
9348 element entry, otherwise we get 1's.
9350 Unfortunately, we don't have an integer vector multipy have to do it as
9351 an even and odd multiply for byt, halfword and word elements. Note, the
9352 MK_Iop_MullOddXUxY shifts the operands right and uses the MullEven
9353 operator, so we have to move the result back to its correct lane
9356 assign( rXA
, getVSReg( rXA_addr
) );
9357 assign( rXB
, getVSReg( rXB_addr
) );
9358 assign( rXC
, getVSReg( rXC_addr
) );
9361 binop( Iop_64HLtoV128
,
9362 mkU64( 0xFFFFFFFFFFFFFFFFULL
),
9363 mkU64( 0xFFFFFFFFFFFFFFFFULL
) ) );
9367 /* VSX Vector Blend Variable Byte 8RR:XX4-Form */
9368 DIP("xxblendvb v%u,v%u,v%u,v%u\n",
9369 rXT_addr
, rXA_addr
, rXB_addr
, rXC_addr
);
9375 binop( Iop_64HLtoV128
,
9376 mkU64( 0x8080808080808080ULL
),
9377 mkU64( 0x8080808080808080ULL
) ) ),
9381 binop( Iop_MullEven8Ux16
,
9383 mkexpr( bit_mask
) ),
9385 MK_Iop_MullOdd8Ux16(
9387 mkexpr( bit_mask
) ),
9392 /* VSX Vector Blend Variable Halfword 8RR:XX4-Form */
9393 DIP("xxblendvh v%u,v%u,v%u,v%u\n",
9394 rXT_addr
, rXA_addr
, rXB_addr
, rXC_addr
);
9400 binop( Iop_64HLtoV128
,
9401 mkU64( 0x8000800080008000ULL
),
9402 mkU64( 0x8000800080008000ULL
) ) ),
9406 binop( Iop_MullEven16Ux8
,
9408 mkexpr( bit_mask
) ),
9410 MK_Iop_MullOdd16Ux8(
9412 mkexpr( bit_mask
) ),
9417 /* VSX Vector Blend Variable Word 8RR:XX4-Form */
9418 DIP("xxblendvw v%u,v%u,v%u,v%u\n",
9419 rXT_addr
, rXA_addr
, rXB_addr
, rXC_addr
);
9425 binop( Iop_64HLtoV128
,
9426 mkU64( 0x8000000080000000ULL
),
9427 mkU64( 0x8000000080000000ULL
) ) ),
9431 binop( Iop_MullEven32Ux4
,
9433 mkexpr( bit_mask
) ),
9435 MK_Iop_MullOdd32Ux4(
9437 mkexpr( bit_mask
) ),
9442 /* VSX Vector Blend Variable Double 8RR:XX4-Form */
9443 DIP("xxblendvd v%u,v%u,v%u,v%u\n",
9444 rXT_addr
, rXA_addr
, rXB_addr
, rXC_addr
);
9446 /* Have to use a different trick here */
9448 binop( Iop_64HLtoV128
,
9452 unop( Iop_V128HIto64
,
9460 mkU8( 63) ) ) ) ) );
9464 vex_printf("dis_vector_blend_prefix (opc2)\n");
9467 putVSReg( rXT_addr
, binop( Iop_OrV128
,
9469 unop( Iop_NotV128
, mkexpr( mask
) ),
9473 mkexpr( rXB
) ) ) );
9479 Integer Store Instructions
9481 static Bool
dis_int_store_ds_prefix ( UInt prefix
,
9482 UInt theInstr
, const VexAbiInfo
* vbi
)
9484 UChar opc1
= ifieldOPC(theInstr
);
9485 UInt rS_addr
= ifieldRegDS(theInstr
);
9486 UInt rA_addr
= ifieldRegA(theInstr
);
9487 UChar b0
= ifieldBIT0(theInstr
);
9488 UChar b1
= ifieldBIT1(theInstr
);
9489 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
9490 IRTemp rS
= newTemp(ty
);
9491 IRTemp EA
= newTemp(ty
);
9492 UInt ptype
= PrefixType(prefix
);
9493 Bool is_prefix
= prefix_instruction( prefix
);
9494 UInt R
= 0; // must be zero for word instruction
9495 ULong immediate_val
= 0;
9496 Int simm16
= extend_s_16to32(ifieldUIMM16(theInstr
));
9499 // force opc2 to 2 to map pstq to stq inst
9502 assign( EA
, calculate_prefix_EA( prefix
, theInstr
, rA_addr
,
9503 ptype
, DSFORM_IMMASK
, &immediate_val
,
9505 } else if (opc1
== 0x3D) {
9506 // force opc2 to 0 to map pstd to std inst
9509 assign( EA
, calculate_prefix_EA( prefix
, theInstr
, rA_addr
,
9510 ptype
, DFORM_IMMASK
, &immediate_val
,
9513 } else if ( opc1
== 0x3 ) {
9514 assign( EA
, ea_rAor0_simm( rA_addr
, simm16
) );
9516 } else if ( opc1
== 0x3E ) { // std, stdu, stq
9517 // lowest 2 bits of immediate before forming EA
9518 immediate_val
= simm16
& 0xFFFFFFFC;
9519 assign( EA
, ea_rAor0_simm( rA_addr
, immediate_val
) );
9525 assign( rS
, getIReg(rS_addr
) );
9527 /* DS Form - 64bit Stores. In each case EA will have been formed
9528 with the lowest 2 bits masked off the immediate offset. */
9529 switch ((b1
<<1) | b0
) {
9530 case 0x0: // std (Store DWord, PPC64 p580)
9534 pDIP( is_prefix
,"std r%u,%llu(r%u)", rS_addr
, immediate_val
, rA_addr
);
9535 DIPp( is_prefix
, ",%u", R
);
9536 store( mkexpr(EA
), mkexpr(rS
) );
9539 case 0x1: // stdu (Store DWord, Update, PPC64 p583)
9540 /* Note this instruction is handled here but it isn't actually a
9541 prefix instruction. Just makes the parsing easier to handle it
9546 DIP("stdu r%u,%llu(r%u)\n", rS_addr
, immediate_val
, rA_addr
);
9547 putIReg( rA_addr
, mkexpr(EA
) );
9548 store( mkexpr(EA
), mkexpr(rS
) );
9551 case 0x2: // stq, pstq (Store QuadWord, Update, PPC64 p583)
9553 IRTemp EA_hi
= newTemp(ty
);
9554 IRTemp EA_lo
= newTemp(ty
);
9556 pDIP( is_prefix
, "stq r%u,%llu(r%u)", rS_addr
, immediate_val
, rA_addr
);
9557 DIPp( is_prefix
, ",%u", R
);
9560 if (host_endness
== VexEndnessBE
) {
9563 assign( EA_hi
, mkexpr(EA
));
9566 assign( EA_lo
, binop(Iop_Add64
, mkexpr(EA
), mkU64(8)));
9570 assign( EA_hi
, binop(Iop_Add64
, mkexpr(EA
), mkU64(8)));
9573 assign( EA_lo
, mkexpr(EA
));
9576 /* upper half of upper 64-bits */
9577 assign( EA_hi
, binop(Iop_Add32
, mkexpr(EA
), mkU32(4)));
9579 /* lower half of upper 64-bits */
9580 assign( EA_lo
, binop(Iop_Add32
, mkexpr(EA
), mkU32(12)));
9583 /* Note, the store order for stq instruction is the same for BE
9584 and LE. The store order for the pstq instruction is endian aware
9586 if (is_prefix
&&( host_endness
== VexEndnessLE
)) {
9588 store( mkexpr(EA_hi
), getIReg( rS_addr
+1 ) );
9589 store( mkexpr(EA_lo
), mkexpr(rS
) );
9591 store( mkexpr(EA_hi
), mkexpr(rS
) );
9592 store( mkexpr(EA_lo
), getIReg( rS_addr
+1 ) );
9597 vex_printf("dis_int_store_ds_prefix(ppc)(opc1)\n");
9603 static Bool
dis_int_store_prefix ( UInt prefix
,
9604 UInt theInstr
, const VexAbiInfo
* vbi
)
9606 UChar opc1
= ifieldOPC(theInstr
);
9607 UInt rS_addr
= ifieldRegDS(theInstr
);
9608 UInt rA_addr
= ifieldRegA(theInstr
);
9609 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
9610 IRTemp rS
= newTemp(ty
);
9611 IRTemp EA
= newTemp(ty
);
9612 UInt ptype
= PrefixType(prefix
);
9613 Bool is_prefix
= prefix_instruction( prefix
);
9614 ULong immediate_val
= 0;
9615 UInt R
= 0; // must be zero for word instruction
9617 assign( rS
, getIReg(rS_addr
) );
9618 assign( EA
, calculate_prefix_EA( prefix
, theInstr
, rA_addr
,
9619 ptype
, DFORM_IMMASK
,
9620 &immediate_val
, &R
) );
9623 case 0x24: // stw (Store W, PPC32 p530)
9624 pDIP( is_prefix
, "stw r%u,%llu(r%u)\n", rS_addr
, immediate_val
, rA_addr
);
9625 DIPp( is_prefix
, ",%u", R
);
9626 store( mkexpr(EA
), mkNarrowTo32(ty
, mkexpr(rS
)) );
9629 case 0x26: // stb (Store B, PPC32 p509)
9630 pDIP( is_prefix
, "stb r%u,%llu(r%u)", rS_addr
, immediate_val
, rA_addr
);
9631 DIPp( is_prefix
, ",%u", R
);
9632 store( mkexpr(EA
), mkNarrowTo8(ty
, mkexpr(rS
)) );
9635 case 0x2C: // sth (Store HW, PPC32 p522)
9636 pDIP( is_prefix
, "sth r%u,%llu(r%u)", rS_addr
, immediate_val
, rA_addr
);
9637 DIPp( is_prefix
, ",%u", R
);
9638 store( mkexpr(EA
), mkNarrowTo16(ty
, mkexpr(rS
)) );
9642 vex_printf("dis_int_store_prefix(ppc)(opc1)\n");
9648 static Bool
dis_int_store ( UInt prefix
, UInt theInstr
, const VexAbiInfo
* vbi
)
9650 /* D-Form, X-Form, DS-Form */
9651 UChar opc1
= ifieldOPC(theInstr
);
9652 UInt rS_addr
= ifieldRegDS(theInstr
);
9653 UInt rA_addr
= ifieldRegA(theInstr
);
9654 UInt uimm16
= ifieldUIMM16(theInstr
);
9655 UInt rB_addr
= ifieldRegB(theInstr
);
9656 UInt opc2
= ifieldOPClo10(theInstr
);
9657 UChar b0
= ifieldBIT0(theInstr
);
9659 Int simm16
= extend_s_16to32(uimm16
);
9660 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
9661 IRTemp rS
= newTemp(ty
);
9662 IRTemp rB
= newTemp(ty
);
9663 IRTemp EA
= newTemp(ty
);
9665 /* There is no prefixed version of these instructions. */
9668 assign( rB
, getIReg(rB_addr
) );
9669 assign( rS
, getIReg(rS_addr
) );
9672 case 0x1F: // register offset
9673 assign( EA
, ea_rAor0_idxd( rA_addr
, rB_addr
) );
9677 default: // immediate offset
9678 assign( EA
, ea_rAor0_simm( rA_addr
, simm16
) );
9683 case 0x27: // stbu (Store B, Update, PPC32 p510)
9684 if (rA_addr
== 0 ) {
9685 vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n");
9688 DIP("stbu r%u,%d(r%u)\n", rS_addr
, simm16
, rA_addr
);
9689 putIReg( rA_addr
, mkexpr(EA
) );
9690 store( mkexpr(EA
), mkNarrowTo8(ty
, mkexpr(rS
)) );
9693 case 0x2D: // sthu (Store HW, Update, PPC32 p524)
9695 vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n");
9698 DIP("sthu r%u,%d(r%u)\n", rS_addr
, simm16
, rA_addr
);
9699 putIReg( rA_addr
, mkexpr(EA
) );
9700 store( mkexpr(EA
), mkNarrowTo16(ty
, mkexpr(rS
)) );
9703 case 0x24: // stw (Store W, PPC32 p530)
9705 DIP("stw r%u,%d(r%u)\n", rS_addr
, simm16
, rA_addr
);
9706 store( mkexpr(EA
), mkNarrowTo32(ty
, mkexpr(rS
)) );
9710 case 0x25: // stwu (Store W, Update, PPC32 p534)
9712 vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n");
9715 DIP("stwu r%u,%d(r%u)\n", rS_addr
, simm16
, rA_addr
);
9716 putIReg( rA_addr
, mkexpr(EA
) );
9717 store( mkexpr(EA
), mkNarrowTo32(ty
, mkexpr(rS
)) );
9720 /* X Form : all these use EA_indexed */
9723 vex_printf("dis_int_store(ppc)(0x1F,b0)\n");
9728 case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511)
9730 vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n");
9733 DIP("stbux r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
9734 putIReg( rA_addr
, mkexpr(EA
) );
9735 store( mkexpr(EA
), mkNarrowTo8(ty
, mkexpr(rS
)) );
9738 case 0x0D7: // stbx (Store B Indexed, PPC32 p512)
9739 DIP("stbx r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
9740 store( mkexpr(EA
), mkNarrowTo8(ty
, mkexpr(rS
)) );
9743 case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525)
9745 vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n");
9748 DIP("sthux r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
9749 putIReg( rA_addr
, mkexpr(EA
) );
9750 store( mkexpr(EA
), mkNarrowTo16(ty
, mkexpr(rS
)) );
9753 case 0x197: // sthx (Store HW Indexed, PPC32 p526)
9754 DIP("sthx r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
9755 store( mkexpr(EA
), mkNarrowTo16(ty
, mkexpr(rS
)) );
9758 case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535)
9760 vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n");
9763 DIP("stwux r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
9764 putIReg( rA_addr
, mkexpr(EA
) );
9765 store( mkexpr(EA
), mkNarrowTo32(ty
, mkexpr(rS
)) );
9768 case 0x097: // stwx (Store W Indexed, PPC32 p536)
9769 DIP("stwx r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
9770 store( mkexpr(EA
), mkNarrowTo32(ty
, mkexpr(rS
)) );
9775 case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584)
9777 vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n");
9780 DIP("stdux r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
9781 putIReg( rA_addr
, mkexpr(EA
) );
9782 store( mkexpr(EA
), mkexpr(rS
) );
9785 case 0x095: // stdx (Store DWord Indexed, PPC64 p585)
9786 DIP("stdx r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
9787 store( mkexpr(EA
), mkexpr(rS
) );
9791 vex_printf("dis_int_store(ppc)(opc2)\n");
9797 vex_printf("dis_int_store(ppc)(opc1)\n");
9806 Integer Load/Store Multiple Instructions
9808 static Bool
dis_int_ldst_mult ( UInt prefix
, UInt theInstr
)
9811 UChar opc1
= ifieldOPC(theInstr
);
9812 UChar rD_addr
= ifieldRegDS(theInstr
);
9813 UChar rS_addr
= rD_addr
;
9814 UChar rA_addr
= ifieldRegA(theInstr
);
9815 UInt uimm16
= ifieldUIMM16(theInstr
);
9817 Int simm16
= extend_s_16to32(uimm16
);
9818 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
9819 IROp mkAdd
= mode64
? Iop_Add64
: Iop_Add32
;
9820 IRTemp EA
= newTemp(ty
);
9825 /* There is no prefixed version of these instructions. */
9828 assign( EA
, ea_rAor0_simm( rA_addr
, simm16
) );
9831 case 0x2E: // lmw (Load Multiple Word, PPC32 p454)
9832 if (rA_addr
>= rD_addr
) {
9833 vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n");
9836 DIP("lmw r%u,%d(r%u)\n", rD_addr
, simm16
, rA_addr
);
9837 for (r
= rD_addr
; r
<= 31; r
++) {
9838 irx_addr
= binop(mkAdd
, mkexpr(EA
), mode64
? mkU64(ea_off
) : mkU32(ea_off
));
9839 putIReg( r
, mkWidenFrom32(ty
, load(Ity_I32
, irx_addr
),
9845 case 0x2F: // stmw (Store Multiple Word, PPC32 p527)
9846 DIP("stmw r%u,%d(r%u)\n", rS_addr
, simm16
, rA_addr
);
9847 for (r
= rS_addr
; r
<= 31; r
++) {
9848 irx_addr
= binop(mkAdd
, mkexpr(EA
), mode64
? mkU64(ea_off
) : mkU32(ea_off
));
9849 store( irx_addr
, mkNarrowTo32(ty
, getIReg(r
)) );
9855 vex_printf("dis_int_ldst_mult(ppc)(opc1)\n");
9864 Integer Load/Store String Instructions
9867 void generate_lsw_sequence ( IRTemp tNBytes
, // # bytes, :: Ity_I32
9869 Int rD
, // first dst register
9870 Int maxBytes
) // 32 or 128
9873 IRExpr
* e_nbytes
= mkexpr(tNBytes
);
9874 IRExpr
* e_EA
= mkexpr(EA
);
9875 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
9877 vassert(rD
>= 0 && rD
< 32);
9878 rD
--; if (rD
< 0) rD
= 31;
9880 for (i
= 0; i
< maxBytes
; i
++) {
9881 /* if (nBytes < (i+1)) goto NIA; */
9882 stmt( IRStmt_Exit( binop(Iop_CmpLT32U
, e_nbytes
, mkU32(i
+1)),
9884 mkSzConst( ty
, nextInsnAddr()), OFFB_CIA
));
9885 /* when crossing into a new dest register, set it to zero. */
9887 rD
++; if (rD
== 32) rD
= 0;
9888 putIReg(rD
, mkSzImm(ty
, 0));
9891 /* rD |= (8Uto32(*(EA+i))) << shift */
9892 vassert(shift
== 0 || shift
== 8 || shift
== 16 || shift
== 24);
9899 mkNarrowTo32(ty
, getIReg(rD
)),
9905 binop( mkSzOp(ty
,Iop_Add8
),
9906 e_EA
, mkSzImm(ty
,i
)))
9908 mkU8(toUChar(shift
))
9919 void generate_stsw_sequence ( IRTemp tNBytes
, // # bytes, :: Ity_I32
9921 Int rS
, // first src register
9922 Int maxBytes
) // 32 or 128
9925 IRExpr
* e_nbytes
= mkexpr(tNBytes
);
9926 IRExpr
* e_EA
= mkexpr(EA
);
9927 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
9929 vassert(rS
>= 0 && rS
< 32);
9930 rS
--; if (rS
< 0) rS
= 31;
9932 for (i
= 0; i
< maxBytes
; i
++) {
9933 /* if (nBytes < (i+1)) goto NIA; */
9934 stmt( IRStmt_Exit( binop(Iop_CmpLT32U
, e_nbytes
, mkU32(i
+1)),
9936 mkSzConst( ty
, nextInsnAddr() ), OFFB_CIA
));
9937 /* check for crossing into a new src register. */
9939 rS
++; if (rS
== 32) rS
= 0;
9942 /* *(EA+i) = 32to8(rS >> shift) */
9943 vassert(shift
== 0 || shift
== 8 || shift
== 16 || shift
== 24);
9945 binop( mkSzOp(ty
,Iop_Add8
), e_EA
, mkSzImm(ty
,i
)),
9948 mkNarrowTo32( ty
, getIReg(rS
) ),
9949 mkU8( toUChar(shift
) )))
9955 static Bool
dis_int_ldst_str ( UInt prefix
, UInt theInstr
, /*OUT*/Bool
* stopHere
)
9958 UChar opc1
= ifieldOPC(theInstr
);
9959 UChar rD_addr
= ifieldRegDS(theInstr
);
9960 UChar rS_addr
= rD_addr
;
9961 UChar rA_addr
= ifieldRegA(theInstr
);
9962 UChar rB_addr
= ifieldRegB(theInstr
);
9963 UChar NumBytes
= rB_addr
;
9964 UInt opc2
= ifieldOPClo10(theInstr
);
9965 UChar b0
= ifieldBIT0(theInstr
);
9967 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
9968 IRTemp t_EA
= newTemp(ty
);
9969 IRTemp t_nbytes
= IRTemp_INVALID
;
9971 /* There is no prefixed version of these instructions. */
9976 if (opc1
!= 0x1F || b0
!= 0) {
9977 vex_printf("dis_int_ldst_str(ppc)(opc1)\n");
9982 case 0x255: // lswi (Load String Word Immediate, PPC32 p455)
9983 /* NB: does not reject the case where RA is in the range of
9984 registers to be loaded. It should. */
9985 DIP("lswi r%u,r%u,%d\n", rD_addr
, rA_addr
, NumBytes
);
9986 assign( t_EA
, ea_rAor0(rA_addr
) );
9987 if (NumBytes
== 8 && !mode64
) {
9988 /* Special case hack */
9989 /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */
9991 load(Ity_I32
, mkexpr(t_EA
)) );
9992 putIReg( (rD_addr
+1) % 32,
9994 binop(Iop_Add32
, mkexpr(t_EA
), mkU32(4))) );
9996 t_nbytes
= newTemp(Ity_I32
);
9997 assign( t_nbytes
, mkU32(NumBytes
==0 ? 32 : NumBytes
) );
9998 generate_lsw_sequence( t_nbytes
, t_EA
, rD_addr
, 32 );
10003 case 0x215: // lswx (Load String Word Indexed, PPC32 p456)
10004 /* NB: does not reject the case where RA is in the range of
10005 registers to be loaded. It should. Although considering
10006 that that can only be detected at run time, it's not easy to
10008 if (rD_addr
== rA_addr
|| rD_addr
== rB_addr
)
10010 if (rD_addr
== 0 && rA_addr
== 0)
10012 DIP("lswx r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
10013 t_nbytes
= newTemp(Ity_I32
);
10014 assign( t_EA
, ea_rAor0_idxd(rA_addr
,rB_addr
) );
10015 assign( t_nbytes
, unop( Iop_8Uto32
, getXER_BC() ) );
10016 generate_lsw_sequence( t_nbytes
, t_EA
, rD_addr
, 128 );
10020 case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528)
10021 DIP("stswi r%u,r%u,%d\n", rS_addr
, rA_addr
, NumBytes
);
10022 assign( t_EA
, ea_rAor0(rA_addr
) );
10023 if (NumBytes
== 8 && !mode64
) {
10024 /* Special case hack */
10025 /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */
10026 store( mkexpr(t_EA
),
10027 getIReg(rD_addr
) );
10028 store( binop(Iop_Add32
, mkexpr(t_EA
), mkU32(4)),
10029 getIReg((rD_addr
+1) % 32) );
10031 t_nbytes
= newTemp(Ity_I32
);
10032 assign( t_nbytes
, mkU32(NumBytes
==0 ? 32 : NumBytes
) );
10033 generate_stsw_sequence( t_nbytes
, t_EA
, rD_addr
, 32 );
10038 case 0x295: // stswx (Store String Word Indexed, PPC32 p529)
10039 DIP("stswx r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
10040 t_nbytes
= newTemp(Ity_I32
);
10041 assign( t_EA
, ea_rAor0_idxd(rA_addr
,rB_addr
) );
10042 assign( t_nbytes
, unop( Iop_8Uto32
, getXER_BC() ) );
10043 generate_stsw_sequence( t_nbytes
, t_EA
, rS_addr
, 128 );
10048 vex_printf("dis_int_ldst_str(ppc)(opc2)\n");
10055 /* ------------------------------------------------------------------
10056 Integer Branch Instructions
10057 ------------------------------------------------------------------ */
10060 Branch helper function
10061 ok = BO[2] | ((CTR[0] != 0) ^ BO[1])
10062 Returns an I32 which is 0x00000000 if the ctr condition failed
10063 and 0xFFFFFFFF otherwise.
10065 static IRExpr
* /* :: Ity_I32 */ branch_ctr_ok( UInt BO
)
10067 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
10068 IRTemp ok
= newTemp(Ity_I32
);
10070 if ((BO
>> 2) & 1) { // independent of ctr
10071 assign( ok
, mkU32(0xFFFFFFFF) );
10073 if ((BO
>> 1) & 1) { // ctr == 0 ?
10074 assign( ok
, unop( Iop_1Sto32
,
10075 binop( mkSzOp(ty
, Iop_CmpEQ8
),
10076 getGST( PPC_GST_CTR
),
10078 } else { // ctr != 0 ?
10079 assign( ok
, unop( Iop_1Sto32
,
10080 binop( mkSzOp(ty
, Iop_CmpNE8
),
10081 getGST( PPC_GST_CTR
),
10090 Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3])
10091 Returns an I32 which is either 0 if the condition failed or
10092 some arbitrary nonzero value otherwise. */
10094 static IRExpr
* /* :: Ity_I32 */ branch_cond_ok( UInt BO
, UInt BI
)
10097 IRTemp res
= newTemp(Ity_I32
);
10098 IRTemp cr_bi
= newTemp(Ity_I32
);
10100 if ((BO
>> 4) & 1) {
10101 assign( res
, mkU32(1) );
10103 // ok = (CR[BI] == BO[3]) Note, the following relies on
10104 // getCRbit_anywhere returning a value which
10105 // is either zero or has exactly 1 bit set.
10106 assign( cr_bi
, getCRbit_anywhere( BI
, &where
) );
10108 if ((BO
>> 3) & 1) {
10109 /* We can use cr_bi as-is. */
10110 assign( res
, mkexpr(cr_bi
) );
10112 /* We have to invert the sense of the information held in
10113 cr_bi. For that we need to know which bit
10114 getCRbit_anywhere regards as significant. */
10115 assign( res
, binop(Iop_Xor32
, mkexpr(cr_bi
),
10116 mkU32(1<<where
)) );
10119 return mkexpr(res
);
10124 Integer Branch Instructions
10126 static Bool
dis_branch ( UInt prefix
, UInt theInstr
,
10127 const VexAbiInfo
* vbi
,
10128 /*OUT*/DisResult
* dres
)
10130 UChar opc1
= ifieldOPC(theInstr
);
10131 UChar BO
= ifieldRegDS(theInstr
);
10132 UChar BI
= ifieldRegA(theInstr
);
10133 UInt BD_u16
= ifieldUIMM16(theInstr
) & 0xFFFFFFFC; /* mask off */
10134 UChar b11to15
= ifieldRegB(theInstr
);
10135 UInt opc2
= ifieldOPClo10(theInstr
);
10136 UInt LI_u26
= ifieldUIMM26(theInstr
) & 0xFFFFFFFC; /* mask off */
10137 UChar flag_AA
= ifieldBIT1(theInstr
);
10138 UChar flag_LK
= ifieldBIT0(theInstr
);
10140 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
10142 UInt BD
= extend_s_16to32(BD_u16
);
10143 IRTemp do_branch
= newTemp(Ity_I32
);
10144 IRTemp ctr_ok
= newTemp(Ity_I32
);
10145 IRTemp cond_ok
= newTemp(Ity_I32
);
10146 IRExpr
* e_nia
= mkSzImm(ty
, nextInsnAddr());
10147 IRConst
* c_nia
= mkSzConst(ty
, nextInsnAddr());
10148 IRTemp lr_old
= newTemp(ty
);
10150 /* There is no prefixed version of these instructions. */
10153 /* Hack to pass through code that just wants to read the PC */
10154 if (theInstr
== 0x429F0005) {
10155 DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO
, BI
);
10156 putGST( PPC_GST_LR
, e_nia
);
10160 /* The default what-next. Individual cases can override it. */
10161 dres
->whatNext
= Dis_StopHere
;
10162 vassert(dres
->jk_StopHere
== Ijk_INVALID
);
10165 case 0x12: // b (Branch, PPC32 p360)
10167 tgt
= mkSzAddr( ty
, extend_s_26to64(LI_u26
) );
10169 tgt
= mkSzAddr( ty
, guest_CIA_curr_instr
+
10170 (Long
)extend_s_26to64(LI_u26
) );
10173 DIP("b%s%s 0x%llx\n",
10174 flag_LK
? "l" : "", flag_AA
? "a" : "", tgt
);
10176 DIP("b%s%s 0x%x\n",
10177 flag_LK
? "l" : "", flag_AA
? "a" : "", (Addr32
)tgt
);
10181 putGST( PPC_GST_LR
, e_nia
);
10182 if (vbi
->guest_ppc_zap_RZ_at_bl
10183 && vbi
->guest_ppc_zap_RZ_at_bl( (ULong
)tgt
) ) {
10184 IRTemp t_tgt
= newTemp(ty
);
10185 assign(t_tgt
, mode64
? mkU64(tgt
) : mkU32(tgt
) );
10186 make_redzone_AbiHint( vbi
, t_tgt
,
10187 "branch-and-link (unconditional call)" );
10191 dres
->jk_StopHere
= flag_LK
? Ijk_Call
: Ijk_Boring
; ;
10192 putGST( PPC_GST_CIA
, mkSzImm(ty
, tgt
) );
10195 case 0x10: // bc (Branch Conditional, PPC32 p361)
10196 DIP("bc%s%s 0x%x, 0x%x, 0x%x\n",
10197 flag_LK
? "l" : "", flag_AA
? "a" : "", BO
, BI
, BD
);
10200 putGST( PPC_GST_CTR
,
10201 binop(mkSzOp(ty
, Iop_Sub8
),
10202 getGST( PPC_GST_CTR
), mkSzImm(ty
, 1)) );
10205 /* This is a bit subtle. ctr_ok is either all 0s or all 1s.
10206 cond_ok is either zero or nonzero, since that's the cheapest
10207 way to compute it. Anding them together gives a value which
10208 is either zero or non zero and so that's what we must test
10209 for in the IRStmt_Exit. */
10210 assign( ctr_ok
, branch_ctr_ok( BO
) );
10211 assign( cond_ok
, branch_cond_ok( BO
, BI
) );
10213 binop(Iop_And32
, mkexpr(cond_ok
), mkexpr(ctr_ok
)) );
10216 tgt
= mkSzAddr(ty
, extend_s_16to64(BD_u16
));
10218 tgt
= mkSzAddr(ty
, guest_CIA_curr_instr
+
10219 (Long
)extend_s_16to64(BD_u16
));
10222 putGST( PPC_GST_LR
, e_nia
);
10225 binop(Iop_CmpNE32
, mkexpr(do_branch
), mkU32(0)),
10226 flag_LK
? Ijk_Call
: Ijk_Boring
,
10227 mkSzConst(ty
, tgt
), OFFB_CIA
) );
10229 dres
->jk_StopHere
= Ijk_Boring
;
10230 putGST( PPC_GST_CIA
, e_nia
);
10234 /* For bclr and bcctr, it appears that the lowest two bits of
10235 b11to15 are a branch hint, and so we only need to ensure it's
10236 of the form 000XX. */
10237 if ((b11to15
& ~3) != 0) {
10238 vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", b11to15
);
10243 case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363)
10244 if ((BO
& 0x4) == 0) { // "decr and test CTR" option invalid
10245 vex_printf("dis_int_branch(ppc)(bcctr,BO)\n");
10248 DIP("bcctr%s 0x%x, 0x%x\n", flag_LK
? "l" : "", BO
, BI
);
10250 assign( cond_ok
, branch_cond_ok( BO
, BI
) );
10252 /* FIXME: this is confusing. lr_old holds the old value
10253 of ctr, not lr :-) */
10254 assign( lr_old
, addr_align( getGST( PPC_GST_CTR
), 4 ));
10257 putGST( PPC_GST_LR
, e_nia
);
10260 binop(Iop_CmpEQ32
, mkexpr(cond_ok
), mkU32(0)),
10262 c_nia
, OFFB_CIA
));
10264 if (flag_LK
&& vbi
->guest_ppc_zap_RZ_at_bl
) {
10265 make_redzone_AbiHint( vbi
, lr_old
,
10266 "b-ctr-l (indirect call)" );
10269 dres
->jk_StopHere
= flag_LK
? Ijk_Call
: Ijk_Boring
;;
10270 putGST( PPC_GST_CIA
, mkexpr(lr_old
) );
10273 case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365)
10274 Bool vanilla_return
= False
;
10275 if ((BO
& 0x14 /* 1z1zz */) == 0x14 && flag_LK
== 0) {
10277 vanilla_return
= True
;
10279 DIP("bclr%s 0x%x, 0x%x\n", flag_LK
? "l" : "", BO
, BI
);
10283 putGST( PPC_GST_CTR
,
10284 binop(mkSzOp(ty
, Iop_Sub8
),
10285 getGST( PPC_GST_CTR
), mkSzImm(ty
, 1)) );
10288 /* See comments above for 'bc' about this */
10289 assign( ctr_ok
, branch_ctr_ok( BO
) );
10290 assign( cond_ok
, branch_cond_ok( BO
, BI
) );
10292 binop(Iop_And32
, mkexpr(cond_ok
), mkexpr(ctr_ok
)) );
10294 assign( lr_old
, addr_align( getGST( PPC_GST_LR
), 4 ));
10297 putGST( PPC_GST_LR
, e_nia
);
10300 binop(Iop_CmpEQ32
, mkexpr(do_branch
), mkU32(0)),
10302 c_nia
, OFFB_CIA
));
10304 if (vanilla_return
&& vbi
->guest_ppc_zap_RZ_at_blr
) {
10305 make_redzone_AbiHint( vbi
, lr_old
,
10306 "branch-to-lr (unconditional return)" );
10309 /* blrl is pretty strange; it's like a return that sets the
10310 return address of its caller to the insn following this
10311 one. Mark it as a return. */
10312 dres
->jk_StopHere
= Ijk_Ret
; /* was flag_LK ? Ijk_Call : Ijk_Ret; */
10313 putGST( PPC_GST_CIA
, mkexpr(lr_old
) );
10317 vex_printf("dis_int_branch(ppc)(opc2)\n");
10323 vex_printf("dis_int_branch(ppc)(opc1)\n");
10331 * PC relative instruction
10333 static Bool
dis_pc_relative ( UInt prefix
, UInt theInstr
)
10336 UChar opc1
= ifieldOPC(theInstr
);
10337 unsigned long long D
;
10338 UInt d0
= IFIELD(theInstr
, 6, 10);
10339 UInt d1
= IFIELD(theInstr
, 16, 5);
10340 UInt d2
= IFIELD(theInstr
, 0, 1);
10341 UChar rT_addr
= ifieldRegDS(theInstr
);
10342 UInt opc2
= ifieldOPClo5(theInstr
);
10343 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
10345 /* There is no prefixed version of these instructions. */
10348 if ( opc1
!= 0x13) {
10349 vex_printf("dis_pc_relative(ppc)(opc1)\n");
10354 case 0x002: // addpcis (Add PC immediate Shifted DX-form)
10356 IRExpr
* nia
= mkSzImm(ty
, nextInsnAddr());
10359 D
= (d0
<< 6) | (d1
<< 1) | d2
;
10360 DIP("addpcis %u,%llu\n", rT_addr
, D
);
10362 if ( (D
& 0x8000) == 0x8000 )
10363 D
= 0xFFFFFFFFFFFF0000UL
| D
; // sign extend
10365 if ( ty
== Ity_I32
) {
10366 result
= binop( Iop_Add32
, nia
, mkU32( D
<< 16 ) );
10368 vassert( ty
== Ity_I64
);
10369 result
= binop( Iop_Add64
, nia
, mkU64( D
<< 16 ) );
10372 putIReg( rT_addr
, result
);
10377 vex_printf("dis_pc_relative(ppc)(opc2)\n");
10385 Condition Register Logical Instructions
10387 static Bool
dis_cond_logic ( UInt prefix
, UInt theInstr
)
10390 UChar opc1
= ifieldOPC(theInstr
);
10391 UChar crbD_addr
= ifieldRegDS(theInstr
);
10392 UChar crfD_addr
= toUChar( IFIELD(theInstr
, 23, 3) );
10393 UChar crbA_addr
= ifieldRegA(theInstr
);
10394 UChar crfS_addr
= toUChar( IFIELD(theInstr
, 18, 3) );
10395 UChar crbB_addr
= ifieldRegB(theInstr
);
10396 UInt opc2
= ifieldOPClo10(theInstr
);
10397 UChar b0
= ifieldBIT0(theInstr
);
10399 IRTemp crbD
= newTemp(Ity_I32
);
10400 IRTemp crbA
= newTemp(Ity_I32
);
10401 IRTemp crbB
= newTemp(Ity_I32
);
10403 /* There is no prefixed version of these instructions. */
10406 if (opc1
!= 19 || b0
!= 0) {
10407 vex_printf("dis_cond_logic(ppc)(opc1)\n");
10411 if (opc2
== 0) { // mcrf (Move Cond Reg Field, PPC32 p464)
10412 if (((crbD_addr
& 0x3) != 0) ||
10413 ((crbA_addr
& 0x3) != 0) || (crbB_addr
!= 0)) {
10414 vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n");
10417 DIP("mcrf cr%u,cr%u\n", crfD_addr
, crfS_addr
);
10418 putCR0( crfD_addr
, getCR0( crfS_addr
) );
10419 putCR321( crfD_addr
, getCR321(crfS_addr
) );
10421 assign( crbA
, getCRbit(crbA_addr
) );
10422 if (crbA_addr
== crbB_addr
)
10425 assign( crbB
, getCRbit(crbB_addr
) );
10428 case 0x101: // crand (Cond Reg AND, PPC32 p372)
10429 DIP("crand crb%d,crb%d,crb%d\n", crbD_addr
, crbA_addr
, crbB_addr
);
10430 assign( crbD
, binop(Iop_And32
, mkexpr(crbA
), mkexpr(crbB
)) );
10432 case 0x081: // crandc (Cond Reg AND w. Complement, PPC32 p373)
10433 DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr
, crbA_addr
, crbB_addr
);
10434 assign( crbD
, binop(Iop_And32
,
10436 unop(Iop_Not32
, mkexpr(crbB
))) );
10438 case 0x121: // creqv (Cond Reg Equivalent, PPC32 p374)
10439 DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr
, crbA_addr
, crbB_addr
);
10440 assign( crbD
, unop(Iop_Not32
,
10441 binop(Iop_Xor32
, mkexpr(crbA
), mkexpr(crbB
))) );
10443 case 0x0E1: // crnand (Cond Reg NAND, PPC32 p375)
10444 DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr
, crbA_addr
, crbB_addr
);
10445 assign( crbD
, unop(Iop_Not32
,
10446 binop(Iop_And32
, mkexpr(crbA
), mkexpr(crbB
))) );
10448 case 0x021: // crnor (Cond Reg NOR, PPC32 p376)
10449 DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr
, crbA_addr
, crbB_addr
);
10450 assign( crbD
, unop(Iop_Not32
,
10451 binop(Iop_Or32
, mkexpr(crbA
), mkexpr(crbB
))) );
10453 case 0x1C1: // cror (Cond Reg OR, PPC32 p377)
10454 DIP("cror crb%d,crb%d,crb%d\n", crbD_addr
, crbA_addr
, crbB_addr
);
10455 assign( crbD
, binop(Iop_Or32
, mkexpr(crbA
), mkexpr(crbB
)) );
10457 case 0x1A1: // crorc (Cond Reg OR w. Complement, PPC32 p378)
10458 DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr
, crbA_addr
, crbB_addr
);
10459 assign( crbD
, binop(Iop_Or32
,
10461 unop(Iop_Not32
, mkexpr(crbB
))) );
10463 case 0x0C1: // crxor (Cond Reg XOR, PPC32 p379)
10464 DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr
, crbA_addr
, crbB_addr
);
10465 assign( crbD
, binop(Iop_Xor32
, mkexpr(crbA
), mkexpr(crbB
)) );
10468 vex_printf("dis_cond_logic(ppc)(opc2)\n");
10472 putCRbit( crbD_addr
, mkexpr(crbD
) );
10477 static Bool
dis_set_bool_condition ( UInt prefixInstr
, UInt theInstr
)
10479 UInt opc2
= ifieldOPClo10(theInstr
);
10480 UChar BI
= toUChar( IFIELD( theInstr
, 16, 5 ) );
10481 UInt rT_addr
= ifieldRegDS( theInstr
);
10482 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
10485 /* There is no prefixed version of these instructions. */
10486 vassert( !prefix_instruction( prefixInstr
) );
10489 case 0x180: // setbc
10490 /* If bit BI of the CR contains a 1, register RT is set to 1.
10491 Otherwise, register RT is set to 0. */
10492 DIP(" setbc %u,%u\n", rT_addr
, BI
);
10493 Iop_1XtoX
= mode64
? Iop_1Uto64
: Iop_1Uto32
;
10494 putIReg( rT_addr
, unop( Iop_1XtoX
,
10495 binop( Iop_CmpEQ32
,
10500 case 0x1A0: // setbcr
10501 /* If bit BI of the CR contains a 1, register RT is set to 0.
10502 Otherwise, register RT is set to 1. */
10503 DIP(" setbcr %u,%u\n", rT_addr
, BI
);
10504 Iop_1XtoX
= mode64
? Iop_1Uto64
: Iop_1Uto32
;
10505 putIReg( rT_addr
, unop( Iop_1XtoX
,
10506 binop( Iop_CmpNE32
,
10511 case 0x1C0: // setnbc
10512 /* If bit BI of the CR contains a 1, register RT is set to -1.
10513 Otherwise, register RT is set to 0. */
10514 DIP(" setnbc %u,%u\n", rT_addr
, BI
);
10515 Iop_1XtoX
= mode64
? Iop_1Sto64
: Iop_1Sto32
;
10516 putIReg( rT_addr
, binop( mkSzOp(ty
, Iop_And8
),
10519 binop( Iop_CmpEQ32
,
10521 mkU32( 1 ) ) ) ) );
10524 case 0x1E0: // setnbcr
10525 /* If bit BI of the CR contains a 1, register RT is set to -1.
10526 Otherwise, register RT is set to 0. */
10527 DIP(" setnbcr %u,%u\n", rT_addr
, BI
);
10528 Iop_1XtoX
= mode64
? Iop_1Sto64
: Iop_1Sto32
;
10529 putIReg( rT_addr
, binop( mkSzOp(ty
, Iop_And8
),
10532 binop( Iop_CmpNE32
,
10534 mkU32( 1 ) ) ) ) );
10538 vex_printf("dis_set_bool_condition(ppc)(opc2)\n");
10549 /* Do the code generation for a trap. Returned Bool is true iff
10550 this is an unconditional trap. If the two arg IRExpr*s are
10551 Ity_I32s then the comparison is 32-bit. If they are Ity_I64s
10552 then they are 64-bit, and we must be disassembling 64-bit
10554 static Bool
do_trap ( UChar TO
,
10555 IRExpr
* argL0
, IRExpr
* argR0
, Addr64 cia
)
10558 IRExpr
*argLe
, *argRe
, *cond
, *tmp
;
10560 Bool is32bit
= typeOfIRExpr(irsb
->tyenv
, argL0
) == Ity_I32
;
10562 IROp opAND
= is32bit
? Iop_And32
: Iop_And64
;
10563 IROp opOR
= is32bit
? Iop_Or32
: Iop_Or64
;
10564 IROp opCMPORDS
= is32bit
? Iop_CmpORD32S
: Iop_CmpORD64S
;
10565 IROp opCMPORDU
= is32bit
? Iop_CmpORD32U
: Iop_CmpORD64U
;
10566 IROp opCMPNE
= is32bit
? Iop_CmpNE32
: Iop_CmpNE64
;
10567 IROp opCMPEQ
= is32bit
? Iop_CmpEQ32
: Iop_CmpEQ64
;
10568 IRExpr
* const0
= is32bit
? mkU32(0) : mkU64(0);
10569 IRExpr
* const2
= is32bit
? mkU32(2) : mkU64(2);
10570 IRExpr
* const4
= is32bit
? mkU32(4) : mkU64(4);
10571 IRExpr
* const8
= is32bit
? mkU32(8) : mkU64(8);
10573 const UChar b11100
= 0x1C;
10574 const UChar b00111
= 0x07;
10577 vassert( typeOfIRExpr(irsb
->tyenv
, argL0
) == Ity_I32
);
10578 vassert( typeOfIRExpr(irsb
->tyenv
, argR0
) == Ity_I32
);
10580 vassert( typeOfIRExpr(irsb
->tyenv
, argL0
) == Ity_I64
);
10581 vassert( typeOfIRExpr(irsb
->tyenv
, argR0
) == Ity_I64
);
10585 if ((TO
& b11100
) == b11100
|| (TO
& b00111
) == b00111
) {
10586 /* Unconditional trap. Just do the exit without
10587 testing the arguments. */
10589 binop(opCMPEQ
, const0
, const0
),
10591 mode64
? IRConst_U64(cia
) : IRConst_U32((UInt
)cia
),
10594 return True
; /* unconditional trap */
10598 argL
= newTemp(Ity_I32
);
10599 argR
= newTemp(Ity_I32
);
10601 argL
= newTemp(Ity_I64
);
10602 argR
= newTemp(Ity_I64
);
10605 assign( argL
, argL0
);
10606 assign( argR
, argR0
);
10608 argLe
= mkexpr(argL
);
10609 argRe
= mkexpr(argR
);
10612 if (TO
& 16) { // L <s R
10613 tmp
= binop(opAND
, binop(opCMPORDS
, argLe
, argRe
), const8
);
10614 cond
= binop(opOR
, tmp
, cond
);
10616 if (TO
& 8) { // L >s R
10617 tmp
= binop(opAND
, binop(opCMPORDS
, argLe
, argRe
), const4
);
10618 cond
= binop(opOR
, tmp
, cond
);
10620 if (TO
& 4) { // L == R
10621 tmp
= binop(opAND
, binop(opCMPORDS
, argLe
, argRe
), const2
);
10622 cond
= binop(opOR
, tmp
, cond
);
10624 if (TO
& 2) { // L <u R
10625 tmp
= binop(opAND
, binop(opCMPORDU
, argLe
, argRe
), const8
);
10626 cond
= binop(opOR
, tmp
, cond
);
10628 if (TO
& 1) { // L >u R
10629 tmp
= binop(opAND
, binop(opCMPORDU
, argLe
, argRe
), const4
);
10630 cond
= binop(opOR
, tmp
, cond
);
10633 binop(opCMPNE
, cond
, const0
),
10635 mode64
? IRConst_U64(cia
) : IRConst_U32((UInt
)cia
),
10638 return False
; /* not an unconditional trap */
10641 static Bool
dis_trapi ( UInt prefix
, UInt theInstr
,
10642 /*OUT*/DisResult
* dres
)
10645 UChar opc1
= ifieldOPC(theInstr
);
10646 UChar TO
= ifieldRegDS(theInstr
);
10647 UChar rA_addr
= ifieldRegA(theInstr
);
10648 UInt uimm16
= ifieldUIMM16(theInstr
);
10649 ULong simm16
= extend_s_16to64(uimm16
);
10650 Addr64 cia
= guest_CIA_curr_instr
;
10651 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
10652 Bool uncond
= False
;
10654 /* There is no prefixed version of these instructions. */
10658 case 0x03: // twi (Trap Word Immediate, PPC32 p548)
10659 uncond
= do_trap( TO
,
10660 mode64
? unop(Iop_64to32
, getIReg(rA_addr
))
10661 : getIReg(rA_addr
),
10662 mkU32( (UInt
)simm16
),
10665 DIP("tweqi r%u,%d\n", rA_addr
, (Int
)simm16
);
10667 DIP("tw%di r%u,%d\n", TO
, rA_addr
, (Int
)simm16
);
10673 uncond
= do_trap( TO
, getIReg(rA_addr
), mkU64( (ULong
)simm16
), cia
);
10675 DIP("tdeqi r%u,%d\n", rA_addr
, (Int
)simm16
);
10677 DIP("td%di r%u,%d\n", TO
, rA_addr
, (Int
)simm16
);
10685 /* If the trap shows signs of being unconditional, don't
10686 continue decoding past it. */
10687 putGST( PPC_GST_CIA
, mkSzImm( ty
, nextInsnAddr() ));
10688 dres
->jk_StopHere
= Ijk_Boring
;
10689 dres
->whatNext
= Dis_StopHere
;
10695 static Bool
dis_trap ( UInt prefix
, UInt theInstr
,
10696 /*OUT*/DisResult
* dres
)
10699 UInt opc2
= ifieldOPClo10(theInstr
);
10700 UChar TO
= ifieldRegDS(theInstr
);
10701 UChar rA_addr
= ifieldRegA(theInstr
);
10702 UChar rB_addr
= ifieldRegB(theInstr
);
10703 Addr64 cia
= guest_CIA_curr_instr
;
10704 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
10705 Bool uncond
= False
;
10707 /* There is no prefixed version of these instructions. */
10710 if (ifieldBIT0(theInstr
) != 0)
10714 case 0x004: // tw (Trap Word, PPC64 p540)
10715 uncond
= do_trap( TO
,
10716 mode64
? unop(Iop_64to32
, getIReg(rA_addr
))
10717 : getIReg(rA_addr
),
10718 mode64
? unop(Iop_64to32
, getIReg(rB_addr
))
10719 : getIReg(rB_addr
),
10722 DIP("tweq r%u,r%u\n", rA_addr
, rB_addr
);
10724 DIP("tw%d r%u,r%u\n", TO
, rA_addr
, rB_addr
);
10727 case 0x044: // td (Trap Doubleword, PPC64 p534)
10730 uncond
= do_trap( TO
, getIReg(rA_addr
), getIReg(rB_addr
), cia
);
10732 DIP("tdeq r%u,r%u\n", rA_addr
, rB_addr
);
10734 DIP("td%d r%u,r%u\n", TO
, rA_addr
, rB_addr
);
10742 /* If the trap shows signs of being unconditional, don't
10743 continue decoding past it. */
10744 putGST( PPC_GST_CIA
, mkSzImm( ty
, nextInsnAddr() ));
10745 dres
->jk_StopHere
= Ijk_Boring
;
10746 dres
->whatNext
= Dis_StopHere
;
10754 System Linkage Instructions
10757 static Bool
dis_syslink ( UInt prefix
, UInt theInstr
,
10758 const VexAbiInfo
* abiinfo
, DisResult
* dres
,
10759 Bool allow_scv
, Bool sigill_diag
)
10761 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
10763 /* There is no prefixed version of these instructions. */
10766 if ((theInstr
!= 0x44000002) // sc
10767 && (theInstr
!= 0x44000001)) { // scv
10768 vex_printf("dis_syslink(ppc)(theInstr)\n");
10772 /* The PPC syscall uses guest_GPR9 to pass a flag to indicate which
10773 system call instruction is to be used. Arg7 = SC_FLAG for the sc
10774 instruction; Arg7 = SCV_FLAG for the scv instruction. */
10775 if (theInstr
== 0x44000002) {
10776 // sc (System Call, PPC32 p504)
10778 put_syscall_flag( mkU32(SC_FLAG
) );
10779 } else if (theInstr
== 0x44000001) {
10780 if (allow_scv
) { // scv
10782 put_syscall_flag( mkU32(SCV_FLAG
) );
10785 vex_printf("The scv instruction is not supported in this environment per the HWCAPS2 capability flags.\n");
10789 /* Unknown instruction */
10793 /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on Darwin
10794 Valgrind can back the guest up to this instruction if it needs
10795 to restart the syscall. */
10796 putGST( PPC_GST_IP_AT_SYSCALL
, getGST( PPC_GST_CIA
) );
10798 /* It's important that all ArchRegs carry their up-to-date value
10799 at this point. So we declare an end-of-block here, which
10800 forces any TempRegs caching ArchRegs to be flushed. */
10801 putGST( PPC_GST_CIA
, mkSzImm( ty
, nextInsnAddr() ));
10803 dres
->whatNext
= Dis_StopHere
;
10804 dres
->jk_StopHere
= Ijk_Sys_syscall
;
10810 Memory Synchronization Instructions
10812 Note on Reservations:
10813 We rely on the assumption that V will in fact only allow one thread at
10814 once to run. In effect, a thread can make a reservation, but we don't
10815 check any stores it does. Instead, the reservation is cancelled when
10816 the scheduler switches to another thread (run_thread_for_a_while()).
10818 static Bool
dis_memsync ( UInt prefix
, UInt theInstr
,
10819 UInt allow_isa_3_0
, UInt allow_isa_3_1
)
10821 /* X-Form, XL-Form */
10822 UChar opc1
= ifieldOPC(theInstr
);
10823 UInt b11to25
= IFIELD(theInstr
, 11, 15);
10824 /* The L-field is 2 bits in ISA 3.0 and earlier and 3 bits in ISA 3.1 */
10825 UChar flag_L
= IFIELD(theInstr
, 21, (allow_isa_3_1
? 3 : 2));
10826 UInt b11to20
= IFIELD(theInstr
, 11, 10);
10827 UInt M0
= IFIELD(theInstr
, 11, 5);
10828 UChar rD_addr
= ifieldRegDS(theInstr
);
10829 UChar rS_addr
= rD_addr
;
10830 UChar rA_addr
= ifieldRegA(theInstr
);
10831 UChar rB_addr
= ifieldRegB(theInstr
);
10832 UInt opc2
= ifieldOPClo10(theInstr
);
10833 UChar b0
= ifieldBIT0(theInstr
);
10835 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
10836 IRTemp EA
= newTemp(ty
);
10838 /* There is no prefixed version of these instructions. */
10841 assign( EA
, ea_rAor0_idxd( rA_addr
, rB_addr
) );
10845 case 0x13: // isync (Instruction Synchronize, PPC32 p432)
10846 if (opc2
!= 0x096) {
10847 vex_printf("dis_memsync(ppc)(0x13,opc2)\n");
10850 if (b11to25
!= 0 || b0
!= 0) {
10851 vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n");
10855 stmt( IRStmt_MBE(Imbe_Fence
) );
10861 case 0x356: // eieio or mbar (Enforce In-Order Exec of I/O, PPC32 p394)
10863 if (b11to20
!= 0 || b0
!= 0) {
10864 vex_printf("dis_memsync(ppc)(eieio,b11to20|b0)\n");
10869 if (b11to20
!= 0 || b0
!= 0) {
10870 vex_printf("dis_memsync(ppc)(mbar,b11to20|b0)\n");
10873 DIP("mbar %u\n", M0
);
10875 /* Insert a memory fence, just to be on the safe side. */
10876 stmt( IRStmt_MBE(Imbe_Fence
) );
10879 case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458)
10881 /* According to the PowerPC ISA version 2.05, b0 (called EH
10882 in the documentation) is merely a hint bit to the
10883 hardware, I think as to whether or not contention is
10884 likely. So we can just ignore it. */
10885 DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr
, rA_addr
, rB_addr
, b0
);
10887 // trap if misaligned
10888 gen_SIGBUS_if_misaligned( EA
, 4 );
10890 // and actually do the load
10891 res
= newTemp(Ity_I32
);
10892 stmt( stmt_load(res
, mkexpr(EA
), NULL
/*this is a load*/) );
10894 putIReg( rD_addr
, mkWidenFrom32(ty
, mkexpr(res
), False
) );
10898 case 0x034: { // lbarx (Load Word and Reserve Indexed)
10900 /* According to the PowerPC ISA version 2.05, b0 (called EH
10901 in the documentation) is merely a hint bit to the
10902 hardware, I think as to whether or not contention is
10903 likely. So we can just ignore it. */
10904 DIP("lbarx r%u,r%u,r%u,EH=%u\n", rD_addr
, rA_addr
, rB_addr
, b0
);
10906 // and actually do the load
10907 res
= newTemp(Ity_I8
);
10908 stmt( stmt_load(res
, mkexpr(EA
), NULL
/*this is a load*/) );
10910 putIReg( rD_addr
, mkWidenFrom8(ty
, mkexpr(res
), False
) );
10914 case 0x074: { // lharx (Load Word and Reserve Indexed)
10916 /* According to the PowerPC ISA version 2.05, b0 (called EH
10917 in the documentation) is merely a hint bit to the
10918 hardware, I think as to whether or not contention is
10919 likely. So we can just ignore it. */
10920 DIP("lharx r%u,r%u,r%u,EH=%u\n", rD_addr
, rA_addr
, rB_addr
, b0
);
10922 // trap if misaligned
10923 gen_SIGBUS_if_misaligned( EA
, 2 );
10925 // and actually do the load
10926 res
= newTemp(Ity_I16
);
10927 stmt( stmt_load(res
, mkexpr(EA
), NULL
/*this is a load*/) );
10929 putIReg( rD_addr
, mkWidenFrom16(ty
, mkexpr(res
), False
) );
10934 // stwcx. (Store Word Conditional Indexed, PPC32 p532)
10935 // Note this has to handle stwcx. in both 32- and 64-bit modes,
10936 // so isn't quite as straightforward as it might otherwise be.
10937 IRTemp rS
= newTemp(Ity_I32
);
10940 vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
10943 DIP("stwcx. r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
10945 // trap if misaligned
10946 gen_SIGBUS_if_misaligned( EA
, 4 );
10948 // Get the data to be stored, and narrow to 32 bits if necessary
10949 assign( rS
, mkNarrowTo32(ty
, getIReg(rS_addr
)) );
10951 // Do the store, and get success/failure bit into resSC
10952 resSC
= newTemp(Ity_I1
);
10953 stmt( stmt_load( resSC
, mkexpr(EA
), mkexpr(rS
)) );
10955 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure
10956 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success
10957 putCR321(0, binop(Iop_Shl8
, unop(Iop_1Uto8
, mkexpr(resSC
)), mkU8(1)));
10958 putCR0(0, getXER_SO());
10961 If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
10962 whether rS is stored is dependent on that value. */
10963 /* So I guess we can just ignore this case? */
10968 // stbcx. (Store Byte Conditional Indexed)
10969 // Note this has to handle stbcx. in both 32- and 64-bit modes,
10970 // so isn't quite as straightforward as it might otherwise be.
10971 IRTemp rS
= newTemp(Ity_I8
);
10974 vex_printf("dis_memsync(ppc)(stbcx.,b0)\n");
10977 DIP("stbcx. r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
10979 // Get the data to be stored, and narrow to 32 bits if necessary
10980 assign( rS
, mkNarrowTo8(ty
, getIReg(rS_addr
)) );
10982 // Do the store, and get success/failure bit into resSC
10983 resSC
= newTemp(Ity_I1
);
10984 stmt( stmt_load( resSC
, mkexpr(EA
), mkexpr(rS
)) );
10986 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure
10987 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success
10988 putCR321(0, binop(Iop_Shl8
, unop(Iop_1Uto8
, mkexpr(resSC
)), mkU8(1)));
10989 putCR0(0, getXER_SO());
10992 If resaddr != lbarx_resaddr, CR0[EQ] is undefined, and
10993 whether rS is stored is dependent on that value. */
10994 /* So I guess we can just ignore this case? */
10999 // sthcx. (Store Word Conditional Indexed, PPC32 p532)
11000 // Note this has to handle sthcx. in both 32- and 64-bit modes,
11001 // so isn't quite as straightforward as it might otherwise be.
11002 IRTemp rS
= newTemp(Ity_I16
);
11005 vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
11008 DIP("sthcx. r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
11010 // trap if misaligned
11011 gen_SIGBUS_if_misaligned( EA
, 2 );
11013 // Get the data to be stored, and narrow to 16 bits if necessary
11014 assign( rS
, mkNarrowTo16(ty
, getIReg(rS_addr
)) );
11016 // Do the store, and get success/failure bit into resSC
11017 resSC
= newTemp(Ity_I1
);
11018 stmt( stmt_load( resSC
, mkexpr(EA
), mkexpr(rS
)) );
11020 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure
11021 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success
11022 putCR321(0, binop(Iop_Shl8
, unop(Iop_1Uto8
, mkexpr(resSC
)), mkU8(1)));
11023 putCR0(0, getXER_SO());
11026 If resaddr != lharx_resaddr, CR0[EQ] is undefined, and
11027 whether rS is stored is dependent on that value. */
11028 /* So I guess we can just ignore this case? */
11032 case 0x256: // sync (Synchronize, PPC32 p543),
11033 // also lwsync (L==1), ptesync (L==2)
11034 /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html
11036 The PowerPC architecture used in IBM chips has expanded
11037 the sync instruction into two variants: lightweight sync
11038 and heavyweight sync. The original sync instruction is
11039 the new heavyweight sync and lightweight sync is a strict
11040 subset of the heavyweight sync functionality. This allows
11041 the programmer to specify a less expensive operation on
11042 high-end systems when the full sync functionality is not
11045 The basic "sync" mnemonic now utilizes an operand. "sync"
11046 without an operand now becomes a extended mnemonic for
11047 heavyweight sync. Processors without the lwsync
11048 instruction will not decode the L field and will perform a
11049 heavyweight sync. Everything is backward compatible.
11053 ptesync = sync 2 ISA 3.0 and newer
11054 persistent heavyweight sync (phsync) = sync 4 ISA 3.1 and newer
11055 persistent lightweight sync (plsync) = sync 5 ISA 3.1 and newer
11057 if (b11to20
!= 0 || b0
!= 0) {
11058 vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n");
11062 if (!((flag_L
== 0/*sync*/ || flag_L
== 1/*lwsync*/)
11063 || (flag_L
== 2/*ptesync*/ && allow_isa_3_0
== True
)
11064 || ((flag_L
== 4/*phsync*/ || flag_L
== 5/*plsync*/)
11065 && allow_isa_3_1
== True
)))
11067 vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n");
11071 DIP("%ssync\n", flag_L
== 1 ? "lw" : "");
11072 /* Insert a memory fence. It's sometimes important that these
11073 are carried through to the generated code. */
11074 stmt( IRStmt_MBE(Imbe_Fence
) );
11077 /* 64bit Memsync */
11078 case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473)
11080 /* According to the PowerPC ISA version 2.05, b0 (called EH
11081 in the documentation) is merely a hint bit to the
11082 hardware, I think as to whether or not contention is
11083 likely. So we can just ignore it. */
11086 DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr
, rA_addr
, rB_addr
, b0
);
11088 // trap if misaligned
11089 gen_SIGBUS_if_misaligned( EA
, 8 );
11091 // and actually do the load
11092 res
= newTemp(Ity_I64
);
11093 stmt( stmt_load( res
, mkexpr(EA
), NULL
/*this is a load*/) );
11095 putIReg( rD_addr
, mkexpr(res
) );
11099 case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581)
11100 // A marginally simplified version of the stwcx. case
11101 IRTemp rS
= newTemp(Ity_I64
);
11104 vex_printf("dis_memsync(ppc)(stdcx.,b0)\n");
11109 DIP("stdcx. r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
11111 // trap if misaligned
11112 gen_SIGBUS_if_misaligned( EA
, 8 );
11114 // Get the data to be stored
11115 assign( rS
, getIReg(rS_addr
) );
11117 // Do the store, and get success/failure bit into resSC
11118 resSC
= newTemp(Ity_I1
);
11119 stmt( stmt_load( resSC
, mkexpr(EA
), mkexpr(rS
)) );
11121 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure
11122 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success
11123 putCR321(0, binop(Iop_Shl8
, unop(Iop_1Uto8
, mkexpr(resSC
)), mkU8(1)));
11124 putCR0(0, getXER_SO());
11127 If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
11128 whether rS is stored is dependent on that value. */
11129 /* So I guess we can just ignore this case? */
11133 /* 128bit Memsync */
11134 case 0x114: { // lqarx (Load QuadWord and Reserve Indexed)
11135 IRTemp res_hi
= newTemp(ty
);
11136 IRTemp res_lo
= newTemp(ty
);
11138 /* According to the PowerPC ISA version 2.07, b0 (called EH
11139 in the documentation) is merely a hint bit to the
11140 hardware, I think as to whether or not contention is
11141 likely. So we can just ignore it. */
11142 DIP("lqarx r%u,r%u,r%u,EH=%u\n", rD_addr
, rA_addr
, rB_addr
, b0
);
11144 // trap if misaligned
11145 gen_SIGBUS_if_misaligned( EA
, 16 );
11147 // and actually do the load
11149 if (host_endness
== VexEndnessBE
) {
11150 stmt( stmt_load( res_hi
,
11151 mkexpr(EA
), NULL
/*this is a load*/) );
11152 stmt( stmt_load( res_lo
,
11153 binop(Iop_Add64
, mkexpr(EA
), mkU64(8) ),
11154 NULL
/*this is a load*/) );
11156 stmt( stmt_load( res_lo
,
11157 mkexpr(EA
), NULL
/*this is a load*/) );
11158 stmt( stmt_load( res_hi
,
11159 binop(Iop_Add64
, mkexpr(EA
), mkU64(8) ),
11160 NULL
/*this is a load*/) );
11163 stmt( stmt_load( res_hi
,
11164 binop( Iop_Add32
, mkexpr(EA
), mkU32(4) ),
11165 NULL
/*this is a load*/) );
11166 stmt( stmt_load( res_lo
,
11167 binop( Iop_Add32
, mkexpr(EA
), mkU32(12) ),
11168 NULL
/*this is a load*/) );
11170 putIReg( rD_addr
, mkexpr(res_hi
) );
11171 putIReg( rD_addr
+1, mkexpr(res_lo
) );
11175 case 0x0B6: { // stqcx. (Store QuadWord Condition Indexd, PPC64)
11176 // A marginally simplified version of the stwcx. case
11177 IRTemp rS_hi
= newTemp(ty
);
11178 IRTemp rS_lo
= newTemp(ty
);
11181 vex_printf("dis_memsync(ppc)(stqcx.,b0)\n");
11185 DIP("stqcx. r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
11187 // trap if misaligned
11188 gen_SIGBUS_if_misaligned( EA
, 16 );
11189 // Get the data to be stored
11190 assign( rS_hi
, getIReg(rS_addr
) );
11191 assign( rS_lo
, getIReg(rS_addr
+1) );
11193 // Do the store, and get success/failure bit into resSC
11194 resSC
= newTemp(Ity_I1
);
11197 if (host_endness
== VexEndnessBE
) {
11198 stmt( stmt_load( resSC
, mkexpr(EA
), mkexpr(rS_hi
) ) );
11199 store( binop( Iop_Add64
, mkexpr(EA
), mkU64(8) ),
11202 stmt( stmt_load( resSC
, mkexpr(EA
), mkexpr(rS_lo
) ) );
11203 store( binop( Iop_Add64
, mkexpr(EA
), mkU64(8) ),
11207 stmt( stmt_load( resSC
, binop( Iop_Add32
,
11211 store( binop(Iop_Add32
, mkexpr(EA
), mkU32(12) ), mkexpr(rS_lo
) );
11214 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure
11215 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success
11216 putCR321(0, binop( Iop_Shl8
,
11217 unop(Iop_1Uto8
, mkexpr(resSC
) ),
11219 putCR0(0, getXER_SO());
11224 vex_printf("dis_memsync(ppc)(opc2)\n");
11230 vex_printf("dis_memsync(ppc)(opc1)\n");
11239 Integer Shift Instructions
11241 static Bool
dis_int_shift ( UInt prefix
, UInt theInstr
, UInt allow_isa_3_0
)
11243 /* X-Form, XS-Form */
11244 UChar opc1
= ifieldOPC(theInstr
);
11245 UChar rS_addr
= ifieldRegDS(theInstr
);
11246 UChar rA_addr
= ifieldRegA(theInstr
);
11247 UChar rB_addr
= ifieldRegB(theInstr
);
11248 UChar sh_imm
= rB_addr
;
11249 UInt opc2
= ifieldOPClo10(theInstr
);
11250 UChar b1
= ifieldBIT1(theInstr
);
11251 UChar flag_rC
= ifieldBIT0(theInstr
);
11253 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
11254 IRTemp rA
= newTemp(ty
);
11255 IRTemp rS
= newTemp(ty
);
11256 IRTemp rB
= newTemp(ty
);
11257 IRTemp outofrange
= newTemp(Ity_I1
);
11258 IRTemp rS_lo32
= newTemp(Ity_I32
);
11259 IRTemp rB_lo32
= newTemp(Ity_I32
);
11262 /* There is no prefixed version of these instructions. */
11265 assign( rS
, getIReg(rS_addr
) );
11266 assign( rB
, getIReg(rB_addr
) );
11267 assign( rS_lo32
, mkNarrowTo32(ty
, mkexpr(rS
)) );
11268 assign( rB_lo32
, mkNarrowTo32(ty
, mkexpr(rB
)) );
11270 if (opc1
== 0x1F) {
11272 case 0x018: { // slw (Shift Left Word, PPC32 p505)
11273 DIP("slw%s r%u,r%u,r%u\n", flag_rC
? ".":"",
11274 rA_addr
, rS_addr
, rB_addr
);
11275 /* rA = rS << rB */
11276 /* ppc32 semantics are:
11277 slw(x,y) = (x << (y & 31)) -- primary result
11278 & ~((y << 26) >>s 31) -- make result 0
11287 mkexpr(rB_lo32
), mkU32(31)))),
11290 binop(Iop_Shl32
, mkexpr(rB_lo32
), mkU8(26)),
11292 assign( rA
, mkWidenFrom32(ty
, e_tmp
, /* Signed */False
) );
11296 case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506)
11297 IRTemp sh_amt
= newTemp(Ity_I32
);
11298 DIP("sraw%s r%u,r%u,r%u\n", flag_rC
? ".":"",
11299 rA_addr
, rS_addr
, rB_addr
);
11300 /* JRS: my reading of the (poorly worded) PPC32 doc p506 is:
11302 rA = Sar32( rS, amt > 31 ? 31 : amt )
11303 XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi)
11305 assign( sh_amt
, binop(Iop_And32
, mkU32(0x3F),
11306 mkexpr(rB_lo32
)) );
11307 assign( outofrange
,
11308 binop(Iop_CmpLT32U
, mkU32(31), mkexpr(sh_amt
)) );
11309 e_tmp
= binop( Iop_Sar32
,
11312 IRExpr_ITE( mkexpr(outofrange
),
11314 mkexpr(sh_amt
)) ) );
11315 assign( rA
, mkWidenFrom32(ty
, e_tmp
, /* Signed */True
) );
11318 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_SRAW
,
11320 mkWidenFrom32(ty
, mkexpr(rS_lo32
), True
),
11321 mkWidenFrom32(ty
, mkexpr(sh_amt
), True
),
11322 mkWidenFrom32(ty
, getXER_CA_32(), True
) );
11325 /* copy CA to CA32 */
11326 putXER_CA32( unop(Iop_32to8
, getXER_CA_32()));
11330 case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507)
11331 DIP("srawi%s r%u,r%u,%d\n", flag_rC
? ".":"",
11332 rA_addr
, rS_addr
, sh_imm
);
11333 vassert(sh_imm
< 32);
11335 assign( rA
, binop(Iop_Sar64
,
11336 binop(Iop_Shl64
, getIReg(rS_addr
),
11338 mkU8(32 + sh_imm
)) );
11340 assign( rA
, binop(Iop_Sar32
, mkexpr(rS_lo32
),
11345 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_SRAWI
,
11347 mkWidenFrom32(ty
, mkexpr(rS_lo32
), /* Syned */True
),
11348 mkSzImm(ty
, sh_imm
),
11349 mkWidenFrom32(ty
, getXER_CA_32(), /* Syned */False
) );
11352 /* copy CA to CA32 */
11353 putXER_CA32( unop(Iop_32to8
, getXER_CA_32()));
11356 case 0x218: // srw (Shift Right Word, PPC32 p508)
11357 DIP("srw%s r%u,r%u,r%u\n", flag_rC
? ".":"",
11358 rA_addr
, rS_addr
, rB_addr
);
11359 /* rA = rS >>u rB */
11360 /* ppc32 semantics are:
11361 srw(x,y) = (x >>u (y & 31)) -- primary result
11362 & ~((y << 26) >>s 31) -- make result 0
11371 binop(Iop_And32
, mkexpr(rB_lo32
),
11375 binop(Iop_Shl32
, mkexpr(rB_lo32
),
11378 assign( rA
, mkWidenFrom32(ty
, e_tmp
, /* Signed */False
) );
11383 case 0x01B: // sld (Shift Left DWord, PPC64 p568)
11384 DIP("sld%s r%u,r%u,r%u\n",
11385 flag_rC
? ".":"", rA_addr
, rS_addr
, rB_addr
);
11386 /* rA = rS << rB */
11387 /* ppc64 semantics are:
11388 slw(x,y) = (x << (y & 63)) -- primary result
11389 & ~((y << 57) >>s 63) -- make result 0
11398 binop(Iop_And64
, mkexpr(rB
), mkU64(63)))),
11401 binop(Iop_Shl64
, mkexpr(rB
), mkU8(57)),
11405 case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570)
11406 IRTemp sh_amt
= newTemp(Ity_I64
);
11407 DIP("srad%s r%u,r%u,r%u\n",
11408 flag_rC
? ".":"", rA_addr
, rS_addr
, rB_addr
);
11410 rA = Sar64( rS, amt > 63 ? 63 : amt )
11411 XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi)
11413 assign( sh_amt
, binop(Iop_And64
, mkU64(0x7F), mkexpr(rB
)) );
11414 assign( outofrange
,
11415 binop(Iop_CmpLT64U
, mkU64(63), mkexpr(sh_amt
)) );
11420 IRExpr_ITE( mkexpr(outofrange
),
11425 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_SRAD
,
11426 mkexpr(rA
), mkexpr(rS
), mkexpr(sh_amt
),
11427 mkWidenFrom32(ty
, getXER_CA_32(), /* Syned */False
) );
11430 /* copy CA to CA32 */
11431 putXER_CA32( unop(Iop_32to8
, getXER_CA_32()));
11435 case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571)
11437 vassert(sh_imm
< 64);
11438 DIP("sradi%s r%u,r%u,%u\n",
11439 flag_rC
? ".":"", rA_addr
, rS_addr
, sh_imm
);
11440 assign( rA
, binop(Iop_Sar64
, getIReg(rS_addr
), mkU8(sh_imm
)) );
11443 set_XER_CA_CA32( ty
, PPCG_FLAG_OP_SRADI
,
11447 mkWidenFrom32(ty
, getXER_CA_32(), /* Syned */False
) );
11450 /* copy CA to CA32 */
11451 putXER_CA32( unop(Iop_32to8
, getXER_CA_32()));
11454 case 0x21B: // srd (Shift Right DWord, PPC64 p574)
11455 DIP("srd%s r%u,r%u,r%u\n",
11456 flag_rC
? ".":"", rA_addr
, rS_addr
, rB_addr
);
11457 /* rA = rS >>u rB */
11458 /* ppc semantics are:
11459 srw(x,y) = (x >>u (y & 63)) -- primary result
11460 & ~((y << 57) >>s 63) -- make result 0
11469 binop(Iop_And64
, mkexpr(rB
), mkU64(63)))),
11472 binop(Iop_Shl64
, mkexpr(rB
), mkU8(57)),
11477 vex_printf("dis_int_shift(ppc)(opc2)\n");
11481 vex_printf("dis_int_shift(ppc)(opc1)\n");
11485 putIReg( rA_addr
, mkexpr(rA
) );
11488 set_CR0( mkexpr(rA
) );
11496 Integer Load/Store Reverse Instructions
11498 /* Generates code to swap the byte order in an Ity_I32. */
11499 static IRExpr
* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t
)
11501 vassert(typeOfIRTemp(irsb
->tyenv
, t
) == Ity_I32
);
11502 return unop(Iop_Reverse8sIn32_x1
, mkexpr(t
));
11505 /* Generates code to swap the byte order in the lower half of an Ity_I32,
11506 and zeroes the upper half. */
11507 static IRExpr
* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t
)
11509 vassert(typeOfIRTemp(irsb
->tyenv
, t
) == Ity_I32
);
11512 binop(Iop_And32
, binop(Iop_Shl32
, mkexpr(t
), mkU8(8)),
11513 mkU32(0x0000FF00)),
11514 binop(Iop_And32
, binop(Iop_Shr32
, mkexpr(t
), mkU8(8)),
11519 static Bool
dis_int_ldst_rev ( UInt prefix
, UInt theInstr
)
11522 UChar opc1
= ifieldOPC(theInstr
);
11523 UChar rD_addr
= ifieldRegDS(theInstr
);
11524 UChar rS_addr
= rD_addr
;
11525 UChar rA_addr
= ifieldRegA(theInstr
);
11526 UChar rB_addr
= ifieldRegB(theInstr
);
11527 UInt opc2
= ifieldOPClo10(theInstr
);
11528 UChar b0
= ifieldBIT0(theInstr
);
11530 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
11531 IRTemp EA
= newTemp(ty
);
11532 IRTemp w1
= newTemp(Ity_I32
);
11533 IRTemp w2
= newTemp(Ity_I32
);
11535 /* There is no prefixed version of these instructions. */
11538 if (opc1
!= 0x1F || b0
!= 0) {
11539 vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n");
11543 assign( EA
, ea_rAor0_idxd( rA_addr
, rB_addr
) );
11547 case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449)
11548 DIP("lhbrx r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
11549 assign( w1
, unop(Iop_16Uto32
, load(Ity_I16
, mkexpr(EA
))) );
11550 assign( w2
, gen_byterev16(w1
) );
11551 putIReg( rD_addr
, mkWidenFrom32(ty
, mkexpr(w2
),
11552 /* Signed */False
) );
11555 case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459)
11556 DIP("lwbrx r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
11557 assign( w1
, load(Ity_I32
, mkexpr(EA
)) );
11558 assign( w2
, gen_byterev32(w1
) );
11559 putIReg( rD_addr
, mkWidenFrom32(ty
, mkexpr(w2
),
11560 /* Signed */False
) );
11563 case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed)
11565 /* Caller makes sure we are only called in mode64. */
11567 /* If we supported swapping LE/BE loads in the backend then we could
11568 just load the value with the bytes reversed by doing a BE load
11569 on an LE machine and a LE load on a BE machine.
11571 IRTemp dw1 = newTemp(Ity_I64);
11572 if (host_endness == VexEndnessBE)
11573 assign( dw1, IRExpr_Load(Iend_LE, Ity_I64, mkexpr(EA)));
11575 assign( dw1, IRExpr_Load(Iend_BE, Ity_I64, mkexpr(EA)));
11576 putIReg( rD_addr, mkexpr(dw1) );
11578 But since we currently don't we load the value as is and then
11579 switch it around with Iop_Reverse8sIn64_x1. */
11581 IRTemp dw1
= newTemp(Ity_I64
);
11582 IRTemp dw2
= newTemp(Ity_I64
);
11583 DIP("ldbrx r%u,r%u,r%u\n", rD_addr
, rA_addr
, rB_addr
);
11584 assign( dw1
, load(Ity_I64
, mkexpr(EA
)) );
11585 assign( dw2
, unop(Iop_Reverse8sIn64_x1
, mkexpr(dw1
)) );
11586 putIReg( rD_addr
, mkexpr(dw2
) );
11590 case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523)
11591 DIP("sthbrx r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
11592 assign( w1
, mkNarrowTo32(ty
, getIReg(rS_addr
)) );
11593 store( mkexpr(EA
), unop(Iop_32to16
, gen_byterev16(w1
)) );
11596 case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531)
11597 DIP("stwbrx r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
11598 assign( w1
, mkNarrowTo32(ty
, getIReg(rS_addr
)) );
11599 store( mkexpr(EA
), gen_byterev32(w1
) );
11602 case 0x294: // stdbrx (Store Doubleword Byte-Reverse Indexed)
11604 IRTemp lo
= newTemp(Ity_I32
);
11605 IRTemp hi
= newTemp(Ity_I32
);
11606 IRTemp rS
= newTemp(Ity_I64
);
11607 assign( rS
, getIReg( rS_addr
) );
11608 DIP("stdbrx r%u,r%u,r%u\n", rS_addr
, rA_addr
, rB_addr
);
11609 assign(lo
, unop(Iop_64HIto32
, mkexpr(rS
)));
11610 assign(hi
, unop(Iop_64to32
, mkexpr(rS
)));
11611 store( mkexpr( EA
),
11612 binop( Iop_32HLto64
, gen_byterev32( hi
),
11613 gen_byterev32( lo
) ) );
11618 vex_printf("dis_int_ldst_rev(ppc)(opc2)\n");
11627 Processor Control Instructions
11629 static Bool
dis_proc_ctl ( const VexAbiInfo
* vbi
, UInt prefix
, UInt theInstr
)
11631 UChar opc1
= ifieldOPC(theInstr
);
11634 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) );
11635 UChar b21to22
= toUChar( IFIELD( theInstr
, 21, 2 ) );
11636 UChar rD_addr
= ifieldRegDS(theInstr
);
11637 UInt b11to20
= IFIELD( theInstr
, 11, 10 );
11640 UChar rS_addr
= rD_addr
;
11641 UInt SPR
= b11to20
;
11642 UInt TBR
= b11to20
;
11643 UChar b20
= toUChar( IFIELD( theInstr
, 20, 1 ) );
11644 UInt CRM
= IFIELD( theInstr
, 12, 8 );
11645 UChar b11
= toUChar( IFIELD( theInstr
, 11, 1 ) );
11647 UInt opc2
= ifieldOPClo10(theInstr
);
11648 UChar b0
= ifieldBIT0(theInstr
);
11650 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
11651 IRTemp rS
= newTemp(ty
);
11653 /* There is no prefixed version of these instructions. */
11656 assign( rS
, getIReg(rS_addr
) );
11658 /* Reorder SPR field as per PPC32 p470 */
11659 SPR
= ((SPR
& 0x1F) << 5) | ((SPR
>> 5) & 0x1F);
11660 /* Reorder TBR field as per PPC32 p475 */
11661 TBR
= ((TBR
& 31) << 5) | ((TBR
>> 5) & 31);
11663 /* b0 = 0, inst is treated as floating point inst for reservation purposes
11664 * b0 = 1, inst is treated as vector inst for reservation purposes
11666 if (opc1
!= 0x1F) {
11667 vex_printf("dis_proc_ctl(ppc)(opc1|b%d)\n", b0
);
11673 case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466)
11674 if (b21to22
!= 0 || b11to20
!= 0) {
11675 vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n");
11678 DIP("mcrxr crf%d\n", crfD
);
11679 /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */
11680 putGST_field( PPC_GST_CR
,
11681 getGST_field( PPC_GST_XER
, 7 ),
11685 putXER_SO( mkU8(0) );
11686 putXER_OV( mkU8(0) );
11687 putXER_CA( mkU8(0) );
11691 case 0x240: { // mcrxrx (Move to Cond Register from XER)
11692 IRTemp OV
= newTemp(Ity_I32
);
11693 IRTemp CA
= newTemp(Ity_I32
);
11694 IRTemp OV32
= newTemp(Ity_I32
);
11695 IRTemp CA32
= newTemp(Ity_I32
);
11696 IRTemp tmp
= newTemp(Ity_I32
);
11698 if (b21to22
!= 0 || b11to20
!= 0) {
11699 vex_printf("dis_proc_ctl(ppc)(mcrxrx,b21to22|b11to20)\n");
11702 DIP("mcrxrx crf%d\n", crfD
);
11703 /* Move OV, OV32, CA, CA32 to condition register field BF */
11704 assign( OV
, binop( Iop_Shl32
, getXER_OV_32(), mkU8( 3 ) ));
11705 assign( CA
, binop( Iop_Shl32
, getXER_CA_32(), mkU8( 1 ) ));
11706 assign( OV32
, binop( Iop_Shl32
, getXER_OV32_32(), mkU8( 2 ) ));
11707 assign( CA32
, getXER_CA32_32() );
11709 /* Put [OV | OV32 | CA | CA32] into the condition code register */
11712 binop( Iop_Or32
, mkexpr ( OV
), mkexpr ( OV32
) ),
11713 binop( Iop_Or32
, mkexpr ( CA
), mkexpr ( CA32
) )
11716 putGST_field( PPC_GST_CR
, mkexpr( tmp
), crfD
);
11721 // b11to20==0: mfcr (Move from Cond Register, PPC32 p467)
11722 // b20==1 & b11==0: mfocrf (Move from One CR Field)
11723 // However it seems that the 'mfcr' behaviour is an acceptable
11724 // implementation of mfocr (from the 2.02 arch spec)
11725 if (b11to20
== 0) {
11726 DIP("mfcr r%u\n", rD_addr
);
11727 putIReg( rD_addr
, mkWidenFrom32(ty
, getGST( PPC_GST_CR
),
11728 /* Signed */False
) );
11731 if (b20
== 1 && b11
== 0) {
11732 DIP("mfocrf r%u,%u\n", rD_addr
, CRM
);
11733 putIReg( rD_addr
, mkWidenFrom32(ty
, getGST( PPC_GST_CR
),
11734 /* Signed */False
) );
11737 /* not decodable */
11741 case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470)
11743 switch (SPR
) { // Choose a register...
11745 DIP("mfxer r%u\n", rD_addr
);
11746 putIReg( rD_addr
, mkWidenFrom32(ty
, getGST( PPC_GST_XER
),
11747 /* Signed */False
) );
11750 DIP("mfspr r%u (DSCR)\n", rD_addr
);
11751 putIReg( rD_addr
, getGST( PPC_GST_DSCR
) );
11754 DIP("mflr r%u\n", rD_addr
);
11755 putIReg( rD_addr
, getGST( PPC_GST_LR
) );
11758 DIP("mfctr r%u\n", rD_addr
);
11759 putIReg( rD_addr
, getGST( PPC_GST_CTR
) );
11762 DIP("mfspr r%u (TFHAR)\n", rD_addr
);
11763 putIReg( rD_addr
, getGST( PPC_GST_TFHAR
) );
11766 DIP("mfspr r%u (TFIAR)\n", rD_addr
);
11767 putIReg( rD_addr
, getGST( PPC_GST_TFIAR
) );
11770 DIP("mfspr r%u (TEXASR)\n", rD_addr
);
11771 putIReg( rD_addr
, getGST( PPC_GST_TEXASR
) );
11774 DIP("mfspr r%u (TEXASRU)\n", rD_addr
);
11775 putIReg( rD_addr
, getGST( PPC_GST_TEXASRU
) );
11778 DIP("mfspr r%u (PSPB)\n", rD_addr
);
11779 putIReg( rD_addr
, getGST( PPC_GST_PSPB
) );
11782 DIP("mfspr r%u (PPR)\n", rD_addr
);
11783 putIReg( rD_addr
, getGST( PPC_GST_PPR
) );
11786 DIP("mfspr r%u (PPR)32\n", rD_addr
);
11787 putIReg( rD_addr
, getGST( PPC_GST_PPR32
) );
11790 DIP("mfvrsave r%u\n", rD_addr
);
11791 putIReg( rD_addr
, mkWidenFrom32(ty
, getGST( PPC_GST_VRSAVE
),
11792 /* Signed */False
) );
11796 DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr
);
11797 putIReg( rD_addr
, getGST( PPC_GST_SPRG3_RO
) );
11800 case 268 /* 0x10C TB - 64 bit time base register */:
11802 IRTemp val
= newTemp(Ity_I64
);
11803 IRExpr
** args
= mkIRExprVec_0();
11804 IRDirty
* d
= unsafeIRDirty_1_N(
11807 "ppcg_dirtyhelper_MFTB",
11808 fnptr_to_fnentry(vbi
,
11809 &ppcg_dirtyhelper_MFTB
),
11811 /* execute the dirty call, dumping the result in val. */
11812 stmt( IRStmt_Dirty(d
) );
11813 putIReg( rD_addr
, (mode64
) ? mkexpr(val
) :
11814 unop(Iop_64to32
, mkexpr(val
)) );
11818 case 269 /* 0x10D TBU - upper 32-bits of time base register */:
11820 DIP("mfspr r%u,%u", rD_addr
, SPR
);
11821 IRTemp val
= newTemp(Ity_I64
);
11822 IRExpr
** args
= mkIRExprVec_0();
11823 IRDirty
* d
= unsafeIRDirty_1_N(
11826 "ppcg_dirtyhelper_MFTB",
11827 fnptr_to_fnentry(vbi
,
11828 &ppcg_dirtyhelper_MFTB
),
11830 /* execute the dirty call, dumping the result in val. */
11831 stmt( IRStmt_Dirty(d
) );
11833 mkWidenFrom32(ty
, unop(Iop_64HIto32
, mkexpr(val
)),
11834 /* Signed */False
) );
11837 case 284 /* 0x1 TBL - lower 32-bits of time base register */:
11839 DIP("mfspr r%u,%u", rD_addr
, SPR
);
11840 IRTemp val
= newTemp(Ity_I64
);
11841 IRExpr
** args
= mkIRExprVec_0();
11842 IRDirty
* d
= unsafeIRDirty_1_N(
11845 "ppcg_dirtyhelper_MFTB",
11846 fnptr_to_fnentry(vbi
,
11847 &ppcg_dirtyhelper_MFTB
),
11849 /* execute the dirty call, dumping the result in val. */
11850 stmt( IRStmt_Dirty(d
) );
11852 mkWidenFrom32(ty
, unop(Iop_64to32
, mkexpr(val
)),
11853 /* Signed */False
) );
11857 /* Again, runs natively on PPC7400 (7447, really). Not
11858 bothering with a feature test. */
11859 case 287: /* 0x11F */ {
11860 IRTemp val
= newTemp(Ity_I32
);
11861 IRExpr
** args
= mkIRExprVec_0();
11862 IRDirty
* d
= unsafeIRDirty_1_N(
11865 "ppc32g_dirtyhelper_MFSPR_287",
11867 (vbi
, &ppc32g_dirtyhelper_MFSPR_287
),
11870 /* execute the dirty call, dumping the result in val. */
11871 stmt( IRStmt_Dirty(d
) );
11873 mkWidenFrom32(ty
, mkexpr(val
), False
/*unsigned*/) );
11874 DIP("mfspr r%u,%u", rD_addr
, SPR
);
11879 vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR
);
11884 case 0x173: { // mftb (Move from Time Base, PPC32 p475)
11885 IRTemp val
= newTemp(Ity_I64
);
11886 IRExpr
** args
= mkIRExprVec_0();
11887 IRDirty
* d
= unsafeIRDirty_1_N(
11890 "ppcg_dirtyhelper_MFTB",
11891 fnptr_to_fnentry(vbi
, &ppcg_dirtyhelper_MFTB
),
11893 /* execute the dirty call, dumping the result in val. */
11894 stmt( IRStmt_Dirty(d
) );
11898 DIP("mftbu r%u", rD_addr
);
11900 mkWidenFrom32(ty
, unop(Iop_64HIto32
, mkexpr(val
)),
11901 /* Signed */False
) );
11904 DIP("mftb r%u", rD_addr
);
11905 putIReg( rD_addr
, (mode64
) ? mkexpr(val
) :
11906 unop(Iop_64to32
, mkexpr(val
)) );
11909 DIP("mftbl r%u", rD_addr
);
11911 mkWidenFrom32(ty
, unop(Iop_64to32
, mkexpr(val
)),
11912 /* Signed */False
) );
11915 return False
; /* illegal instruction */
11921 // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477)
11922 // b20==1: mtocrf (Move to One Cond Reg Field)
11928 /* ppc64 v2.02 spec says mtocrf gives undefined outcome if >
11929 1 field is written. It seems more robust to decline to
11930 decode the insn if so. */
11932 case 0x01: case 0x02: case 0x04: case 0x08:
11933 case 0x10: case 0x20: case 0x40: case 0x80:
11939 DIP("%s 0x%x,r%u\n", b20
==1 ? "mtocrf" : "mtcrf",
11941 /* Write to each field specified by CRM */
11942 for (cr
= 0; cr
< 8; cr
++) {
11943 if ((CRM
& (1 << (7-cr
))) == 0)
11946 putGST_field( PPC_GST_CR
,
11948 mkNarrowTo32(ty
, mkexpr(rS
)),
11954 case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483)
11956 switch (SPR
) { // Choose a register...
11958 DIP("mtxer r%u\n", rS_addr
);
11959 putGST( PPC_GST_XER
, mkNarrowTo32(ty
, mkexpr(rS
)) );
11962 DIP("mtspr r%u (DSCR)\n", rS_addr
);
11963 putGST( PPC_GST_DSCR
, mkexpr(rS
) );
11966 DIP("mtlr r%u\n", rS_addr
);
11967 putGST( PPC_GST_LR
, mkexpr(rS
) );
11970 DIP("mtctr r%u\n", rS_addr
);
11971 putGST( PPC_GST_CTR
, mkexpr(rS
) );
11974 DIP("mtvrsave r%u\n", rS_addr
);
11975 putGST( PPC_GST_VRSAVE
, mkNarrowTo32(ty
, mkexpr(rS
)) );
11978 DIP("mtspr r%u (TFHAR)\n", rS_addr
);
11979 putGST( PPC_GST_TFHAR
, mkexpr(rS
) );
11982 DIP("mtspr r%u (TFIAR)\n", rS_addr
);
11983 putGST( PPC_GST_TFIAR
, mkexpr(rS
) );
11986 DIP("mtspr r%u (TEXASR)\n", rS_addr
);
11987 putGST( PPC_GST_TEXASR
, mkexpr(rS
) );
11990 DIP("mtspr r%u (PSPB)\n", rS_addr
);
11991 putGST( PPC_GST_PSPB
, mkexpr(rS
) );
11994 DIP("mtspr r%u (PPR)\n", rS_addr
);
11995 putGST( PPC_GST_PPR
, mkexpr(rS
) );
11998 DIP("mtspr r%u (PPR32)\n", rS_addr
);
11999 putGST( PPC_GST_PPR32
, mkexpr(rS
) );
12002 vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR
);
12007 case 0x33: // mfvsrd
12009 UChar XS
= ifieldRegXS( theInstr
);
12010 UChar rA_addr
= ifieldRegA(theInstr
);
12012 IRTemp vS
= newTemp( Ity_V128
);
12013 DIP("mfvsrd r%u,vsr%d\n", rA_addr
, XS
);
12016 * For SX=0, mfvsrd is treated as a Floating-Point
12017 * instruction in terms of resource availability.
12018 * For SX=1, mfvsrd is treated as a Vector instruction in
12019 * terms of resource availability.
12020 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
12022 assign( vS
, getVSReg( XS
) );
12023 high64
= unop( Iop_V128HIto64
, mkexpr( vS
) );
12024 putIReg( rA_addr
, (mode64
) ? high64
:
12025 unop( Iop_64to32
, high64
) );
12029 case 0x73: // mfvsrwz
12031 UChar XS
= ifieldRegXS( theInstr
);
12032 UChar rA_addr
= ifieldRegA(theInstr
);
12034 IRTemp vS
= newTemp( Ity_V128
);
12035 DIP("mfvsrwz r%u,vsr%d\n", rA_addr
, XS
);
12037 * For SX=0, mfvsrwz is treated as a Floating-Point
12038 * instruction in terms of resource availability.
12039 * For SX=1, mfvsrwz is treated as a Vector instruction in
12040 * terms of resource availability.
12041 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
12044 assign( vS
, getVSReg( XS
) );
12045 high64
= unop( Iop_V128HIto64
, mkexpr( vS
) );
12046 /* move value to the destination setting the upper 32-bits to zero */
12047 putIReg( rA_addr
, (mode64
) ?
12048 binop( Iop_And64
, high64
, mkU64( 0xFFFFFFFF ) ) :
12050 binop( Iop_And64
, high64
, mkU64( 0xFFFFFFFF ) ) ) );
12054 case 0xB3: // mtvsrd
12056 UChar XT
= ifieldRegXT( theInstr
);
12057 UChar rA_addr
= ifieldRegA(theInstr
);
12058 IRTemp rA
= newTemp(ty
);
12059 DIP("mtvsrd vsr%d,r%u\n", XT
, rA_addr
);
12061 * For SX=0, mfvsrd is treated as a Floating-Point
12062 * instruction in terms of resource availability.
12063 * For SX=1, mfvsrd is treated as a Vector instruction in
12064 * terms of resource availability.
12065 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
12067 assign( rA
, getIReg(rA_addr
) );
12070 putVSReg( XT
, binop( Iop_64HLtoV128
, mkexpr( rA
), mkU64( 0 ) ) );
12072 putVSReg( XT
, binop( Iop_64HLtoV128
,
12073 binop( Iop_32HLto64
,
12080 case 0xD3: // mtvsrwa
12082 UChar XT
= ifieldRegXT( theInstr
);
12083 UChar rA_addr
= ifieldRegA(theInstr
);
12084 IRTemp rA
= newTemp( Ity_I32
);
12085 DIP("mtvsrwa vsr%d,r%u\n", XT
, rA_addr
);
12087 * For SX=0, mtvsrwa is treated as a Floating-Point
12088 * instruction in terms of resource availability.
12089 * For SX=1, mtvsrwa is treated as a Vector instruction in
12090 * terms of resource availability.
12091 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
12094 assign( rA
, unop( Iop_64to32
, getIReg( rA_addr
) ) );
12096 assign( rA
, getIReg(rA_addr
) );
12098 putVSReg( XT
, binop( Iop_64HLtoV128
,
12099 unop( Iop_32Sto64
, mkexpr( rA
) ),
12104 case 0xF3: // mtvsrwz
12106 UChar XT
= ifieldRegXT( theInstr
);
12107 UChar rA_addr
= ifieldRegA(theInstr
);
12108 IRTemp rA
= newTemp( Ity_I32
);
12109 DIP("mtvsrwz vsr%d,r%u\n", rA_addr
, XT
);
12111 * For SX=0, mtvsrwz is treated as a Floating-Point
12112 * instruction in terms of resource availability.
12113 * For SX=1, mtvsrwz is treated as a Vector instruction in
12114 * terms of resource availability.
12115 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
12118 assign( rA
, unop( Iop_64to32
, getIReg( rA_addr
) ) );
12120 assign( rA
, getIReg(rA_addr
) );
12122 putVSReg( XT
, binop( Iop_64HLtoV128
,
12123 binop( Iop_32HLto64
, mkU32( 0 ), mkexpr ( rA
) ),
12129 vex_printf("dis_proc_ctl(ppc)(opc2)\n");
12137 Cache Management Instructions
12139 static Bool
dis_cache_manage ( UInt prefix
, UInt theInstr
,
12141 UInt allow_isa_3_1
,
12142 const VexArchInfo
* guest_archinfo
)
12145 UChar opc1
= ifieldOPC(theInstr
);
12146 UChar b21to25
= ifieldRegDS(theInstr
);
12147 /* The L-field is 2 bits in ISA 3.0 and earlier and 3 bits in ISA 3.1 */
12148 UChar flag_L
= IFIELD(theInstr
, 21, (allow_isa_3_1
? 3 : 2));
12149 UChar rA_addr
= ifieldRegA(theInstr
);
12150 UChar rB_addr
= ifieldRegB(theInstr
);
12151 UInt opc2
= ifieldOPClo10(theInstr
);
12152 UChar b0
= ifieldBIT0(theInstr
);
12153 UInt lineszB
= guest_archinfo
->ppc_icache_line_szB
;
12154 Bool is_dcbzl
= False
;
12156 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
12158 /* There is no prefixed version of these instructions. */
12161 // Check for valid hint values for dcbt and dcbtst as currently described in
12162 // ISA 2.07. If valid, then we simply set b21to25 to zero since we have no
12163 // means of modeling the hint anyway.
12164 if (opc1
== 0x1F && ((opc2
== 0x116) || (opc2
== 0xF6))) {
12165 if (b21to25
== 0x10 || b21to25
< 0x10)
12168 if (opc1
== 0x1F && opc2
== 0x116 && b21to25
== 0x11)
12171 if (opc1
== 0x1F && opc2
== 0x3F6) { // dcbz
12172 if (b21to25
== 1) {
12175 if (!(guest_archinfo
->ppc_dcbzl_szB
)) {
12176 vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n");
12182 if (opc1
!= 0x1F || b0
!= 0) {
12183 if (0) vex_printf("dis_cache_manage %d %d\n",
12185 vex_printf("dis_cache_manage(ppc)(opc1|b0)\n");
12190 vassert(lineszB
== 16 || lineszB
== 32 || lineszB
== 64 || lineszB
== 128);
12193 //zz case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380)
12194 //zz vassert(0); /* AWAITING TEST CASE */
12195 //zz DIP("dcba r%u,r%u\n", rA_addr, rB_addr);
12196 //zz if (0) vex_printf("vex ppc->IR: kludged dcba\n");
12199 case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382)
12200 DIP("dcbf r%u,r%u\n", rA_addr
, rB_addr
);
12202 /* Check the L field and ISA version.
12203 dcbf ra, rb, 0 dcbf
12204 dcbf ra, rb, 1 dcbf local
12205 dcbf ra, rb, 3 dcbf local primary
12206 dcbf ra, rb, 4 dcbf block fjush to persistent storage isa 3.1
12207 dcbf ra, rb, 6 dcbf block store to persistent storage isa 3.1
12209 if (!((flag_L
== 0 || flag_L
== 1 || flag_L
== 3)
12210 || ((flag_L
== 4 || flag_L
== 6) && allow_isa_3_1
== True
)))
12212 vex_printf("dis_cache_manage(ppc)(dcbf,flag_L)\n");
12215 /* nop as far as vex is concerned */
12218 case 0x036: // dcbst (Data Cache Block Store, PPC32 p384)
12219 DIP("dcbst r%u,r%u\n", rA_addr
, rB_addr
);
12220 /* nop as far as vex is concerned */
12223 case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385)
12224 DIP("dcbt r%u,r%u\n", rA_addr
, rB_addr
);
12225 /* nop as far as vex is concerned */
12228 case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386)
12229 DIP("dcbtst r%u,r%u\n", rA_addr
, rB_addr
);
12230 /* nop as far as vex is concerned */
12233 case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387)
12234 // dcbzl (Data Cache Block Clear to Zero Long, bug#135264)
12235 /* Clear all bytes in cache block at (rA|0) + rB. */
12236 IRTemp EA
= newTemp(ty
);
12237 IRTemp addr
= newTemp(ty
);
12242 clearszB
= guest_archinfo
->ppc_dcbzl_szB
;
12243 DIP("dcbzl r%u,r%u\n", rA_addr
, rB_addr
);
12246 clearszB
= guest_archinfo
->ppc_dcbz_szB
;
12247 DIP("dcbz r%u,r%u\n", rA_addr
, rB_addr
);
12250 assign( EA
, ea_rAor0_idxd(rA_addr
, rB_addr
) );
12253 /* Round EA down to the start of the containing block. */
12254 assign( addr
, binop( Iop_And64
,
12256 mkU64( ~((ULong
)clearszB
-1) )) );
12258 for (i
= 0; i
< clearszB
/ 8; i
++) {
12259 irx_addr
= binop( Iop_Add64
, mkexpr(addr
), mkU64(i
*8) );
12260 store( irx_addr
, mkU64(0) );
12263 /* Round EA down to the start of the containing block. */
12264 assign( addr
, binop( Iop_And32
,
12266 mkU32( ~(clearszB
-1) )) );
12268 for (i
= 0; i
< clearszB
/ 4; i
++) {
12269 irx_addr
= binop( Iop_Add32
, mkexpr(addr
), mkU32(i
*4) );
12270 store( irx_addr
, mkU32(0) );
12277 // icbi (Instruction Cache Block Invalidate, PPC32 p431)
12278 /* Invalidate all translations containing code from the cache
12279 block at (rA|0) + rB. */
12280 IRTemp EA
= newTemp(ty
);
12281 IRTemp addr
= newTemp(ty
);
12282 DIP("icbi r%u,r%u\n", rA_addr
, rB_addr
);
12283 assign( EA
, ea_rAor0_idxd(rA_addr
, rB_addr
) );
12285 /* Round EA down to the start of the containing block. */
12286 assign( addr
, binop( mkSzOp(ty
, Iop_And8
),
12288 mkSzImm(ty
, ~(((ULong
)lineszB
)-1) )) );
12289 putGST( PPC_GST_CMSTART
, mkexpr(addr
) );
12290 putGST( PPC_GST_CMLEN
, mkSzImm(ty
, lineszB
) );
12292 /* be paranoid ... */
12293 stmt( IRStmt_MBE(Imbe_Fence
) );
12295 putGST( PPC_GST_CIA
, mkSzImm(ty
, nextInsnAddr()));
12296 dres
->jk_StopHere
= Ijk_InvalICache
;
12297 dres
->whatNext
= Dis_StopHere
;
12302 vex_printf("dis_cache_manage(ppc)(opc2)\n");
12309 /*------------------------------------------------------------*/
12310 /*--- Floating Point Helpers ---*/
12311 /*------------------------------------------------------------*/
12313 /* --------- Synthesise a 2-bit FPU rounding mode. --------- */
12314 /* Produces a value in 0 .. 3, which is encoded as per the type
12315 IRRoundingMode. PPCRoundingMode encoding is different to
12316 IRRoundingMode, so need to map it.
12319 static IRExpr
* /* :: Ity_I32 */ set_round_to_Oddmode ( void )
12321 /* PPC/ valgrind have two-bits to designate the rounding mode.
12322 ISA 3.0 adds instructions than can use a round to odd mode
12323 but did not change the number of bits for the rm. Basically,
12324 they added two instructions that only differ by the rounding
12325 mode the operation uses. In essesce, they encoded the rm
12326 in the name. In order to avoid having to create Iops, that
12327 encode the rm in th name, we will "expand" the definition of
12328 the rounding mode bits. We will just pass the rm and then
12329 map the to odd mode to the appropriate PPCFpOp name that
12330 will tell us which instruction to map to.
12332 rounding mode | PPC | IR
12333 ------------------------
12334 to nearest | 000 | 00
12336 to +infinity | 010 | 10
12337 to -infinity | 011 | 01
12343 static IRExpr
* /* :: Ity_I32 */ get_IR_roundingmode ( void )
12346 rounding mode | PPC | IR
12347 ------------------------
12348 to nearest | 00 | 00
12350 to +infinity | 10 | 10
12351 to -infinity | 11 | 01
12353 IRTemp rm_PPC32
= newTemp(Ity_I32
);
12354 assign( rm_PPC32
, getGST_masked( PPC_GST_FPSCR
, MASK_FPSCR_RN
) );
12356 // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
12357 return binop( Iop_Xor32
,
12360 binop(Iop_Shl32
, mkexpr(rm_PPC32
), mkU8(1)),
12364 /* The DFP IR rounding modes were chosen such that the existing PPC to IR
12365 * mapping would still work with the extended three bit DFP rounding
12368 * rounding mode | PPC | IR
12369 * -----------------------------------------------
12370 * to nearest, ties to even | 000 | 000
12371 * to zero | 001 | 011
12372 * to +infinity | 010 | 010
12373 * to -infinity | 011 | 001
12374 * to nearest, ties away from 0 | 100 | 100
12375 * to nearest, ties toward 0 | 101 | 111
12376 * to away from 0 | 110 | 110
12377 * to prepare for shorter precision | 111 | 101
12379 static IRExpr
* /* :: Ity_I32 */ get_IR_roundingmode_DFP( void )
12381 IRTemp rm_PPC32
= newTemp( Ity_I32
);
12382 assign( rm_PPC32
, getGST_masked_upper( PPC_GST_FPSCR
, MASK_FPSCR_DRN
) );
12384 // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
12385 return binop( Iop_Xor32
,
12386 mkexpr( rm_PPC32
),
12388 binop( Iop_Shl32
, mkexpr( rm_PPC32
), mkU8( 1 ) ),
12392 #define NANmaskSingle 0x7F800000
12393 #define NANmaskDouble 0x7FF00000
12395 static IRExpr
* Check_NaN( IRExpr
* value
, IRExpr
* Hi32Mask
)
12397 IRTemp exp_zero
= newTemp(Ity_I8
);
12398 IRTemp frac_mask
= newTemp(Ity_I32
);
12399 IRTemp frac_not_zero
= newTemp(Ity_I8
);
12401 /* Check if the result is QNAN or SNAN and not +infinity or -infinity.
12402 * The input value is always 64-bits, for single precision values, the
12403 * lower 32 bits must be zero.
12406 * [62:54] exponent field is equal to 0xFF for NAN and Infinity.
12407 * [53:32] fraction field is zero for Infinity and non-zero for NAN
12408 * [31:0] unused for single precision representation
12411 * [62:51] exponent field is equal to 0xFF for NAN and Infinity.
12412 * [50:0] fraction field is zero for Infinity and non-zero for NAN
12414 * Returned result is a U32 value of 0xFFFFFFFF for NaN and 0 otherwise.
12416 assign( frac_mask
, unop( Iop_Not32
,
12418 mkU32( 0x80000000ULL
), Hi32Mask
) ) );
12422 binop( Iop_CmpEQ32
,
12424 unop( Iop_64HIto32
,
12425 unop( Iop_ReinterpF64asI64
,
12429 assign( frac_not_zero
,
12432 binop( Iop_CmpNE32
,
12434 unop( Iop_64HIto32
,
12435 unop( Iop_ReinterpF64asI64
,
12437 mkexpr( frac_mask
) ),
12440 binop( Iop_CmpNE32
,
12443 unop( Iop_ReinterpF64asI64
,
12445 mkU32( 0xFFFFFFFF ) ),
12446 mkU32( 0x0 ) ) ) ) );
12447 return unop( Iop_8Sto32
,
12449 mkexpr( exp_zero
),
12450 mkexpr( frac_not_zero
) ) );
12453 static IRExpr
* Complement_non_NaN( IRExpr
* value
, IRExpr
* nan_mask
)
12455 /* This function will only complement the 64-bit floating point value if it
12456 * is not Nan. NaN is not a signed value. Need to do computations using
12457 * 32-bit operands to ensure it will run in 32-bit mode.
12459 return binop( Iop_32HLto64
,
12463 unop( Iop_64HIto32
,
12464 unop( Iop_ReinterpF64asI64
,
12469 unop( Iop_64HIto32
,
12470 unop( Iop_ReinterpF64asI64
,
12474 unop( Iop_ReinterpF64asI64
, value
) ) );
12477 /*------------------------------------------------------------*/
12478 /*--- Floating Point Instruction Translation ---*/
12479 /*------------------------------------------------------------*/
12482 Floating Point Load Instructions
12484 static Bool
dis_fp_load_prefix ( UInt prefix
, UInt theInstr
)
12486 /* X-Form, D-Form */
12487 UChar opc1
= ifieldOPC(theInstr
);
12488 UChar frT_addr
= ifieldRegDS(theInstr
);
12489 UChar rA_addr
= ifieldRegA(theInstr
);
12491 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
12492 IRTemp EA
= newTemp(ty
);
12493 IRTemp rA
= newTemp(ty
);
12494 UInt ptype
= PrefixType(prefix
);
12495 Bool is_prefix
= prefix_instruction( prefix
);
12496 UInt R
= 0; // must be zero for word instruction
12497 ULong immediate_val
= 0;
12499 assign( rA
, getIReg(rA_addr
) );
12500 assign( EA
, calculate_prefix_EA( prefix
, theInstr
, rA_addr
,
12501 ptype
, DFORM_IMMASK
,
12502 &immediate_val
, &R
) );
12505 case 0x30: // lfs (Load Float Single, PPC32 p441)
12506 pDIP( is_prefix
, "lfs fr%u,%llu(r%u)\n", frT_addr
, immediate_val
, rA_addr
);
12507 DIPp( is_prefix
, ",%u", R
);
12509 unop(Iop_F32toF64
, load(Ity_F32
, mkexpr(EA
))) );
12512 case 0x32: // lfd (Load Float Double, PPC32 p437)
12513 pDIP( prefix
, "lfd fr%u,%llu(r%u)", frT_addr
, immediate_val
, rA_addr
);
12514 DIPp( is_prefix
, ",%u", R
);
12515 putFReg( frT_addr
, load(Ity_F64
, mkexpr(EA
)) );
12519 vex_printf("dis_fp_load_prefix(ppc)(opc1)\n");
12525 static Bool
dis_fp_load ( UInt prefix
, UInt theInstr
)
12527 /* X-Form, D-Form */
12528 UChar opc1
= ifieldOPC(theInstr
);
12529 UChar frD_addr
= ifieldRegDS(theInstr
);
12530 UChar rA_addr
= ifieldRegA(theInstr
);
12531 UChar rB_addr
= ifieldRegB(theInstr
);
12532 UInt opc2
= ifieldOPClo10(theInstr
);
12533 UChar b0
= ifieldBIT0(theInstr
);
12534 UInt uimm16
= ifieldUIMM16(theInstr
);
12536 Int simm16
= extend_s_16to32(uimm16
);
12537 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
12538 IRTemp EA
= newTemp(ty
);
12539 IRTemp rA
= newTemp(ty
);
12540 IRTemp rB
= newTemp(ty
);
12541 IRTemp iHi
= newTemp(Ity_I32
);
12542 IRTemp iLo
= newTemp(Ity_I32
);
12544 /* There is no prefixed version of these instructions. */
12547 assign( rA
, getIReg(rA_addr
) );
12548 assign( rB
, getIReg(rB_addr
) );
12550 /* These are completely straightforward from a rounding and status
12551 bits perspective: no rounding involved and no funny status or CR
12555 case 0x30: // lfs (Load Float Single, PPC32 p441)
12556 DIP("lfs fr%u,%d(r%u)\n", frD_addr
, simm16
, rA_addr
);
12557 assign( EA
, ea_rAor0_simm(rA_addr
, simm16
) );
12559 unop(Iop_F32toF64
, load(Ity_F32
, mkexpr(EA
))) );
12562 case 0x31: // lfsu (Load Float Single, Update, PPC32 p442)
12565 DIP("lfsu fr%u,%d(r%u)\n", frD_addr
, simm16
, rA_addr
);
12566 assign( EA
, ea_rA_simm(rA_addr
, simm16
) );
12568 unop(Iop_F32toF64
, load(Ity_F32
, mkexpr(EA
))) );
12569 putIReg( rA_addr
, mkexpr(EA
) );
12572 case 0x32: // lfd (Load Float Double, PPC32 p437)
12573 DIP("lfd fr%u,%d(r%u)\n", frD_addr
, simm16
, rA_addr
);
12574 assign( EA
, ea_rAor0_simm(rA_addr
, simm16
) );
12575 putFReg( frD_addr
, load(Ity_F64
, mkexpr(EA
)) );
12578 case 0x33: // lfdu (Load Float Double, Update, PPC32 p438)
12581 DIP("lfdu fr%u,%d(r%u)\n", frD_addr
, simm16
, rA_addr
);
12582 assign( EA
, ea_rA_simm(rA_addr
, simm16
) );
12583 putFReg( frD_addr
, load(Ity_F64
, mkexpr(EA
)) );
12584 putIReg( rA_addr
, mkexpr(EA
) );
12589 vex_printf("dis_fp_load(ppc)(instr,b0)\n");
12594 case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444)
12595 DIP("lfsx fr%u,r%u,r%u\n", frD_addr
, rA_addr
, rB_addr
);
12596 assign( EA
, ea_rAor0_idxd(rA_addr
, rB_addr
) );
12597 putFReg( frD_addr
, unop( Iop_F32toF64
,
12598 load(Ity_F32
, mkexpr(EA
))) );
12601 case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443)
12604 DIP("lfsux fr%u,r%u,r%u\n", frD_addr
, rA_addr
, rB_addr
);
12605 assign( EA
, ea_rA_idxd(rA_addr
, rB_addr
) );
12607 unop(Iop_F32toF64
, load(Ity_F32
, mkexpr(EA
))) );
12608 putIReg( rA_addr
, mkexpr(EA
) );
12611 case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440)
12612 DIP("lfdx fr%u,r%u,r%u\n", frD_addr
, rA_addr
, rB_addr
);
12613 assign( EA
, ea_rAor0_idxd(rA_addr
, rB_addr
) );
12614 putFReg( frD_addr
, load(Ity_F64
, mkexpr(EA
)) );
12617 case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439)
12620 DIP("lfdux fr%u,r%u,r%u\n", frD_addr
, rA_addr
, rB_addr
);
12621 assign( EA
, ea_rA_idxd(rA_addr
, rB_addr
) );
12622 putFReg( frD_addr
, load(Ity_F64
, mkexpr(EA
)) );
12623 putIReg( rA_addr
, mkexpr(EA
) );
12626 case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120)
12627 DIP("lfiwax fr%u,r%u,r%u\n", frD_addr
, rA_addr
, rB_addr
);
12628 assign( EA
, ea_rAor0_idxd( rA_addr
, rB_addr
) );
12629 assign( iLo
, load(Ity_I32
, mkexpr(EA
)) );
12630 assign( iHi
, binop(Iop_Sub32
,
12632 binop(Iop_Shr32
, mkexpr(iLo
), mkU8(31))) );
12633 putFReg( frD_addr
, unop(Iop_ReinterpI64asF64
,
12634 binop(Iop_32HLto64
, mkexpr(iHi
), mkexpr(iLo
))) );
12637 case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed
12639 IRTemp dw
= newTemp( Ity_I64
);
12640 DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr
, rA_addr
, rB_addr
);
12641 assign( EA
, ea_rAor0_idxd( rA_addr
, rB_addr
) );
12642 assign( iLo
, load(Ity_I32
, mkexpr(EA
)) );
12643 assign( dw
, binop( Iop_32HLto64
, mkU32( 0 ), mkexpr( iLo
) ) );
12644 putFReg( frD_addr
, unop( Iop_ReinterpI64asF64
, mkexpr( dw
) ) );
12649 vex_printf("dis_fp_load(ppc)(opc2)\n");
12655 vex_printf("dis_fp_load(ppc)(opc1)\n");
12664 Floating Point Store Instructions
12666 static Bool
dis_fp_store_prefix ( UInt prefix
, UInt theInstr
)
12668 /* X-Form, D-Form */
12669 UChar opc1
= ifieldOPC(theInstr
);
12670 UChar frS_addr
= ifieldRegDS(theInstr
);
12671 UChar rA_addr
= ifieldRegA(theInstr
);
12673 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
12674 IRTemp frS
= newTemp(Ity_F64
);
12675 IRTemp EA
= newTemp(ty
);
12676 IRTemp rA
= newTemp(ty
);
12677 UInt ptype
= PrefixType(prefix
);
12678 Bool is_prefix
= prefix_instruction( prefix
);
12679 UInt R
= 0; // must be zero for word instruction
12680 ULong immediate_val
= 0;
12682 assign( frS
, getFReg( frS_addr
) );
12683 assign( rA
, getIReg( rA_addr
) );
12684 assign( EA
, calculate_prefix_EA( prefix
, theInstr
, rA_addr
,
12685 ptype
, DFORM_IMMASK
,
12686 &immediate_val
, &R
) );
12688 /* These are straightforward from a status bits perspective: no
12689 funny status or CR bits affected. For single precision stores,
12690 the values are truncated and denormalised (not rounded) to turn
12691 them into single precision values. */
12695 case 0x34: // stfs (Store Float Single, PPC32 p518)
12696 pDIP( is_prefix
, "stfs fr%u,%llu(r%u)\n", frS_addr
, immediate_val
, rA_addr
);
12697 DIPp( is_prefix
, ",%u", R
);
12698 /* Use Iop_TruncF64asF32 to truncate and possible denormalise
12699 the value to be stored in the correct way, without any
12701 store( mkexpr(EA
), unop(Iop_TruncF64asF32
, mkexpr(frS
)) );
12704 case 0x36: // stfd (Store Float Double, PPC32 p513)
12705 pDIP( is_prefix
, "stfd fr%u,%llu(r%u)", frS_addr
, immediate_val
, rA_addr
);
12706 DIPp( is_prefix
, ",%u", R
);
12707 store( mkexpr(EA
), mkexpr(frS
) );
12711 vex_printf("dis_fp_store_prefix(ppc)(opc1)\n");
12717 static Bool
dis_fp_store ( UInt prefix
, UInt theInstr
)
12719 /* X-Form, D-Form */
12720 UChar opc1
= ifieldOPC(theInstr
);
12721 UChar frS_addr
= ifieldRegDS(theInstr
);
12722 UChar rA_addr
= ifieldRegA(theInstr
);
12723 UChar rB_addr
= ifieldRegB(theInstr
);
12724 UInt opc2
= ifieldOPClo10(theInstr
);
12725 UChar b0
= ifieldBIT0(theInstr
);
12726 Int uimm16
= ifieldUIMM16(theInstr
);
12728 Int simm16
= extend_s_16to32(uimm16
);
12729 IRTemp frS
= newTemp(Ity_F64
);
12730 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
12731 IRTemp EA
= newTemp(ty
);
12732 IRTemp rA
= newTemp(ty
);
12733 IRTemp rB
= newTemp(ty
);
12735 /* There is no prefixed version of these instructions. */
12738 assign( frS
, getFReg(frS_addr
) );
12739 assign( rA
, getIReg(rA_addr
) );
12740 assign( rB
, getIReg(rB_addr
) );
12742 /* These are straightforward from a status bits perspective: no
12743 funny status or CR bits affected. For single precision stores,
12744 the values are truncated and denormalised (not rounded) to turn
12745 them into single precision values. */
12748 case 0x35: // stfsu (Store Float Single, Update, PPC32 p519)
12751 DIP("stfsu fr%u,%d(r%u)\n", frS_addr
, simm16
, rA_addr
);
12752 assign( EA
, ea_rA_simm(rA_addr
, simm16
) );
12753 /* See comment for stfs */
12754 store( mkexpr(EA
), unop(Iop_TruncF64asF32
, mkexpr(frS
)) );
12755 putIReg( rA_addr
, mkexpr(EA
) );
12758 case 0x37: // stfdu (Store Float Double, Update, PPC32 p514)
12761 DIP("stfdu fr%u,%d(r%u)\n", frS_addr
, simm16
, rA_addr
);
12762 assign( EA
, ea_rA_simm(rA_addr
, simm16
) );
12763 store( mkexpr(EA
), mkexpr(frS
) );
12764 putIReg( rA_addr
, mkexpr(EA
) );
12769 vex_printf("dis_fp_store(ppc)(instr,b0)\n");
12773 case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521)
12774 DIP("stfsx fr%u,r%u,r%u\n", frS_addr
, rA_addr
, rB_addr
);
12775 assign( EA
, ea_rAor0_idxd(rA_addr
, rB_addr
) );
12776 /* See note for stfs */
12778 unop(Iop_TruncF64asF32
, mkexpr(frS
)) );
12781 case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520)
12784 DIP("stfsux fr%u,r%u,r%u\n", frS_addr
, rA_addr
, rB_addr
);
12785 assign( EA
, ea_rA_idxd(rA_addr
, rB_addr
) );
12786 /* See note for stfs */
12787 store( mkexpr(EA
), unop(Iop_TruncF64asF32
, mkexpr(frS
)) );
12788 putIReg( rA_addr
, mkexpr(EA
) );
12791 case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516)
12792 DIP("stfdx fr%u,r%u,r%u\n", frS_addr
, rA_addr
, rB_addr
);
12793 assign( EA
, ea_rAor0_idxd(rA_addr
, rB_addr
) );
12794 store( mkexpr(EA
), mkexpr(frS
) );
12797 case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515)
12800 DIP("stfdux fr%u,r%u,r%u\n", frS_addr
, rA_addr
, rB_addr
);
12801 assign( EA
, ea_rA_idxd(rA_addr
, rB_addr
) );
12802 store( mkexpr(EA
), mkexpr(frS
) );
12803 putIReg( rA_addr
, mkexpr(EA
) );
12806 case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517)
12807 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
12808 DIP("stfiwx fr%u,r%u,r%u\n", frS_addr
, rA_addr
, rB_addr
);
12809 assign( EA
, ea_rAor0_idxd(rA_addr
, rB_addr
) );
12811 unop(Iop_64to32
, unop(Iop_ReinterpF64asI64
, mkexpr(frS
))) );
12815 vex_printf("dis_fp_store(ppc)(opc2)\n");
12821 vex_printf("dis_fp_store(ppc)(opc1)\n");
12830 Floating Point Arith Instructions
12832 static Bool
dis_fp_arith ( UInt prefix
, UInt theInstr
)
12835 UChar opc1
= ifieldOPC(theInstr
);
12836 UChar frD_addr
= ifieldRegDS(theInstr
);
12837 UChar frA_addr
= ifieldRegA(theInstr
);
12838 UChar frB_addr
= ifieldRegB(theInstr
);
12839 UChar frC_addr
= ifieldRegC(theInstr
);
12840 UChar opc2
= ifieldOPClo5(theInstr
);
12841 UChar flag_rC
= ifieldBIT0(theInstr
);
12843 IRTemp frD
= newTemp(Ity_F64
);
12844 IRTemp frA
= newTemp(Ity_F64
);
12845 IRTemp frB
= newTemp(Ity_F64
);
12846 IRTemp frC
= newTemp(Ity_F64
);
12847 IRExpr
* rm
= get_IR_roundingmode();
12849 /* By default, we will examine the results of the operation and set
12850 fpscr[FPRF] accordingly. */
12851 Bool set_FPRF
= True
;
12853 /* By default, if flag_RC is set, we will clear cr1 after the
12854 operation. In reality we should set cr1 to indicate the
12855 exception status of the operation, but since we're not
12856 simulating exceptions, the exception status will appear to be
12857 zero. Hence cr1 should be cleared if this is a . form insn. */
12858 Bool clear_CR1
= True
;
12860 /* There is no prefixed version of these instructions. */
12863 assign( frA
, getFReg(frA_addr
));
12864 assign( frB
, getFReg(frB_addr
));
12865 assign( frC
, getFReg(frC_addr
));
12870 case 0x12: // fdivs (Floating Divide Single, PPC32 p407)
12873 DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
12874 frD_addr
, frA_addr
, frB_addr
);
12875 assign( frD
, triop( Iop_DivF64r32
,
12876 rm
, mkexpr(frA
), mkexpr(frB
) ));
12879 case 0x14: // fsubs (Floating Subtract Single, PPC32 p430)
12882 DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
12883 frD_addr
, frA_addr
, frB_addr
);
12884 assign( frD
, triop( Iop_SubF64r32
,
12885 rm
, mkexpr(frA
), mkexpr(frB
) ));
12888 case 0x15: // fadds (Floating Add Single, PPC32 p401)
12891 DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
12892 frD_addr
, frA_addr
, frB_addr
);
12893 assign( frD
, triop( Iop_AddF64r32
,
12894 rm
, mkexpr(frA
), mkexpr(frB
) ));
12897 case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428)
12898 // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
12899 if (frA_addr
!= 0 || frC_addr
!= 0)
12901 DIP("fsqrts%s fr%u,fr%u\n", flag_rC
? ".":"",
12902 frD_addr
, frB_addr
);
12903 // however illogically, on ppc970 this insn behaves identically
12904 // to fsqrt (double-precision). So use SqrtF64, not SqrtF64r32.
12905 assign( frD
, binop( Iop_SqrtF64
, rm
, mkexpr(frB
) ));
12908 case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421)
12909 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
12910 if (frA_addr
!= 0 || frC_addr
!= 0)
12912 DIP("fres%s fr%u,fr%u\n", flag_rC
? ".":"",
12913 frD_addr
, frB_addr
);
12915 = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL
));
12916 assign( frD
, triop( Iop_DivF64r32
,
12918 ieee_one
, mkexpr(frB
) ));
12922 case 0x19: // fmuls (Floating Multiply Single, PPC32 p414)
12925 DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
12926 frD_addr
, frA_addr
, frC_addr
);
12927 assign( frD
, triop( Iop_MulF64r32
,
12928 rm
, mkexpr(frA
), mkexpr(frC
) ));
12931 case 0x1A: // frsqrtes (Floating Recip SqRt Est Single)
12932 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
12933 // Undocumented instruction?
12934 if (frA_addr
!= 0 || frC_addr
!= 0)
12936 DIP("frsqrtes%s fr%u,fr%u\n", flag_rC
? ".":"",
12937 frD_addr
, frB_addr
);
12938 assign( frD
, unop(Iop_RSqrtEst5GoodF64
, mkexpr(frB
)) );
12942 vex_printf("dis_fp_arith(ppc)(3B: opc2)\n");
12949 case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406)
12952 DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
12953 frD_addr
, frA_addr
, frB_addr
);
12954 assign( frD
, triop(Iop_DivF64
, rm
, mkexpr(frA
), mkexpr(frB
)) );
12957 case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429)
12960 DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
12961 frD_addr
, frA_addr
, frB_addr
);
12962 assign( frD
, triop(Iop_SubF64
, rm
, mkexpr(frA
), mkexpr(frB
)) );
12965 case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400)
12968 DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
12969 frD_addr
, frA_addr
, frB_addr
);
12970 assign( frD
, triop(Iop_AddF64
, rm
, mkexpr(frA
), mkexpr(frB
)) );
12973 case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427)
12974 // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
12975 if (frA_addr
!= 0 || frC_addr
!= 0)
12977 DIP("fsqrt%s fr%u,fr%u\n", flag_rC
? ".":"",
12978 frD_addr
, frB_addr
);
12979 assign( frD
, binop(Iop_SqrtF64
, rm
, mkexpr(frB
)) );
12982 case 0x17: { // fsel (Floating Select, PPC32 p426)
12983 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
12984 IRTemp cc
= newTemp(Ity_I32
);
12985 IRTemp cc_b0
= newTemp(Ity_I32
);
12987 DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
12988 frD_addr
, frA_addr
, frC_addr
, frB_addr
);
12990 // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40
12991 // => GT|EQ == (cc & 0x1 == 0)
12992 assign( cc
, binop(Iop_CmpF64
, mkexpr(frA
),
12993 IRExpr_Const(IRConst_F64(0))) );
12994 assign( cc_b0
, binop(Iop_And32
, mkexpr(cc
), mkU32(1)) );
12996 // frD = (frA >= 0.0) ? frC : frB
12997 // = (cc_b0 == 0) ? frC : frB
13000 binop(Iop_CmpEQ32
, mkexpr(cc_b0
), mkU32(0)),
13004 /* One of the rare ones which don't mess with FPRF */
13009 case 0x18: // fre (Floating Reciprocal Estimate)
13010 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
13011 // Note: unclear whether this insn really exists or not
13012 // ppc970 doesn't have it, but POWER5 does
13013 if (frA_addr
!= 0 || frC_addr
!= 0)
13015 DIP("fre%s fr%u,fr%u\n", flag_rC
? ".":"",
13016 frD_addr
, frB_addr
);
13018 = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL
));
13019 assign( frD
, triop( Iop_DivF64
,
13021 ieee_one
, mkexpr(frB
) ));
13025 case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413)
13027 vex_printf("dis_fp_arith(ppc)(instr,fmul)\n");
13028 DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
13029 frD_addr
, frA_addr
, frC_addr
);
13030 assign( frD
, triop(Iop_MulF64
, rm
, mkexpr(frA
), mkexpr(frC
)) );
13033 case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424)
13034 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
13035 if (frA_addr
!= 0 || frC_addr
!= 0)
13037 DIP("frsqrte%s fr%u,fr%u\n", flag_rC
? ".":"",
13038 frD_addr
, frB_addr
);
13039 assign( frD
, unop(Iop_RSqrtEst5GoodF64
, mkexpr(frB
)) );
13043 vex_printf("dis_fp_arith(ppc)(3F: opc2)\n");
13049 vex_printf("dis_fp_arith(ppc)(opc1)\n");
13053 putFReg( frD_addr
, mkexpr(frD
) );
13056 // XXX XXX XXX FIXME
13057 // set FPRF from frD
13060 if (flag_rC
&& clear_CR1
) {
13061 putCR321( 1, mkU8(0) );
13062 putCR0( 1, mkU8(0) );
13071 Floating Point Mult-Add Instructions
13073 static Bool
dis_fp_multadd ( UInt prefix
, UInt theInstr
)
13076 UChar opc1
= ifieldOPC(theInstr
);
13077 UChar frD_addr
= ifieldRegDS(theInstr
);
13078 UChar frA_addr
= ifieldRegA(theInstr
);
13079 UChar frB_addr
= ifieldRegB(theInstr
);
13080 UChar frC_addr
= ifieldRegC(theInstr
);
13081 UChar opc2
= ifieldOPClo5(theInstr
);
13082 UChar flag_rC
= ifieldBIT0(theInstr
);
13084 IRTemp frD
= newTemp(Ity_F64
);
13085 IRTemp frA
= newTemp(Ity_F64
);
13086 IRTemp frB
= newTemp(Ity_F64
);
13087 IRTemp frC
= newTemp(Ity_F64
);
13088 IRTemp rmt
= newTemp(Ity_I32
);
13089 IRTemp tmp
= newTemp(Ity_F64
);
13090 IRTemp sign_tmp
= newTemp(Ity_I64
);
13091 IRTemp nan_mask
= newTemp(Ity_I32
);
13094 /* By default, we will examine the results of the operation and set
13095 fpscr[FPRF] accordingly. */
13096 Bool set_FPRF
= True
;
13098 /* By default, if flag_RC is set, we will clear cr1 after the
13099 operation. In reality we should set cr1 to indicate the
13100 exception status of the operation, but since we're not
13101 simulating exceptions, the exception status will appear to be
13102 zero. Hence cr1 should be cleared if this is a . form insn. */
13103 Bool clear_CR1
= True
;
13105 /* There is no prefixed version of these instructions. */
13108 /* Bind the rounding mode expression to a temp; there's no
13109 point in creating gratuitous CSEs, as we know we'll need
13110 to use it twice. */
13111 assign( rmt
, get_IR_roundingmode() );
13114 assign( frA
, getFReg(frA_addr
));
13115 assign( frB
, getFReg(frB_addr
));
13116 assign( frC
, getFReg(frC_addr
));
13118 /* The rounding in this is all a bit dodgy. The idea is to only do
13119 one rounding. That clearly isn't achieveable without dedicated
13120 four-input IR primops, although in the single precision case we
13121 can sort-of simulate it by doing the inner multiply in double
13124 In the negated cases, the negation happens after rounding. */
13129 case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412)
13130 DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
13131 frD_addr
, frA_addr
, frC_addr
, frB_addr
);
13132 assign( frD
, qop( Iop_MSubF64r32
, rm
,
13133 mkexpr(frA
), mkexpr(frC
), mkexpr(frB
) ));
13136 case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409)
13137 DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
13138 frD_addr
, frA_addr
, frC_addr
, frB_addr
);
13139 assign( frD
, qop( Iop_MAddF64r32
, rm
,
13140 mkexpr(frA
), mkexpr(frC
), mkexpr(frB
) ));
13143 case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420)
13144 case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418)
13146 if (opc2
== 0x1E) {
13147 DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
13148 frD_addr
, frA_addr
, frC_addr
, frB_addr
);
13149 assign( tmp
, qop( Iop_MSubF64r32
, rm
,
13150 mkexpr(frA
), mkexpr(frC
), mkexpr(frB
) ) );
13152 DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
13153 frD_addr
, frA_addr
, frC_addr
, frB_addr
);
13154 assign( tmp
, qop( Iop_MAddF64r32
, rm
,
13155 mkexpr(frA
), mkexpr(frC
), mkexpr(frB
) ) );
13158 assign( nan_mask
, Check_NaN( mkexpr( tmp
),
13159 mkU32( NANmaskSingle
) ) );
13160 assign( sign_tmp
, Complement_non_NaN( mkexpr( tmp
),
13161 mkexpr( nan_mask
) ) );
13162 assign( frD
, unop( Iop_ReinterpI64asF64
, mkexpr( sign_tmp
) ) );
13166 vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n");
13173 case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411)
13174 DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
13175 frD_addr
, frA_addr
, frC_addr
, frB_addr
);
13176 assign( frD
, qop( Iop_MSubF64
, rm
,
13177 mkexpr(frA
), mkexpr(frC
), mkexpr(frB
) ));
13180 case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408)
13181 DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
13182 frD_addr
, frA_addr
, frC_addr
, frB_addr
);
13183 assign( frD
, qop( Iop_MAddF64
, rm
,
13184 mkexpr(frA
), mkexpr(frC
), mkexpr(frB
) ));
13187 case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419)
13188 case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417)
13190 if (opc2
== 0x1E) {
13191 DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
13192 frD_addr
, frA_addr
, frC_addr
, frB_addr
);
13193 assign( tmp
, qop( Iop_MSubF64
, rm
,
13194 mkexpr(frA
), mkexpr(frC
), mkexpr(frB
) ) );
13196 DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC
? ".":"",
13197 frD_addr
, frA_addr
, frC_addr
, frB_addr
);
13198 assign( tmp
, qop( Iop_MAddF64
, rm
,
13199 mkexpr(frA
), mkexpr(frC
), mkexpr(frB
) ));
13202 assign( nan_mask
, Check_NaN( mkexpr( tmp
),
13203 mkU32( NANmaskDouble
) ) );
13204 assign( sign_tmp
, Complement_non_NaN( mkexpr( tmp
),
13205 mkexpr( nan_mask
) ) );
13206 assign( frD
, unop( Iop_ReinterpI64asF64
, mkexpr( sign_tmp
) ) );
13210 vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n");
13216 vex_printf("dis_fp_multadd(ppc)(opc1)\n");
13220 putFReg( frD_addr
, mkexpr(frD
) );
13223 // XXX XXX XXX FIXME
13224 // set FPRF from frD
13227 if (flag_rC
&& clear_CR1
) {
13228 putCR321( 1, mkU8(0) );
13229 putCR0( 1, mkU8(0) );
13236 * fe_flag is set to 1 if any of the following conditions occurs:
13237 * - The floating-point operand in register FRB is a Zero, a
13238 * NaN, an Infinity, or a negative value.
13239 * - e_b is less than or equal to: -970 for double precision; -103 for single precision
13240 * Otherwise fe_flag is set to 0.
13242 * fg_flag is set to 1 if either of the following conditions occurs.
13243 * - The floating-point operand in register FRB is a Zero, an
13244 * Infinity, or a denormalized value.
13245 * Otherwise fg_flag is set to 0.
13249 static void do_fp_tsqrt(IRTemp frB_Int
, Bool sp
, IRTemp
* fe_flag_tmp
, IRTemp
* fg_flag_tmp
)
13251 // The following temps are for holding intermediate results
13252 IRTemp e_b
= newTemp(Ity_I32
);
13253 IRExpr
* fe_flag
, * fg_flag
;
13254 IRTemp frB_exp_shR
= newTemp(Ity_I32
);
13255 UInt bias
= sp
? 127 : 1023;
13256 IRExpr
* frbNaN
, * frbDenorm
, * frBNeg
;
13258 IRTemp frbZero_tmp
= newTemp(Ity_I1
);
13259 IRTemp frbInf_tmp
= newTemp(Ity_I1
);
13260 *fe_flag_tmp
= newTemp(Ity_I32
);
13261 *fg_flag_tmp
= newTemp(Ity_I32
);
13264 assign( frB_exp_shR
, fp_exp_part( Ity_I32
, frB_Int
) );
13266 assign( frB_exp_shR
, fp_exp_part( Ity_I64
, frB_Int
) );
13268 assign(e_b
, binop( Iop_Sub32
, mkexpr(frB_exp_shR
), mkU32( bias
) ));
13270 ////////////////// fe_flag tests BEGIN //////////////////////
13271 /* We first do all tests that may result in setting fe_flag to '1'.
13272 * (NOTE: These tests are similar to those used for ftdiv. See do_fp_tdiv()
13276 frbNaN
= is_NaN( Ity_I32
, frB_Int
);
13277 assign( frbInf_tmp
, is_Inf( Ity_I32
, frB_Int
) );
13278 assign( frbZero_tmp
, is_Zero( Ity_I32
, frB_Int
) );
13281 frbNaN
= is_NaN( Ity_I64
, frB_Int
);
13282 assign( frbInf_tmp
, is_Inf( Ity_I64
, frB_Int
) );
13283 assign( frbZero_tmp
, is_Zero( Ity_I64
, frB_Int
) );
13287 // Test_value = -970 for double precision
13288 UInt test_value
= sp
? 0xffffff99 : 0xfffffc36;
13289 eb_LTE
= binop( Iop_CmpLE32S
, mkexpr( e_b
), mkU32( test_value
) );
13291 frBNeg
= binop( Iop_CmpEQ32
,
13293 sp
? mkexpr( frB_Int
) : unop( Iop_64HIto32
, mkexpr( frB_Int
) ),
13296 ////////////////// fe_flag tests END //////////////////////
13298 ////////////////// fg_flag tests BEGIN //////////////////////
13300 * The following tests were already performed above in the fe_flag
13301 * tests. So these conditions will result in both fe_ and fg_ flags
13303 * - Test if FRB is Zero
13304 * - Test if FRB is an Infinity
13308 * Test if FRB holds a denormalized value. A denormalized value is one where
13309 * the exp is 0 and the fraction is non-zero.
13312 IRTemp frac_part
= newTemp(Ity_I32
);
13313 assign( frac_part
, binop( Iop_And32
, mkexpr(frB_Int
), mkU32(0x007fffff)) );
13315 = mkAND1( binop( Iop_CmpEQ32
, mkexpr( frB_exp_shR
), mkU32( 0 ) ),
13316 binop( Iop_CmpNE32
, mkexpr( frac_part
), mkU32( 0 ) ) );
13318 IRExpr
* hi32
, * low32
, * fraction_is_nonzero
;
13319 IRTemp frac_part
= newTemp(Ity_I64
);
13321 assign( frac_part
, FP_FRAC_PART(frB_Int
) );
13322 hi32
= unop( Iop_64HIto32
, mkexpr( frac_part
) );
13323 low32
= unop( Iop_64to32
, mkexpr( frac_part
) );
13324 fraction_is_nonzero
= binop( Iop_CmpNE32
, binop( Iop_Or32
, low32
, hi32
),
13327 = mkAND1( binop( Iop_CmpEQ32
, mkexpr( frB_exp_shR
), mkU32( 0 ) ),
13328 fraction_is_nonzero
);
13330 ////////////////// fg_flag tests END //////////////////////
13332 /////////////////////////
13333 fe_flag
= mkOR1( mkexpr( frbZero_tmp
),
13335 mkOR1( mkexpr( frbInf_tmp
),
13336 mkOR1( frBNeg
, eb_LTE
) ) ) );
13338 fe_flag
= unop(Iop_1Uto32
, fe_flag
);
13340 fg_flag
= mkOR1( mkexpr( frbZero_tmp
),
13341 mkOR1( mkexpr( frbInf_tmp
), frbDenorm
) );
13342 fg_flag
= unop(Iop_1Uto32
, fg_flag
);
13343 assign (*fg_flag_tmp
, fg_flag
);
13344 assign (*fe_flag_tmp
, fe_flag
);
13347 * fe_flag is set to 1 if any of the following conditions occurs:
13348 * - The double-precision floating-point operand in register FRA is a NaN or an
13350 * - The double-precision floating-point operand in register FRB is a Zero, a
13351 * NaN, or an Infinity.
13352 * - e_b is less than or equal to -1022.
13353 * - e_b is greater than or equal to 1021.
13354 * - The double-precision floating-point operand in register FRA is not a zero
13355 * and the difference, e_a - e_b, is greater than or equal to 1023.
13356 * - The double-precision floating-point operand in register FRA is not a zero
13357 * and the difference, e_a - e_b, is less than or equal to -1021.
13358 * - The double-precision floating-point operand in register FRA is not a zero
13359 * and e_a is less than or equal to -970
13360 * Otherwise fe_flag is set to 0.
13362 * fg_flag is set to 1 if either of the following conditions occurs.
13363 * - The double-precision floating-point operand in register FRA is an Infinity.
13364 * - The double-precision floating-point operand in register FRB is a Zero, an
13365 * Infinity, or a denormalized value.
13366 * Otherwise fg_flag is set to 0.
13369 static void _do_fp_tdiv(IRTemp frA_int
, IRTemp frB_int
, Bool sp
, IRTemp
* fe_flag_tmp
, IRTemp
* fg_flag_tmp
)
13371 // The following temps are for holding intermediate results
13372 IRTemp e_a
= newTemp(Ity_I32
);
13373 IRTemp e_b
= newTemp(Ity_I32
);
13374 IRTemp frA_exp_shR
= newTemp(Ity_I32
);
13375 IRTemp frB_exp_shR
= newTemp(Ity_I32
);
13377 UInt bias
= sp
? 127 : 1023;
13378 *fe_flag_tmp
= newTemp(Ity_I32
);
13379 *fg_flag_tmp
= newTemp(Ity_I32
);
13381 /* The following variables hold boolean results from tests
13382 * that are OR'ed together for setting the fe_ and fg_ flags.
13383 * For some cases, the booleans are used more than once, so
13384 * I make those IRTemp's instead of IRExpr's.
13386 IRExpr
* fraNaN
, * frbNaN
, * frbDenorm
;
13387 IRExpr
* eb_LTE
, * eb_GTE
, * ea_eb_GTE
, * ea_eb_LTE
, * ea_LTE
;
13388 IRTemp fraInf_tmp
= newTemp(Ity_I1
);
13389 IRTemp frbZero_tmp
= newTemp(Ity_I1
);
13390 IRTemp frbInf_tmp
= newTemp(Ity_I1
);
13391 IRTemp fraNotZero_tmp
= newTemp(Ity_I1
);
13393 /* The following are the flags that are set by OR'ing the results of
13394 * all the tests done for tdiv. These flags are the input to the specified CR.
13396 IRExpr
* fe_flag
, * fg_flag
;
13398 // Create temps that will be used throughout the following tests.
13400 assign( frA_exp_shR
, fp_exp_part( Ity_I32
, frA_int
) );
13401 assign( frB_exp_shR
, fp_exp_part( Ity_I32
, frB_int
) );
13403 assign( frA_exp_shR
, fp_exp_part( Ity_I64
, frA_int
) );
13404 assign( frB_exp_shR
, fp_exp_part( Ity_I64
, frB_int
) );
13407 /* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */
13408 assign(e_a
, binop( Iop_Sub32
, mkexpr(frA_exp_shR
), mkU32( bias
) ));
13409 assign(e_b
, binop( Iop_Sub32
, mkexpr(frB_exp_shR
), mkU32( bias
) ));
13412 ////////////////// fe_flag tests BEGIN //////////////////////
13413 /* We first do all tests that may result in setting fe_flag to '1'. */
13416 * Test if the double-precision floating-point operand in register FRA is
13419 fraNaN
= sp
? is_NaN( Ity_I32
, frA_int
) : is_NaN( Ity_I64
, frA_int
);
13421 * Test if the double-precision floating-point operands in register FRA
13422 * and FRB is an Infinity. Test if FRB is zero.
13425 assign(fraInf_tmp
, is_Inf( Ity_I32
, frA_int
) );
13426 assign( frbInf_tmp
, is_Inf( Ity_I32
, frB_int
) );
13427 assign( frbZero_tmp
, is_Zero( Ity_I32
, frB_int
) );
13430 assign(fraInf_tmp
, is_Inf( Ity_I64
, frA_int
) );
13431 assign( frbInf_tmp
, is_Inf( Ity_I64
, frB_int
) );
13432 assign( frbZero_tmp
, is_Zero( Ity_I64
, frB_int
) );
13435 * Test if the double-precision floating-point operand in register FRB is
13438 frbNaN
= sp
? is_NaN( Ity_I32
, frB_int
) : is_NaN( Ity_I64
, frB_int
);
13441 * Test if e_b <= -1022 for double precision;
13442 * or e_b <= -126 for single precision
13445 UInt test_value
= sp
? 0xffffff82 : 0xfffffc02;
13446 eb_LTE
= binop(Iop_CmpLE32S
, mkexpr(e_b
), mkU32(test_value
));
13450 * Test if e_b >= 1021 (i.e., 1021 < e_b) for double precision;
13451 * or e_b >= -125 (125 < e_b) for single precision
13454 Int test_value
= sp
? 125 : 1021;
13455 eb_GTE
= binop(Iop_CmpLT32S
, mkU32(test_value
), mkexpr(e_b
));
13459 * Test if FRA != Zero and (e_a - e_b) >= bias
13462 assign( fraNotZero_tmp
, unop( Iop_Not1
, is_Zero( Ity_I32
, frA_int
) ) );
13464 assign( fraNotZero_tmp
, unop( Iop_Not1
, is_Zero( Ity_I64
, frA_int
) ) );
13466 ea_eb_GTE
= mkAND1( mkexpr( fraNotZero_tmp
),
13467 binop( Iop_CmpLT32S
, mkU32( bias
),
13468 binop( Iop_Sub32
, mkexpr( e_a
),
13469 mkexpr( e_b
) ) ) );
13472 * Test if FRA != Zero and (e_a - e_b) <= [-1021 (double precision) or -125 (single precision)]
13475 UInt test_value
= sp
? 0xffffff83 : 0xfffffc03;
13477 ea_eb_LTE
= mkAND1( mkexpr( fraNotZero_tmp
),
13478 binop( Iop_CmpLE32S
,
13482 mkU32( test_value
) ) );
13486 * Test if FRA != Zero and e_a <= [-970 (double precision) or -103 (single precision)]
13489 UInt test_value
= 0xfffffc36; //Int test_value = -970;
13491 ea_LTE
= mkAND1( mkexpr( fraNotZero_tmp
), binop( Iop_CmpLE32S
,
13493 mkU32( test_value
) ) );
13495 ////////////////// fe_flag tests END //////////////////////
13497 ////////////////// fg_flag tests BEGIN //////////////////////
13499 * The following tests were already performed above in the fe_flag
13500 * tests. So these conditions will result in both fe_ and fg_ flags
13502 * - Test if FRA is an Infinity
13503 * - Test if FRB ix Zero
13504 * - Test if FRB is an Infinity
13508 * Test if FRB holds a denormalized value. A denormalized value is one where
13509 * the exp is 0 and the fraction is non-zero.
13512 IRExpr
* fraction_is_nonzero
;
13515 fraction_is_nonzero
= binop( Iop_CmpNE32
, FP_FRAC_PART32(frB_int
),
13518 IRExpr
* hi32
, * low32
;
13519 IRTemp frac_part
= newTemp(Ity_I64
);
13520 assign( frac_part
, FP_FRAC_PART(frB_int
) );
13522 hi32
= unop( Iop_64HIto32
, mkexpr( frac_part
) );
13523 low32
= unop( Iop_64to32
, mkexpr( frac_part
) );
13524 fraction_is_nonzero
= binop( Iop_CmpNE32
, binop( Iop_Or32
, low32
, hi32
),
13527 frbDenorm
= mkAND1( binop( Iop_CmpEQ32
, mkexpr( frB_exp_shR
),
13528 mkU32( 0x0 ) ), fraction_is_nonzero
);
13531 ////////////////// fg_flag tests END //////////////////////
13537 mkexpr( fraInf_tmp
),
13539 mkexpr( frbZero_tmp
),
13543 mkexpr( frbInf_tmp
),
13548 ea_LTE
) ) ) ) ) ) ) ) );
13550 fe_flag
= unop(Iop_1Uto32
, fe_flag
);
13552 fg_flag
= mkOR1( mkexpr( fraInf_tmp
), mkOR1( mkexpr( frbZero_tmp
),
13553 mkOR1( mkexpr( frbInf_tmp
),
13555 fg_flag
= unop(Iop_1Uto32
, fg_flag
);
13556 assign(*fe_flag_tmp
, fe_flag
);
13557 assign(*fg_flag_tmp
, fg_flag
);
13560 /* See description for _do_fp_tdiv() above. */
13561 static IRExpr
* do_fp_tdiv(IRTemp frA_int
, IRTemp frB_int
)
13563 IRTemp fe_flag
, fg_flag
;
13564 /////////////////////////
13565 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
13566 * where fl_flag == 1 on ppc64.
13568 IRExpr
* fl_flag
= unop(Iop_Not32
, mkU32(0xFFFFFE));
13569 fe_flag
= fg_flag
= IRTemp_INVALID
;
13570 _do_fp_tdiv(frA_int
, frB_int
, False
/*not single precision*/, &fe_flag
, &fg_flag
);
13571 return binop( Iop_Or32
,
13573 binop( Iop_Shl32
, fl_flag
, mkU8( 3 ) ),
13574 binop( Iop_Shl32
, mkexpr(fg_flag
), mkU8( 2 ) ) ),
13575 binop( Iop_Shl32
, mkexpr(fe_flag
), mkU8( 1 ) ) );
13578 static Bool
dis_fp_tests ( UInt prefix
, UInt theInstr
)
13580 UChar opc1
= ifieldOPC(theInstr
);
13581 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) );
13582 UChar frB_addr
= ifieldRegB(theInstr
);
13583 UChar b0
= ifieldBIT0(theInstr
);
13584 UInt opc2
= ifieldOPClo10(theInstr
);
13585 IRTemp frB_I64
= newTemp(Ity_I64
);
13587 /* There is no prefixed version of these instructions. */
13590 if (opc1
!= 0x3F || b0
!= 0 ){
13591 vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
13594 assign( frB_I64
, unop( Iop_ReinterpF64asI64
, getFReg( frB_addr
) ) );
13597 case 0x080: // ftdiv
13599 UChar frA_addr
= ifieldRegA(theInstr
);
13600 IRTemp frA_I64
= newTemp(Ity_I64
);
13601 UChar b21to22
= toUChar( IFIELD( theInstr
, 21, 2 ) );
13602 if (b21to22
!= 0 ) {
13603 vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
13607 assign( frA_I64
, unop( Iop_ReinterpF64asI64
, getFReg( frA_addr
) ) );
13608 putGST_field( PPC_GST_CR
, do_fp_tdiv(frA_I64
, frB_I64
), crfD
);
13610 DIP("ftdiv crf%d,fr%u,fr%u\n", crfD
, frA_addr
, frB_addr
);
13613 case 0x0A0: // ftsqrt
13615 IRTemp flags
= newTemp(Ity_I32
);
13616 IRTemp fe_flag
, fg_flag
;
13617 fe_flag
= fg_flag
= IRTemp_INVALID
;
13618 UChar b18to22
= toUChar( IFIELD( theInstr
, 18, 5 ) );
13619 if ( b18to22
!= 0) {
13620 vex_printf("dis_fp_tests(ppc)(ftsqrt)\n");
13623 DIP("ftsqrt crf%d,fr%u\n", crfD
, frB_addr
);
13624 do_fp_tsqrt(frB_I64
, False
/* not single precision*/, &fe_flag
, &fg_flag
);
13625 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
13626 * where fl_flag == 1 on ppc64.
13630 binop( Iop_Or32
, mkU32( 8 ), // fl_flag
13631 binop( Iop_Shl32
, mkexpr(fg_flag
), mkU8( 2 ) ) ),
13632 binop( Iop_Shl32
, mkexpr(fe_flag
), mkU8( 1 ) ) ) );
13633 putGST_field( PPC_GST_CR
, mkexpr(flags
), crfD
);
13638 vex_printf("dis_fp_tests(ppc)(opc2)\n");
13646 Floating Point Compare Instructions
13648 static Bool
dis_fp_cmp ( UInt prefix
, UInt theInstr
)
13651 UChar opc1
= ifieldOPC(theInstr
);
13652 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) );
13653 UChar b21to22
= toUChar( IFIELD( theInstr
, 21, 2 ) );
13654 UChar frA_addr
= ifieldRegA(theInstr
);
13655 UChar frB_addr
= ifieldRegB(theInstr
);
13656 UInt opc2
= ifieldOPClo10(theInstr
);
13657 UChar b0
= ifieldBIT0(theInstr
);
13659 IRTemp ccIR
= newTemp(Ity_I32
);
13660 IRTemp ccPPC32
= newTemp(Ity_I32
);
13662 IRTemp frA
= newTemp(Ity_F64
);
13663 IRTemp frB
= newTemp(Ity_F64
);
13665 /* There is no prefixed version of these instructions. */
13668 if (opc1
!= 0x3F || b21to22
!= 0 || b0
!= 0) {
13669 vex_printf("dis_fp_cmp(ppc)(instr)\n");
13673 assign( frA
, getFReg(frA_addr
));
13674 assign( frB
, getFReg(frB_addr
));
13676 assign( ccIR
, binop(Iop_CmpF64
, mkexpr(frA
), mkexpr(frB
)) );
13678 /* Map compare result from IR to PPC32 */
13680 FP cmp result | PPC | IR
13681 --------------------------
13688 // ccPPC32 = Shl(1, (~(ccIR>>5) & 2)
13689 // | ((ccIR ^ (ccIR>>6)) & 1)
13703 binop(Iop_Shr32
, mkexpr(ccIR
), mkU8(5))
13712 binop(Iop_Shr32
, mkexpr(ccIR
), mkU8(6))
13721 putGST_field( PPC_GST_CR
, mkexpr(ccPPC32
), crfD
);
13722 putFPCC( mkexpr( ccPPC32
) );
13724 // XXX XXX XXX FIXME
13725 // Also write the result into FPRF (it's not entirely clear how)
13727 /* Note: Differences between fcmpu and fcmpo are only in exception
13728 flag settings, which aren't supported anyway. */
13730 case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403)
13731 DIP("fcmpu crf%d,fr%u,fr%u\n", crfD
, frA_addr
, frB_addr
);
13733 case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402)
13734 DIP("fcmpo crf%d,fr%u,fr%u\n", crfD
, frA_addr
, frB_addr
);
13737 vex_printf("dis_fp_cmp(ppc)(opc2)\n");
13746 Floating Point Rounding/Conversion Instructions
13748 static Bool
dis_fp_round ( UInt prefix
, UInt theInstr
)
13751 UChar opc1
= ifieldOPC(theInstr
);
13752 UChar b16to20
= ifieldRegA(theInstr
);
13753 UChar frD_addr
= ifieldRegDS(theInstr
);
13754 UChar frB_addr
= ifieldRegB(theInstr
);
13755 UInt opc2
= ifieldOPClo10(theInstr
);
13756 UChar flag_rC
= ifieldBIT0(theInstr
);
13758 IRTemp frD
= newTemp(Ity_F64
);
13759 IRTemp frB
= newTemp(Ity_F64
);
13760 IRTemp r_tmp32
= newTemp(Ity_I32
);
13761 IRTemp r_tmp64
= newTemp(Ity_I64
);
13762 IRExpr
* rm
= get_IR_roundingmode();
13764 /* By default, we will examine the results of the operation and set
13765 fpscr[FPRF] accordingly. */
13766 Bool set_FPRF
= True
;
13768 /* By default, if flag_RC is set, we will clear cr1 after the
13769 operation. In reality we should set cr1 to indicate the
13770 exception status of the operation, but since we're not
13771 simulating exceptions, the exception status will appear to be
13772 zero. Hence cr1 should be cleared if this is a . form insn. */
13773 Bool clear_CR1
= True
;
13775 /* There is no prefixed version of these instructions. */
13778 if ((!(opc1
== 0x3F || opc1
== 0x3B)) || b16to20
!= 0) {
13779 vex_printf("dis_fp_round(ppc)(instr)\n");
13783 assign( frB
, getFReg(frB_addr
));
13784 if (opc1
== 0x3B) {
13785 /* The fcfid[u]s instructions (from ISA 2.06) are a bit odd because
13786 * they're very similar to the other instructions handled here, but have
13787 * a different primary opcode.
13790 case 0x34E: // fcfids (Float convert from signed DWord to single precision)
13791 DIP("fcfids%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
13792 assign( r_tmp64
, unop( Iop_ReinterpF64asI64
, mkexpr(frB
)) );
13793 assign( frD
, binop( Iop_RoundF64toF32
, rm
, binop( Iop_I64StoF64
, rm
,
13794 mkexpr( r_tmp64
) ) ) );
13797 case 0x3Ce: // fcfidus (Float convert from unsigned DWord to single precision)
13798 DIP("fcfidus%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
13799 assign( r_tmp64
, unop( Iop_ReinterpF64asI64
, mkexpr(frB
)) );
13800 assign( frD
, unop( Iop_F32toF64
, binop( Iop_I64UtoF32
, rm
, mkexpr( r_tmp64
) ) ) );
13808 case 0x00C: // frsp (Float Round to Single, PPC32 p423)
13809 DIP("frsp%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
13810 assign( frD
, binop( Iop_RoundF64toF32
, rm
, mkexpr(frB
) ));
13813 case 0x00E: // fctiw (Float Conv to Int, PPC32 p404)
13814 DIP("fctiw%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
13816 binop(Iop_F64toI32S
, rm
, mkexpr(frB
)) );
13817 assign( frD
, unop( Iop_ReinterpI64asF64
,
13818 unop( Iop_32Uto64
, mkexpr(r_tmp32
))));
13819 /* FPRF is undefined after fctiw. Leave unchanged. */
13823 case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405)
13824 DIP("fctiwz%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
13826 binop(Iop_F64toI32S
, mkU32(Irrm_ZERO
), mkexpr(frB
) ));
13827 assign( frD
, unop( Iop_ReinterpI64asF64
,
13828 unop( Iop_32Uto64
, mkexpr(r_tmp32
))));
13829 /* FPRF is undefined after fctiwz. Leave unchanged. */
13833 case 0x08F: case 0x08E: // fctiwu[z]
13834 DIP("fctiwu%s%s fr%u,fr%u\n", opc2
== 0x08F ? "z" : "",
13835 flag_rC
? ".":"", frD_addr
, frB_addr
);
13837 binop( Iop_F64toI32U
,
13838 opc2
== 0x08F ? mkU32( Irrm_ZERO
) : rm
,
13840 assign( frD
, unop( Iop_ReinterpI64asF64
,
13841 unop( Iop_32Uto64
, mkexpr(r_tmp32
))));
13842 /* FPRF is undefined after fctiwz. Leave unchanged. */
13847 case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437)
13848 DIP("fctid%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
13850 binop(Iop_F64toI64S
, rm
, mkexpr(frB
)) );
13851 assign( frD
, unop( Iop_ReinterpI64asF64
, mkexpr(r_tmp64
)) );
13852 /* FPRF is undefined after fctid. Leave unchanged. */
13856 case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437)
13857 DIP("fctidz%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
13859 binop(Iop_F64toI64S
, mkU32(Irrm_ZERO
), mkexpr(frB
)) );
13860 assign( frD
, unop( Iop_ReinterpI64asF64
, mkexpr(r_tmp64
)) );
13861 /* FPRF is undefined after fctidz. Leave unchanged. */
13865 case 0x3AE: case 0x3AF: // fctidu[z] (Float Conv to Int DWord Unsigned [Round to Zero])
13867 DIP("fctidu%s%s fr%u,fr%u\n", opc2
== 0x3AE ? "" : "z",
13868 flag_rC
? ".":"", frD_addr
, frB_addr
);
13870 binop(Iop_F64toI64U
, opc2
== 0x3AE ? rm
: mkU32(Irrm_ZERO
), mkexpr(frB
)) );
13871 assign( frD
, unop( Iop_ReinterpI64asF64
, mkexpr(r_tmp64
)) );
13872 /* FPRF is undefined after fctidz. Leave unchanged. */
13876 case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434)
13877 DIP("fcfid%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
13878 assign( r_tmp64
, unop( Iop_ReinterpF64asI64
, mkexpr(frB
)) );
13880 binop(Iop_I64StoF64
, rm
, mkexpr(r_tmp64
)) );
13883 case 0x3CE: // fcfidu (Float convert from unsigned DWord)
13884 DIP("fcfidu%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
13885 assign( r_tmp64
, unop( Iop_ReinterpF64asI64
, mkexpr(frB
)) );
13886 assign( frD
, binop( Iop_I64UtoF64
, rm
, mkexpr( r_tmp64
) ) );
13889 case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim
13891 case 0x188: // frin (Floating Round to Integer Nearest)
13892 DIP("frin%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
13894 binop(Iop_F64toI64S
, mkU32(Irrm_NEAREST
), mkexpr(frB
)) );
13896 case 0x1A8: // friz (Floating Round to Integer Toward Zero)
13897 DIP("friz%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
13899 binop(Iop_F64toI64S
, mkU32(Irrm_ZERO
), mkexpr(frB
)) );
13901 case 0x1C8: // frip (Floating Round to Integer Plus)
13902 DIP("frip%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
13904 binop(Iop_F64toI64S
, mkU32(Irrm_PosINF
), mkexpr(frB
)) );
13906 case 0x1E8: // frim (Floating Round to Integer Minus)
13907 DIP("frim%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
13909 binop(Iop_F64toI64S
, mkU32(Irrm_NegINF
), mkexpr(frB
)) );
13913 /* don't use the rounded integer if frB is outside -9e18..9e18 */
13914 /* F64 has only log10(2**52) significant digits anyway */
13915 /* need to preserve sign of zero */
13916 /* frD = (fabs(frB) > 9e18) ? frB :
13917 (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64 */
13918 assign(frD
, IRExpr_ITE(
13922 IRExpr_Const(IRConst_F64(9e18
)),
13923 unop(Iop_AbsF64
, mkexpr(frB
)))),
13930 unop(Iop_ReinterpF64asI64
,
13936 binop(Iop_I64StoF64
, mkU32(0),
13937 mkexpr(r_tmp64
)) )),
13938 binop(Iop_I64StoF64
, mkU32(0), mkexpr(r_tmp64
) )
13944 vex_printf("dis_fp_round(ppc)(opc2)\n");
13948 putFReg( frD_addr
, mkexpr(frD
) );
13951 // XXX XXX XXX FIXME
13952 // set FPRF from frD
13955 if (flag_rC
&& clear_CR1
) {
13956 putCR321( 1, mkU8(0) );
13957 putCR0( 1, mkU8(0) );
13964 Floating Point Pair Instructions
13966 static Bool
dis_fp_pair_prefix ( UInt prefix
, UInt theInstr
)
13968 /* X-Form/DS-Form */
13969 UChar opc1
= ifieldOPC(theInstr
);
13970 UChar rA_addr
= ifieldRegA(theInstr
);
13971 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
13972 IRTemp EA
= newTemp(ty
);
13973 IRTemp EA_16
= newTemp(ty
);
13974 UInt ptype
= PrefixType(prefix
);
13975 Bool is_prefix
= prefix_instruction( prefix
);
13977 ULong immediate_val
= 0;
13983 UChar XTp
= ifieldRegXTp(theInstr
);
13984 opc2
= ifieldOPClo4(theInstr
);
13986 assign( EA
, calculate_prefix_EA( prefix
, theInstr
,
13987 rA_addr
, ptype
, DQFORM_IMMASK
,
13988 &immediate_val
, &R
) );
13994 /* Endian aware load */
13995 DIP( "lxvp %u,%llu(%u)\n", XTp
, immediate_val
, rA_addr
);
13997 // address of next 128bits
13998 assign( EA_16
, binop( Iop_Add64
, mkU64( 16 ), mkexpr( EA
) ) );
13999 if (host_endness
== VexEndnessBE
) {
14000 putVSReg( XTp
, load( Ity_V128
, mkexpr( EA
) ) );
14001 putVSReg( XTp
+1, load( Ity_V128
, mkexpr( EA_16
) ) );
14003 putVSReg( XTp
+1, load( Ity_V128
, mkexpr( EA
) ) );
14004 putVSReg( XTp
, load( Ity_V128
, mkexpr( EA_16
) ) );
14011 IRTemp EA_8
= newTemp(ty
);
14012 IRTemp EA_24
= newTemp(ty
);
14013 /* Endian aware store */
14014 DIP("stxvp %u,%llu(%u)\n", XTp
, immediate_val
, rA_addr
);
14016 // address of next 128bits
14017 assign( EA_8
, binop( Iop_Add64
, mkU64( 8 ), mkexpr( EA
) ) );
14018 assign( EA_16
, binop( Iop_Add64
, mkU64( 16 ), mkexpr( EA
) ) );
14019 assign( EA_24
, binop( Iop_Add64
, mkU64( 24 ), mkexpr( EA
) ) );
14021 if (host_endness
== VexEndnessBE
) {
14022 store( mkexpr( EA
), unop( Iop_V128to64
, getVSReg( XTp
) ) );
14023 store( mkexpr( EA_8
), unop( Iop_V128HIto64
, getVSReg( XTp
) ) );
14024 store( mkexpr( EA_16
), unop( Iop_V128to64
, getVSReg( XTp
+1 ) ) );
14025 store( mkexpr( EA_24
), unop( Iop_V128HIto64
, getVSReg( XTp
+1 ) ) );
14027 store( mkexpr( EA
), unop( Iop_V128to64
, getVSReg( XTp
+1 ) ) );
14028 store( mkexpr( EA_8
), unop( Iop_V128HIto64
, getVSReg( XTp
+1 ) ) );
14029 store( mkexpr( EA_16
), unop( Iop_V128to64
, getVSReg( XTp
) ) );
14030 store( mkexpr( EA_24
), unop( Iop_V128HIto64
, getVSReg( XTp
) ) );
14036 vex_printf("dis_fp_pair_prefix\n");
14043 case 0x2A: // plxsd
14045 UChar vRT
= ifieldRegDS(theInstr
);
14046 /* The prefixed word version uses the D-form. */
14047 assign( EA
, calculate_prefix_EA( prefix
, theInstr
, rA_addr
,
14048 ptype
, DFORM_IMMASK
,
14049 &immediate_val
, &R
) );
14051 pDIP( is_prefix
, "lxsd v%u,%llu(r%u)\n", vRT
, immediate_val
, rA_addr
);
14052 DIPp( is_prefix
, ",%u", R
);
14054 putVSReg( vRT
+32, binop( Iop_64HLtoV128
,
14055 load( Ity_I64
, mkexpr( EA
) ),
14060 case 0x2B: // plxssp
14062 UChar vRT
= ifieldRegDS(theInstr
);
14063 /* The prefixed word version uses the D-form. */
14064 assign( EA
, calculate_prefix_EA( prefix
, theInstr
, rA_addr
,
14065 ptype
, DFORM_IMMASK
,
14066 &immediate_val
, &R
) );
14069 pDIP( is_prefix
, "lxssp v%u,%llu(r%u)\n", vRT
, immediate_val
, rA_addr
);
14070 DIPp( is_prefix
, ",%u", R
);
14072 binop( Iop_64HLtoV128
,
14073 unop( Iop_ReinterpF64asI64
,
14074 unop( Iop_F32toF64
,
14075 unop( Iop_ReinterpI32asF32
,
14076 load( Ity_I32
, mkexpr( EA
) )
14082 case 0x32: // plxv0
14083 case 0x33: // plxv1 These are both plxv, but bit 5 is used for TX
14088 UChar vRS
= ifieldRegDS(theInstr
);
14089 UInt T
= IFIELD( theInstr
, 21, 5);
14090 UInt TX
= IFIELD( theInstr
, 26, 1);
14093 calculate_prefix_EA( prefix
, theInstr
, rA_addr
, ptype
,
14094 DFORM_IMMASK
, &immediate_val
, &R
) );
14096 // plxv (Load VSX Vector)
14097 pDIP( is_prefix
, "lxv v%u,%llu(r%u)\n", vRS
, immediate_val
, rA_addr
);
14098 DIPp( is_prefix
, ",%u", R
);
14100 word
[0] = newTemp(Ity_I64
);
14101 assign( word
[0], load( Ity_I64
, mkexpr( EA
) ) );
14103 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
14104 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
14106 word
[1] = newTemp(Ity_I64
);
14107 assign( word
[1], load( Ity_I64
, irx_addr
) );
14109 if (host_endness
== VexEndnessBE
)
14110 putVSReg( TX
*32+T
, binop( Iop_64HLtoV128
,
14112 mkexpr( word
[1] ) ) );
14114 putVSReg( TX
*32+T
, binop( Iop_64HLtoV128
,
14116 mkexpr( word
[0] ) ) );
14121 case 0x39: // lxsd, plxsd, lxssp, plxssp
14123 UChar vRT
= ifieldRegDS(theInstr
);
14124 opc2
= ifieldOPC0o2(theInstr
);
14126 if (opc1
== 0x2A) { // plxsd
14127 opc2
= 0x2; // map plxsd to lxsd inst
14128 /* The prefixed word version uses the D-form. */
14129 assign( EA
, calculate_prefix_EA( prefix
, theInstr
, rA_addr
,
14130 ptype
, DFORM_IMMASK
,
14131 &immediate_val
, &R
) );
14133 } else if (opc1
== 0x2B) { // plxssp
14134 opc2
= 0x3; // map plxssp to lxssp inst
14135 /* The prefixed word version uses the D-form. */
14136 assign( EA
, calculate_prefix_EA( prefix
, theInstr
, rA_addr
,
14137 ptype
, DFORM_IMMASK
,
14138 &immediate_val
, &R
) );
14140 /* The word version uses the DS-form. */
14141 assign( EA
, calculate_prefix_EA( prefix
, theInstr
, rA_addr
,
14142 ptype
, DSFORM_IMMASK
,
14143 &immediate_val
, &R
) );
14147 case 0x2: // lxsd, plxsd (Load VSX Scalar Doubleword)
14149 pDIP( is_prefix
, "lxsd v%u,%llu(r%u)\n", vRT
, immediate_val
,
14151 DIPp( is_prefix
, ",%u", R
);
14152 putVSReg( vRT
+32, binop( Iop_64HLtoV128
,
14153 load( Ity_I64
, mkexpr( EA
) ),
14159 case 0x3: // lxssp (Load VSX Scalar Single from memory,
14160 // store as double in register)
14161 pDIP( is_prefix
, "lxssp v%u,%llu(r%u)\n", vRT
, immediate_val
,
14163 DIPp( is_prefix
, ",%u", R
);
14166 binop( Iop_64HLtoV128
,
14167 unop( Iop_ReinterpF64asI64
,
14168 unop( Iop_F32toF64
,
14169 unop( Iop_ReinterpI32asF32
,
14170 load( Ity_I32
, mkexpr( EA
) )
14176 vex_printf("dis_fp_pair_prefix(ppc) : DS-form wrong opc2\n");
14182 case 0x2E: // pstxsd
14184 // pstxsd (Store VSX Scalar Doubleword)
14185 UChar vRS
= ifieldRegDS(theInstr
);
14187 assign( EA
, calculate_prefix_EA( prefix
, theInstr
,
14188 rA_addr
, ptype
, DFORM_IMMASK
,
14189 &immediate_val
, &R
) );
14190 pDIP( is_prefix
, "stxsd v%u,%llu(r%u)\n", vRS
, immediate_val
, rA_addr
);
14191 DIPp( is_prefix
, ",%u", R
);
14192 store( mkexpr(EA
), unop( Iop_V128HIto64
,
14193 getVSReg( vRS
+32 ) ) );
14194 /* HW is clearing vector element 1. Don't see that in the ISA but
14197 putVSReg( vRS
+32, binop( Iop_64HLtoV128
,
14198 unop( Iop_V128HIto64
,
14199 getVSReg( vRS
+32 ) ),
14207 // pstxssp (Store VSX Scalar Single - store double precision
14208 // value from register into memory in single precision format)
14209 UChar vRS
= ifieldRegDS(theInstr
);
14210 IRTemp high64
= newTemp(Ity_F64
);
14211 IRTemp val32
= newTemp(Ity_I32
);
14213 assign( EA
, calculate_prefix_EA( prefix
, theInstr
,
14214 rA_addr
, ptype
, DFORM_IMMASK
,
14215 &immediate_val
, &R
) );
14216 pDIP( is_prefix
, "stxssp v%u,%llu(r%u)\n", vRS
, immediate_val
, rA_addr
);
14217 DIPp( is_prefix
, ",%u", R
);
14219 assign(high64
, unop( Iop_ReinterpI64asF64
,
14220 unop( Iop_V128HIto64
, getVSReg( vRS
+32 ) ) ) );
14222 assign(val32
, unop( Iop_ReinterpF32asI32
,
14223 unop( Iop_TruncF64asF32
,
14224 mkexpr(high64
) ) ) );
14225 store( mkexpr(EA
), mkexpr( val32
) );
14236 UChar vRS
= ifieldRegDS(theInstr
);
14237 UInt T
= IFIELD( theInstr
, 21, 5);
14238 UInt TX
= IFIELD( theInstr
, 3, 1);
14240 opc2
= IFIELD(theInstr
, 0, 3);
14242 if ( IFIELD( theInstr
, 0, 3) == 1) {
14243 // lxv (Load VSX Vector)
14244 assign( EA
, calculate_prefix_EA( prefix
, theInstr
,
14245 rA_addr
, ptype
, DQFORM_IMMASK
,
14246 &immediate_val
, &R
) );
14248 DIP("lxv v%u,%llu(r%u)\n", vRS
, immediate_val
, rA_addr
);
14249 word
[0] = newTemp(Ity_I64
);
14250 assign( word
[0], load( Ity_I64
, mkexpr( EA
) ) );
14252 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
14253 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
14254 word
[1] = newTemp(Ity_I64
);
14255 assign( word
[1], load( Ity_I64
, irx_addr
) );
14257 if (host_endness
== VexEndnessBE
)
14258 putVSReg( TX
*32+T
, binop( Iop_64HLtoV128
,
14260 mkexpr( word
[1] ) ) );
14262 putVSReg( TX
*32+T
, binop( Iop_64HLtoV128
,
14264 mkexpr( word
[0] ) ) );
14267 } else if ((opc2
& 0x3) == 0x2) {
14268 // stxsd (Store VSX Scalar Doubleword)
14269 R
= 0; // must be zero for word instruction
14270 assign( EA
, calculate_prefix_EA( prefix
, theInstr
,
14271 rA_addr
, ptype
, DSFORM_IMMASK
,
14272 &immediate_val
, &R
) );
14274 DIP("stxsd v%u,%llu(r%u)\n", vRS
, immediate_val
, rA_addr
);
14275 store( mkexpr(EA
), unop( Iop_V128HIto64
,
14276 getVSReg( vRS
+32 ) ) );
14277 /* HW is clearing vector element 1. Don't see that in the ISA but
14280 putVSReg( vRS
+32, binop( Iop_64HLtoV128
,
14281 unop( Iop_V128HIto64
,
14282 getVSReg( vRS
+32 ) ),
14286 } else if ((opc2
& 0x3) == 0x3) {
14287 // stxssp (Store VSX Scalar Single - store double precision
14288 // value from register into memory in single precision format)
14289 IRTemp high64
= newTemp(Ity_F64
);
14290 IRTemp val32
= newTemp(Ity_I32
);
14293 calculate_prefix_EA( prefix
, theInstr
, rA_addr
, ptype
,
14294 DSFORM_IMMASK
, &immediate_val
, &R
) );
14295 DIP("stxssp v%u,%llu(r%u)\n", vRS
, immediate_val
, rA_addr
);
14296 assign(high64
, unop( Iop_ReinterpI64asF64
,
14297 unop( Iop_V128HIto64
, getVSReg( vRS
+32 ) ) ) );
14299 assign(val32
, unop( Iop_ReinterpF32asI32
,
14300 unop( Iop_TruncF64asF32
,
14301 mkexpr(high64
) ) ) );
14302 store( mkexpr(EA
), mkexpr( val32
) );
14306 } else if (opc2
== 0x5) {
14307 // stxv (Store VSX Vector)
14308 assign( EA
, calculate_prefix_EA( prefix
, theInstr
,
14309 rA_addr
, ptype
, DQFORM_IMMASK
,
14310 &immediate_val
, &R
) );
14311 DIP("stxv v%u,%llu(r%u)\n", vRS
, immediate_val
, rA_addr
);
14313 if (host_endness
== VexEndnessBE
) {
14314 store( mkexpr(EA
), unop( Iop_V128HIto64
,
14315 getVSReg( TX
*32+T
) ) );
14317 = binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
14318 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
14319 store( irx_addr
, unop( Iop_V128to64
,
14320 getVSReg( TX
*32+T
) ) );
14322 store( mkexpr(EA
), unop( Iop_V128to64
,
14323 getVSReg( TX
*32+T
) ) );
14325 = binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
14326 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
14327 store( irx_addr
, unop( Iop_V128HIto64
,
14328 getVSReg( TX
*32+T
) ) );
14333 vex_printf("dis_fp_pair vector load/store (ppc) : DS-form wrong opc2\n");
14339 case 0x3A: // plxvp
14341 UChar XTp
= ifieldRegXTp(theInstr
);
14343 assign( EA
, calculate_prefix_EA( prefix
, theInstr
,
14344 rA_addr
, ptype
, DFORM_IMMASK
,
14345 &immediate_val
, &R
) );
14347 /* Endian aware prefixed load */
14348 pDIP( is_prefix
, "lxvp %u,%llu(%u)", XTp
, immediate_val
, rA_addr
);
14349 DIPp( is_prefix
, ",%u", R
);
14351 // address of next 128bits
14352 assign( EA_16
, binop( Iop_Add64
, mkU64( 16 ), mkexpr( EA
) ) );
14353 if (host_endness
== VexEndnessBE
) {
14354 putVSReg( XTp
, load( Ity_V128
, mkexpr( EA
) ) );
14355 putVSReg( XTp
+1, load( Ity_V128
, mkexpr( EA_16
) ) );
14357 putVSReg( XTp
+1, load( Ity_V128
, mkexpr( EA
) ) );
14358 putVSReg( XTp
, load( Ity_V128
, mkexpr( EA_16
) ) );
14363 case 0x3E: // pstxvp
14365 IRTemp EA_8
= newTemp(ty
);
14366 IRTemp EA_24
= newTemp(ty
);
14367 UChar XTp
= ifieldRegXTp(theInstr
);
14369 assign( EA
, calculate_prefix_EA( prefix
, theInstr
,
14370 rA_addr
, ptype
, DFORM_IMMASK
,
14371 &immediate_val
, &R
) );
14373 /* Endian aware prefixed load */
14374 pDIP( is_prefix
, "stxvp %u,%llu(%u)\n", XTp
, immediate_val
, rA_addr
);
14375 DIPp( is_prefix
, ",%u", R
);
14377 assign( EA_8
, binop( Iop_Add64
, mkU64( 8 ), mkexpr( EA
) ) );
14378 assign( EA_16
, binop( Iop_Add64
, mkU64( 16 ), mkexpr( EA
) ) );
14379 assign( EA_24
, binop( Iop_Add64
, mkU64( 24 ), mkexpr( EA
) ) );
14381 if (host_endness
== VexEndnessBE
) {
14382 store( mkexpr( EA
), unop( Iop_V128to64
, getVSReg( XTp
) ) );
14383 store( mkexpr( EA_8
), unop( Iop_V128HIto64
, getVSReg( XTp
) ) );
14384 store( mkexpr( EA_16
), unop( Iop_V128to64
, getVSReg( XTp
+1 ) ) );
14385 store( mkexpr( EA_24
), unop( Iop_V128HIto64
, getVSReg( XTp
+1 ) ) );
14387 store( mkexpr( EA
), unop( Iop_V128to64
, getVSReg( XTp
+1 ) ) );
14388 store( mkexpr( EA_8
), unop( Iop_V128HIto64
, getVSReg( XTp
+1 ) ) );
14389 store( mkexpr( EA_16
), unop( Iop_V128to64
, getVSReg( XTp
) ) );
14390 store( mkexpr( EA_24
), unop( Iop_V128HIto64
, getVSReg( XTp
) ) );
14395 case 0x36: // pstxv0
14396 case 0x37: // pstxv1, pstxv inst where bit 5 is SX
14398 // pstxv (Prefixed store VSX Vector 1 8LS:D-form)
14399 // AKA pstxv0, pstxv1
14400 UInt S
= IFIELD( theInstr
, 21, 5);
14401 UInt SX
= IFIELD( theInstr
, 26, 1);
14403 UChar vRS
= ifieldRegDS(theInstr
);
14404 IRTemp tmpV128
= newTemp(Ity_V128
);
14408 DIP("pstxv v%u,%llu(r%u)", vRS
, immediate_val
, rA_addr
);
14409 DIPp( is_prefix
, ",%u", R
);
14411 assign( tmpV128
, getVSReg( XS
) );
14414 calculate_prefix_EA( prefix
, theInstr
,
14415 rA_addr
, ptype
, DFORM_IMMASK
,
14416 &immediate_val
, &R
) );
14418 if (host_endness
== VexEndnessBE
) {
14419 store( mkexpr(EA
), unop( Iop_V128HIto64
,
14420 mkexpr( tmpV128
) ) );
14421 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
14422 ty
== Ity_I64
? mkU64( ea_off
):
14424 store( irx_addr
, unop( Iop_V128to64
,
14425 mkexpr( tmpV128
) ) );
14428 store( mkexpr(EA
), unop( Iop_V128to64
,
14429 mkexpr( tmpV128
) ) );
14430 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
14431 ty
== Ity_I64
? mkU64( ea_off
):
14433 store( irx_addr
, unop( Iop_V128HIto64
,
14434 mkexpr( tmpV128
) ) );
14440 vex_printf("dis_fp_pair_prefix(ppc)(instr)\n");
14446 static Bool
dis_fp_pair ( UInt prefix
, UInt theInstr
)
14448 /* X-Form/DS-Form */
14449 UChar opc1
= ifieldOPC(theInstr
);
14450 UChar frT_hi_addr
= ifieldRegDS(theInstr
);
14451 UChar frT_lo_addr
= frT_hi_addr
+ 1;
14452 UChar rA_addr
= ifieldRegA(theInstr
);
14453 UChar rB_addr
= ifieldRegB(theInstr
);
14454 UInt uimm16
= ifieldUIMM16(theInstr
);
14455 Int simm16
= extend_s_16to32(uimm16
);
14456 UInt opc2
= ifieldOPClo10(theInstr
);
14457 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
14458 IRTemp EA_hi
= newTemp(ty
);
14459 IRTemp EA_lo
= newTemp(ty
);
14460 IRTemp frT_hi
= newTemp(Ity_F64
);
14461 IRTemp frT_lo
= newTemp(Ity_F64
);
14462 UChar b0
= ifieldBIT0(theInstr
);
14465 /* There is no prefixed version of these instructions. */
14469 case 0x1F: // register offset
14470 /* These instructions work on a pair of registers. The specified
14471 * register must be even.
14473 if ((frT_hi_addr
%2) != 0) {
14474 vex_printf("dis_fp_pair(ppc) ldpx or stdpx: odd frT register\n");
14479 case 0x317: // lfdpx (FP Load Double Pair X-form, ISA 2.05 p125)
14480 DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr
, rA_addr
, rB_addr
);
14483 case 0x397: // stfdpx (FP STORE Double Pair X-form, ISA 2.05 p125)
14484 DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr
, rA_addr
, rB_addr
);
14487 vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n");
14492 vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n");
14495 assign( EA_hi
, ea_rAor0_idxd( rA_addr
, rB_addr
) );
14499 opc2
= ifieldOPC0o2(theInstr
);
14502 case 0x0: // lfdp (FP Load Double Pair DS-form, ISA 2.05 p125)
14503 /* This instruction works on a pair of registers. The specified
14504 * register must be even.
14506 if ((frT_hi_addr
%2) != 0) {
14507 vex_printf("dis_fp_pair(ppc) lfdp : odd frT register\n");
14511 DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr
, simm16
, rA_addr
);
14512 assign( EA_hi
, ea_rAor0_simm( rA_addr
, simm16
) );
14517 vex_printf("dis_fp_pair(ppc) : DS-form wrong opc2\n");
14524 opc2
= ifieldOPC0o2(theInstr
);
14528 // stfdp (FP Store Double Pair DS-form, ISA 2.05 p125)
14529 /* This instruction works on a pair of registers. The specified
14530 * register must be even.
14532 if ((frT_hi_addr
%2) != 0) {
14533 vex_printf("dis_fp_pair(ppc) stfdp : odd frT register\n");
14537 DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr
, simm16
, rA_addr
);
14538 assign( EA_hi
, ea_rAor0_simm( rA_addr
, simm16
) );
14542 vex_printf("dis_fp_pair(ppc) : DS-form wrong opc2\n");
14547 default: // immediate offset
14548 vex_printf("dis_fp_pair(ppc)(instr)\n");
14553 assign( EA_lo
, binop(Iop_Add64
, mkexpr(EA_hi
), mkU64(8)) );
14555 assign( EA_lo
, binop(Iop_Add32
, mkexpr(EA_hi
), mkU32(8)) );
14557 assign( frT_hi
, getFReg(frT_hi_addr
) );
14558 assign( frT_lo
, getFReg(frT_lo_addr
) );
14561 putFReg( frT_hi_addr
, load(Ity_F64
, mkexpr(EA_hi
)) );
14562 putFReg( frT_lo_addr
, load(Ity_F64
, mkexpr(EA_lo
)) );
14564 store( mkexpr(EA_hi
), mkexpr(frT_hi
) );
14565 store( mkexpr(EA_lo
), mkexpr(frT_lo
) );
14573 Floating Point Merge Instructions
14575 static Bool
dis_fp_merge ( UInt prefix
, UInt theInstr
)
14578 UInt opc2
= ifieldOPClo10(theInstr
);
14579 UChar frD_addr
= ifieldRegDS(theInstr
);
14580 UChar frA_addr
= ifieldRegA(theInstr
);
14581 UChar frB_addr
= ifieldRegB(theInstr
);
14583 IRTemp frD
= newTemp(Ity_F64
);
14584 IRTemp frA
= newTemp(Ity_F64
);
14585 IRTemp frB
= newTemp(Ity_F64
);
14587 /* There is no prefixed version of these instructions. */
14590 assign( frA
, getFReg(frA_addr
));
14591 assign( frB
, getFReg(frB_addr
));
14594 case 0x3c6: // fmrgew floating merge even word
14595 DIP("fmrgew fr%u,fr%u,fr%u\n", frD_addr
, frA_addr
, frB_addr
);
14597 assign( frD
, unop( Iop_ReinterpI64asF64
,
14598 binop( Iop_32HLto64
,
14599 unop( Iop_64HIto32
,
14600 unop( Iop_ReinterpF64asI64
,
14602 unop( Iop_64HIto32
,
14603 unop( Iop_ReinterpF64asI64
,
14604 mkexpr(frB
) ) ) ) ) );
14607 case 0x346: // fmrgow floating merge odd word
14608 DIP("fmrgow fr%u,fr%u,fr%u\n", frD_addr
, frA_addr
, frB_addr
);
14610 assign( frD
, unop( Iop_ReinterpI64asF64
,
14611 binop( Iop_32HLto64
,
14613 unop( Iop_ReinterpF64asI64
,
14616 unop( Iop_ReinterpF64asI64
,
14617 mkexpr(frB
) ) ) ) ) );
14621 vex_printf("dis_fp_merge(ppc)(opc2)\n");
14625 putFReg( frD_addr
, mkexpr(frD
) );
14630 Floating Point Move Instructions
14632 static Bool
dis_fp_move ( UInt prefix
, UInt theInstr
)
14635 UChar opc1
= ifieldOPC(theInstr
);
14636 UChar frD_addr
= ifieldRegDS(theInstr
);
14637 UChar frA_addr
= ifieldRegA(theInstr
);
14638 UChar frB_addr
= ifieldRegB(theInstr
);
14639 UInt opc2
= ifieldOPClo10(theInstr
);
14640 UChar flag_rC
= ifieldBIT0(theInstr
);
14642 IRTemp frD
= newTemp(Ity_F64
);
14643 IRTemp frB
= newTemp(Ity_F64
);
14644 IRTemp itmpB
= newTemp(Ity_F64
);
14649 /* There is no prefixed version of these instructions. */
14652 if (opc1
!= 0x3F || (frA_addr
!= 0 && opc2
!= 0x008)) {
14653 vex_printf("dis_fp_move(ppc)(instr)\n");
14657 assign( frB
, getFReg(frB_addr
));
14660 case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126)
14661 DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frA_addr
,
14663 signA
= newTemp(Ity_I32
);
14664 hiD
= newTemp(Ity_I32
);
14665 itmpB
= newTemp(Ity_I64
);
14666 frA
= newTemp(Ity_F64
);
14667 assign( frA
, getFReg(frA_addr
) );
14669 /* get A's sign bit */
14670 assign(signA
, binop(Iop_And32
,
14671 unop(Iop_64HIto32
, unop(Iop_ReinterpF64asI64
,
14673 mkU32(0x80000000)) );
14675 assign( itmpB
, unop(Iop_ReinterpF64asI64
, mkexpr(frB
)) );
14677 /* mask off B's sign bit and or in A's sign bit */
14678 assign(hiD
, binop(Iop_Or32
,
14681 mkexpr(itmpB
)), /* frB's high 32 bits */
14682 mkU32(0x7fffffff)),
14685 /* combine hiD/loB into frD */
14686 assign( frD
, unop(Iop_ReinterpI64asF64
,
14687 binop(Iop_32HLto64
,
14690 mkexpr(itmpB
)))) ); /* frB's low 32 bits */
14693 case 0x028: // fneg (Floating Negate, PPC32 p416)
14694 DIP("fneg%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
14695 assign( frD
, unop( Iop_NegF64
, mkexpr(frB
) ));
14698 case 0x048: // fmr (Floating Move Register, PPC32 p410)
14699 DIP("fmr%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
14700 assign( frD
, mkexpr(frB
) );
14703 case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415)
14704 DIP("fnabs%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
14705 assign( frD
, unop( Iop_NegF64
, unop( Iop_AbsF64
, mkexpr(frB
) )));
14708 case 0x108: // fabs (Floating Absolute Value, PPC32 p399)
14709 DIP("fabs%s fr%u,fr%u\n", flag_rC
? ".":"", frD_addr
, frB_addr
);
14710 assign( frD
, unop( Iop_AbsF64
, mkexpr(frB
) ));
14714 vex_printf("dis_fp_move(ppc)(opc2)\n");
14718 putFReg( frD_addr
, mkexpr(frD
) );
14720 /* None of these change FPRF. cr1 is set in the usual way though,
14721 if flag_rC is set. */
14724 putCR321( 1, mkU8(0) );
14725 putCR0( 1, mkU8(0) );
14734 Floating Point Status/Control Register Instructions
14736 static Bool
dis_fp_scr ( UInt prefix
, UInt theInstr
, Bool GX_level
)
14738 /* Many forms - see each switch case */
14739 UChar opc1
= ifieldOPC(theInstr
);
14740 UInt opc2
= ifieldOPClo10(theInstr
);
14741 UChar flag_rC
= ifieldBIT0(theInstr
);
14743 /* There is no prefixed version of these instructions. */
14746 if (opc1
!= 0x3F) {
14747 vex_printf("dis_fp_scr(ppc)(instr)\n");
14752 case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479)
14753 // Bit crbD of the FPSCR is set.
14754 UChar crbD
= ifieldRegDS(theInstr
);
14755 UInt b11to20
= IFIELD(theInstr
, 11, 10);
14757 if (b11to20
!= 0) {
14758 vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n");
14761 DIP("mtfsb1%s crb%d \n", flag_rC
? ".":"", crbD
);
14762 putGST_masked( PPC_GST_FPSCR
, mkU64( 1 <<( 31 - crbD
) ),
14763 1ULL << ( 31 - crbD
) );
14767 case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465)
14768 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) );
14769 UChar b21to22
= toUChar( IFIELD( theInstr
, 21, 2 ) );
14770 UChar crfS
= toUChar( IFIELD( theInstr
, 18, 3 ) );
14771 UChar b11to17
= toUChar( IFIELD( theInstr
, 11, 7 ) );
14772 IRTemp tmp
= newTemp(Ity_I32
);
14774 if (b21to22
!= 0 || b11to17
!= 0 || flag_rC
!= 0) {
14775 vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n");
14778 DIP("mcrfs crf%d,crf%d\n", crfD
, crfS
);
14781 fpscr_all
= getGST_masked( PPC_GST_FPSCR
, MASK_FPSCR_RN
);
14782 assign( tmp
, binop(Iop_And32
,
14783 binop(Iop_Shr32
,fpscr_all
,mkU8(4 * (7-crfS
))),
14785 putGST_field( PPC_GST_CR
, mkexpr(tmp
), crfD
);
14789 case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478)
14790 // Bit crbD of the FPSCR is cleared.
14791 UChar crbD
= ifieldRegDS(theInstr
);
14792 UInt b11to20
= IFIELD(theInstr
, 11, 10);
14794 if (b11to20
!= 0) {
14795 vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n");
14798 DIP("mtfsb0%s crb%d\n", flag_rC
? ".":"", crbD
);
14799 putGST_masked( PPC_GST_FPSCR
, mkU64( 0 ), 1ULL << ( 31 - crbD
) );
14803 case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481)
14804 UInt crfD
= IFIELD( theInstr
, 23, 3 );
14805 UChar b17to22
= toUChar( IFIELD( theInstr
, 17, 6 ) );
14806 UChar IMM
= toUChar( IFIELD( theInstr
, 12, 4 ) );
14807 UChar b11
= toUChar( IFIELD( theInstr
, 11, 1 ) );
14808 UChar Wbit
= toUChar( IFIELD( theInstr
, 16, 1 ) );
14810 if (b17to22
!= 0 || b11
!= 0 || (Wbit
&& !GX_level
)) {
14811 vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n");
14814 DIP("mtfsfi%s crf%u,%d%s\n", flag_rC
? ".":"", crfD
, IMM
, Wbit
? ",1":"");
14815 crfD
= crfD
+ (8 * (1 - Wbit
) );
14816 putGST_field( PPC_GST_FPSCR
, mkU32( IMM
), crfD
);
14820 case 0x247: { // mffs (Move from FPSCR, PPC32 p468)
14821 UChar frD_addr
= ifieldRegDS(theInstr
);
14822 UChar frB_addr
= ifieldRegB(theInstr
);
14823 IRTemp frB
= newTemp(Ity_F64
);
14824 UInt b11to12
= IFIELD(theInstr
, 19, 2);
14825 UInt b13to15
= IFIELD(theInstr
, 16, 3);
14826 UInt RN
= IFIELD(theInstr
, 11, 2);
14827 UInt DRN
= IFIELD(theInstr
, 11, 3);
14829 /* The FPSCR_DRN, FPSCR_RN and FPSCR_FPCC are all stored in
14830 * their own 8-bit entries with distinct offsets. The FPSCR
14831 * register is handled as two 32-bit values. We need to
14832 * assemble the pieces into the single 64-bit value to return.
14834 IRExpr
* fpscr_lower
14836 getGST_masked( PPC_GST_FPSCR
, (MASK_FPSCR_RN
| MASK_FPSCR_C_FPCC
) ),
14844 IRExpr
* fpscr_upper
= getGST_masked_upper( PPC_GST_FPSCR
, MASK_FPSCR_DRN
);
14846 if ((b11to12
== 0) && (b13to15
== 0)) {
14847 DIP("mffs%s fr%u\n", flag_rC
? ".":"", frD_addr
);
14849 unop( Iop_ReinterpI64asF64
,
14850 binop( Iop_32HLto64
, fpscr_upper
, fpscr_lower
) ) );
14852 } else if ((b11to12
== 0) && (b13to15
== 1)) {
14853 DIP("mffsce fr%u\n", frD_addr
);
14854 /* Technically as of 4/5/2017 we are not tracking VE, OE, UE, ZE,
14855 or XE but in case that changes in the future, do the masking. */
14857 unop( Iop_ReinterpI64asF64
,
14858 binop( Iop_32HLto64
, fpscr_upper
,
14859 binop( Iop_And32
, fpscr_lower
,
14860 mkU32( 0xFFFFFF07 ) ) ) ) );
14862 } else if ((b11to12
== 2) && (b13to15
== 4)) {
14863 IRTemp frB_int
= newTemp(Ity_I64
);
14865 DIP("mffscdrn fr%u,fr%u\n", frD_addr
, frB_addr
);
14867 assign( frB
, getFReg(frB_addr
));
14868 assign( frB_int
, unop( Iop_ReinterpF64asI64
, mkexpr( frB
) ) );
14870 /* Clear all of the FPSCR bits except for the DRN field, VE,
14871 OE, UE, ZE and XE bits and write the result to the frD
14872 register. Note, currently the exception bits are not tracked but
14873 will mask anyway in case that changes in the future. */
14875 unop( Iop_ReinterpI64asF64
,
14876 binop( Iop_32HLto64
,
14877 binop( Iop_And32
, mkU32(0x7), fpscr_upper
),
14878 binop( Iop_And32
, mkU32(0xFF), fpscr_lower
) ) ) );
14880 /* Put new_DRN bits into the FPSCR register */
14881 putGST_masked( PPC_GST_FPSCR
, mkexpr( frB_int
), MASK_FPSCR_DRN
);
14883 } else if ((b11to12
== 2) && (b13to15
== 5)) {
14884 DIP("mffscdrni fr%u,%u\n", frD_addr
, DRN
);
14886 /* Clear all of the FPSCR bits except for the DRN field, VE,
14887 OE, UE, ZE and XE bits and write the result to the frD
14888 register. Note, currently the exception bits are not tracked but
14889 will mask anyway in case that changes in the future. */
14891 unop( Iop_ReinterpI64asF64
,
14892 binop( Iop_32HLto64
,
14893 binop( Iop_And32
, mkU32(0x7), fpscr_upper
),
14894 binop( Iop_And32
, mkU32(0xFF), fpscr_lower
) ) ) );
14896 /* Put new_DRN bits into the FPSCR register */
14897 putGST_masked( PPC_GST_FPSCR
, binop( Iop_32HLto64
, mkU32( DRN
),
14898 mkU32( 0 ) ), MASK_FPSCR_DRN
);
14900 } else if ((b11to12
== 2) && (b13to15
== 6)) {
14901 IRTemp frB_int
= newTemp(Ity_I64
);
14903 DIP("mffscrn fr%u,fr%u\n", frD_addr
,frB_addr
);
14905 assign( frB
, getFReg(frB_addr
));
14906 assign( frB_int
, unop( Iop_ReinterpF64asI64
, mkexpr( frB
) ) );
14908 /* Clear all of the FPSCR bits except for the DRN field, VE,
14909 OE, UE, ZE and XE bits and write the result to the frD
14910 register. Note, currently the exception bits are not tracked but
14911 will mask anyway in case that changes in the future. */
14913 unop( Iop_ReinterpI64asF64
,
14914 binop( Iop_32HLto64
,
14915 binop( Iop_And32
, mkU32(0x7), fpscr_upper
),
14916 binop( Iop_And32
, mkU32(0xFF), fpscr_lower
) ) ) );
14918 /* Put new_CRN bits into the FPSCR register */
14919 putGST_masked( PPC_GST_FPSCR
, mkexpr( frB_int
), MASK_FPSCR_RN
);
14921 } else if ((b11to12
== 2) && (b13to15
== 7)) {
14922 DIP("mffscrni fr%u,%u\n", frD_addr
, RN
);
14924 /* Clear all of the FPSCR bits except for the DRN field, VE,
14925 OE, UE, ZE and XE bits and write the result to the frD
14926 register. Note, currently the exception bits are not tracked but
14927 will mask anyway in case that changes in the future. */
14929 unop( Iop_ReinterpI64asF64
,
14930 binop( Iop_32HLto64
,
14931 binop( Iop_And32
, mkU32(0x7), fpscr_upper
),
14932 binop( Iop_And32
, mkU32(0xFF), fpscr_lower
) ) ) );
14934 /* Put new_RN bits into the FPSCR register */
14935 putGST_masked( PPC_GST_FPSCR
, binop( Iop_32HLto64
, mkU32( 0 ),
14936 mkU32( RN
) ), MASK_FPSCR_RN
);
14938 } else if ((b11to12
== 3) && (b13to15
== 0)) {
14939 DIP("mffsl fr%u\n", frD_addr
);
14940 /* Technically as of 4/5/2017 we are not tracking VE, OE, UE, ZE,
14941 XE, FR, FI, C, FL, FG, FE, FU. Also only track DRN in the upper
14942 bits but in case that changes in the future we will do the
14945 unop( Iop_ReinterpI64asF64
,
14946 binop( Iop_32HLto64
,
14947 binop( Iop_And32
, fpscr_upper
,
14949 binop( Iop_And32
, fpscr_lower
,
14950 mkU32( 0x7F0FF ) ) ) ) );
14952 vex_printf("dis_fp_scr(ppc)(mff**) Unrecognized instruction.\n");
14958 case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480)
14959 UChar b25
= toUChar( IFIELD(theInstr
, 25, 1) );
14960 UChar FM
= toUChar( IFIELD(theInstr
, 17, 8) );
14961 UChar frB_addr
= ifieldRegB(theInstr
);
14962 IRTemp frB
= newTemp(Ity_F64
);
14963 IRTemp rB_64
= newTemp( Ity_I64
);
14967 #define BFP_MASK_SEED 0x3000000000000000ULL
14968 #define DFP_MASK_SEED 0x7000000000000000ULL
14971 /* This implies that Decimal Floating Point is supported, and the
14972 * FPSCR must be managed as a 64-bit register.
14974 Wbit
= toUChar( IFIELD(theInstr
, 16, 1) );
14980 /* new 64 bit move variant for power 6. If L field (bit 25) is
14981 * a one do a full 64 bit move. Note, the FPSCR is not really
14982 * properly modeled. This instruciton only changes the value of
14983 * the rounding mode bit fields RN, FPCC and DRN. The HW exception bits
14984 * do not get set in the simulator. 1/12/09
14986 DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC
? ".":"", FM
, frB_addr
);
14987 mask
= 0x1F0001F003;
14990 DIP("mtfsf%s %d,fr%u\n", flag_rC
? ".":"", FM
, frB_addr
);
14991 // Build 32bit mask from FM:
14993 for (i
=0; i
<8; i
++) {
14994 if ((FM
& (1<<(7-i
))) == 1) {
14995 /* FPSCR field k is set to the contents of the corresponding
14996 * field of register FRB, where k = i+8x(1-W). In the Power
14997 * ISA, register field numbering is from left to right, so field
14998 * 15 is the least significant field in a 64-bit register. To
14999 * generate the mask, we set all the appropriate rounding mode
15000 * bits in the highest order nibble (field 0) and shift right
15001 * 'k x nibble length'.
15004 mask
|= DFP_MASK_SEED
>> ( 4 * ( i
+ 8 * ( 1 - Wbit
) ) );
15006 mask
|= BFP_MASK_SEED
>> ( 4 * ( i
+ 8 * ( 1 - Wbit
) ) );
15008 if ((FM
& (1<<(7-i
))) == 0x2) { //set the FPCC bits
15011 if ((FM
& (1<<(7-i
))) == 0x4) { //set the Floating-Point Class Descriptor (C) bit
15016 assign( frB
, getFReg(frB_addr
));
15017 assign( rB_64
, unop( Iop_ReinterpF64asI64
, mkexpr( frB
) ) );
15018 putGST_masked( PPC_GST_FPSCR
, mkexpr( rB_64
), mask
);
15023 vex_printf("dis_fp_scr(ppc)(opc2)\n");
15029 /*------------------------------------------------------------*/
15030 /*--- Decimal Floating Point (DFP) Helper functions ---*/
15031 /*------------------------------------------------------------*/
15033 #define DFP_EXTND 2
15034 #define DFP_LONG_BIAS 398
15035 #define DFP_LONG_ENCODED_FIELD_MASK 0x1F00
15036 #define DFP_EXTND_BIAS 6176
15037 #define DFP_EXTND_ENCODED_FIELD_MASK 0x1F000
15038 #define DFP_LONG_EXP_MSK 0XFF
15039 #define DFP_EXTND_EXP_MSK 0XFFF
15041 #define DFP_G_FIELD_LONG_MASK 0x7FFC0000 // upper 32-bits only
15042 #define DFP_LONG_GFIELD_RT_SHIFT (63 - 13 - 32) // adj for upper 32-bits
15043 #define DFP_G_FIELD_EXTND_MASK 0x7FFFC000 // upper 32-bits only
15044 #define DFP_EXTND_GFIELD_RT_SHIFT (63 - 17 - 32) //adj for upper 32 bits
15045 #define DFP_T_FIELD_LONG_MASK 0x3FFFF // mask for upper 32-bits
15046 #define DFP_T_FIELD_EXTND_MASK 0x03FFFF // mask for upper 32-bits
15047 #define DFP_LONG_EXP_MAX 369 // biased max
15048 #define DFP_LONG_EXP_MIN 0 // biased min
15049 #define DFP_EXTND_EXP_MAX 6111 // biased max
15050 #define DFP_EXTND_EXP_MIN 0 // biased min
15051 #define DFP_LONG_MAX_SIG_DIGITS 16
15052 #define DFP_EXTND_MAX_SIG_DIGITS 34
15053 #define MAX_DIGITS_IN_STRING 8
15056 #define AND(x, y) binop( Iop_And32, x, y )
15057 #define AND4(w, x, y, z) AND( AND( w, x ), AND( y, z ) )
15058 #define OR(x, y) binop( Iop_Or32, x, y )
15059 #define OR3(x, y, z) OR( x, OR( y, z ) )
15060 #define OR4(w, x, y, z) OR( OR( w, x ), OR( y, z ) )
15061 #define NOT(x) unop( Iop_1Uto32, unop( Iop_Not1, unop( Iop_32to1, mkexpr( x ) ) ) )
15063 #define SHL(value, by) binop( Iop_Shl32, value, mkU8( by ) )
15064 #define SHR(value, by) binop( Iop_Shr32, value, mkU8( by ) )
15066 #define BITS5(_b4,_b3,_b2,_b1,_b0) \
15067 (((_b4) << 4) | ((_b3) << 3) | ((_b2) << 2) | \
15068 ((_b1) << 1) | ((_b0) << 0))
15070 static void generate_store_DFP_FPRF_value( ULong irType
, IRExpr
*src
,
15071 const VexAbiInfo
* vbi
)
15073 /* This function takes a DFP value and computes the value of the FPRF
15074 field in the FPCC register and store it. It is done as a clean helper.
15077 0b00001 Signaling NaN (DFP only)
15079 0b01001 negative infinity
15080 0b01000 negative normal number
15081 0b11000 negative subnormal number
15082 0b10010 negative zero
15083 0b00010 positive zero
15084 0b10100 positive subnormal number
15085 0b00100 positive normal number
15086 0b00101 positive infinity
15089 IRTemp sign
= newTemp( Ity_I32
);
15090 IRTemp gfield
= newTemp( Ity_I32
);
15091 IRTemp gfield_mask
= newTemp( Ity_I32
);
15092 IRTemp exponent
= newTemp( Ity_I64
);
15093 UInt exponent_bias
= 0;
15094 IRTemp T_value_is_zero
= newTemp( Ity_I32
);
15095 IRTemp fprf_value
= newTemp( Ity_I32
);
15096 IRTemp lmd
= newTemp( Ity_I32
);
15097 IRTemp lmd_zero_true
= newTemp( Ity_I1
);
15098 Int min_norm_exp
= 0;
15100 vassert( irType
== Ity_D128
);
15102 if (irType
== Ity_D128
) {
15103 assign( gfield_mask
, mkU32( DFP_G_FIELD_EXTND_MASK
) );
15104 /* The gfield bits are left justified. */
15105 assign( gfield
, binop( Iop_And32
,
15106 mkexpr( gfield_mask
),
15107 unop( Iop_64HIto32
,
15108 unop( Iop_ReinterpD64asI64
,
15109 unop( Iop_D128HItoD64
, src
) ) ) ) );
15110 assign( exponent
, unop( Iop_ExtractExpD128
, src
) );
15111 exponent_bias
= 6176;
15112 min_norm_exp
= -6143;
15114 /* The significand is zero if the T field and LMD are all zeros */
15115 /* Check if LMD is zero */
15116 Get_lmd( &lmd
, binop( Iop_Shr32
,
15117 mkexpr( gfield
), mkU8( 31 - 5 ) ) );
15119 assign( lmd_zero_true
, binop( Iop_CmpEQ32
,
15122 /* The T value and the LMD are the BCD value of the significand.
15123 If the upper and lower T value fields and the LMD are all zero
15124 then the significand is zero. */
15125 assign( T_value_is_zero
,
15128 mkexpr( lmd_zero_true
),
15129 mkAND1 ( binop( Iop_CmpEQ64
,
15131 mkU64( DFP_T_FIELD_EXTND_MASK
),
15132 unop( Iop_ReinterpD64asI64
,
15133 unop( Iop_D128HItoD64
,
15136 binop( Iop_CmpEQ64
,
15137 unop( Iop_ReinterpD64asI64
,
15138 unop( Iop_D128LOtoD64
,
15140 mkU64( 0 ) ) ) ) ) );
15145 unop( Iop_ReinterpD64asI64
,
15146 unop( Iop_D128HItoD64
, src
) ),
15149 /* generate_store_DFP_FPRF_value, unknown value for irType */
15153 /* Determine what the type of the number is. */
15154 assign( fprf_value
,
15155 mkIRExprCCall( Ity_I32
, 0 /*regparms*/,
15156 "generate_DFP_FPRF_value_helper",
15157 fnptr_to_fnentry( vbi
,
15158 &generate_DFP_FPRF_value_helper
),
15159 mkIRExprVec_6( mkexpr( gfield
),
15160 mkexpr( exponent
),
15161 mkU32( exponent_bias
),
15162 mkU32( min_norm_exp
),
15164 mkexpr( T_value_is_zero
) ) ) );
15165 /* fprf[0:4] = (C | FPCC[0:3]) */
15166 putC( binop( Iop_Shr32
, mkexpr( fprf_value
), mkU8( 4 ) ) );
15167 putFPCC( binop( Iop_And32
, mkexpr( fprf_value
), mkU32 (0xF ) ) );
15171 static IRExpr
* Gfield_encoding( IRExpr
* lmexp
, IRExpr
* lmd32
)
15173 IRTemp lmd_07_mask
= newTemp( Ity_I32
);
15174 IRTemp lmd_8_mask
= newTemp( Ity_I32
);
15175 IRTemp lmd_9_mask
= newTemp( Ity_I32
);
15176 IRTemp lmexp_00_mask
= newTemp( Ity_I32
);
15177 IRTemp lmexp_01_mask
= newTemp( Ity_I32
);
15178 IRTemp lmexp_10_mask
= newTemp( Ity_I32
);
15179 IRTemp lmd_07_val
= newTemp( Ity_I32
);
15180 IRTemp lmd_8_val
= newTemp( Ity_I32
);
15181 IRTemp lmd_9_val
= newTemp( Ity_I32
);
15183 /* The encodig is as follows:
15184 * lmd - left most digit
15185 * lme - left most 2-bits of the exponent
15188 * 0 - 7 (lmexp << 3) | lmd
15189 * 8 0b11000 (24 decimal) if lme=0b00;
15190 * 0b11010 (26 decimal) if lme=0b01;
15191 * 0b11100 (28 decimal) if lme=0b10;
15192 * 9 0b11001 (25 decimal) if lme=0b00;
15193 * 0b11011 (27 decimal) if lme=0b01;
15194 * 0b11101 (29 decimal) if lme=0b10;
15197 /* Generate the masks for each condition */
15198 assign( lmd_07_mask
,
15199 unop( Iop_1Sto32
, binop( Iop_CmpLE32U
, lmd32
, mkU32( 7 ) ) ) );
15200 assign( lmd_8_mask
,
15201 unop( Iop_1Sto32
, binop( Iop_CmpEQ32
, lmd32
, mkU32( 8 ) ) ) );
15202 assign( lmd_9_mask
,
15203 unop( Iop_1Sto32
, binop( Iop_CmpEQ32
, lmd32
, mkU32( 9 ) ) ) );
15204 assign( lmexp_00_mask
,
15205 unop( Iop_1Sto32
, binop( Iop_CmpEQ32
, lmexp
, mkU32( 0 ) ) ) );
15206 assign( lmexp_01_mask
,
15207 unop( Iop_1Sto32
, binop( Iop_CmpEQ32
, lmexp
, mkU32( 1 ) ) ) );
15208 assign( lmexp_10_mask
,
15209 unop( Iop_1Sto32
, binop( Iop_CmpEQ32
, lmexp
, mkU32( 2 ) ) ) );
15211 /* Generate the values for each LMD condition, assuming the condition
15214 assign( lmd_07_val
,
15215 binop( Iop_Or32
, binop( Iop_Shl32
, lmexp
, mkU8( 3 ) ), lmd32
) );
15220 mkexpr( lmexp_00_mask
),
15223 mkexpr( lmexp_01_mask
),
15225 binop( Iop_And32
, mkexpr( lmexp_10_mask
), mkU32( 28 ) ) ) );
15230 mkexpr( lmexp_00_mask
),
15233 mkexpr( lmexp_01_mask
),
15235 binop( Iop_And32
, mkexpr( lmexp_10_mask
), mkU32( 29 ) ) ) );
15237 /* generate the result from the possible LMD values */
15238 return binop( Iop_Or32
,
15241 mkexpr( lmd_07_mask
),
15242 mkexpr( lmd_07_val
) ),
15244 mkexpr( lmd_8_mask
),
15245 mkexpr( lmd_8_val
) ) ),
15246 binop( Iop_And32
, mkexpr( lmd_9_mask
), mkexpr( lmd_9_val
) ) );
15249 static void Get_lmd( IRTemp
* lmd
, IRExpr
* gfield_0_4
)
15251 /* Extract the exponent and the left most digit of the mantissa
15252 * from the G field bits [0:4].
15254 IRTemp lmd_07_mask
= newTemp( Ity_I32
);
15255 IRTemp lmd_8_00_mask
= newTemp( Ity_I32
);
15256 IRTemp lmd_8_01_mask
= newTemp( Ity_I32
);
15257 IRTemp lmd_8_10_mask
= newTemp( Ity_I32
);
15258 IRTemp lmd_9_00_mask
= newTemp( Ity_I32
);
15259 IRTemp lmd_9_01_mask
= newTemp( Ity_I32
);
15260 IRTemp lmd_9_10_mask
= newTemp( Ity_I32
);
15262 IRTemp lmd_07_val
= newTemp( Ity_I32
);
15263 IRTemp lmd_8_val
= newTemp( Ity_I32
);
15264 IRTemp lmd_9_val
= newTemp( Ity_I32
);
15266 /* The left most digit (LMD) encoding is as follows:
15268 * 0 - 7 (lmexp << 3) | lmd
15269 * 8 0b11000 (24 decimal) if lme=0b00;
15270 * 0b11010 (26 decimal) if lme=0b01;
15271 * 0b11100 (28 decimal) if lme=0b10
15272 * 9 0b11001 (25 decimal) if lme=0b00;
15273 * 0b11011 (27 decimal) if lme=0b01;
15274 * 0b11101 (29 decimal) if lme=0b10;
15277 /* Generate the masks for each condition of LMD and exponent bits */
15278 assign( lmd_07_mask
,
15279 unop( Iop_1Sto32
, binop( Iop_CmpLE32U
,
15281 mkU32( BITS5(1,0,1,1,1) ) ) ) );
15282 assign( lmd_8_00_mask
,
15283 unop( Iop_1Sto32
, binop( Iop_CmpEQ32
,
15285 mkU32( BITS5(1,1,0,0,0) ) ) ) );
15286 assign( lmd_8_01_mask
,
15287 unop( Iop_1Sto32
, binop( Iop_CmpEQ32
,
15289 mkU32( BITS5(1,1,0,1,0) ) ) ) );
15290 assign( lmd_8_10_mask
,
15291 unop( Iop_1Sto32
, binop( Iop_CmpEQ32
,
15293 mkU32( BITS5(1,1,1,0,0) ) ) ) );
15294 assign( lmd_9_00_mask
,
15295 unop( Iop_1Sto32
, binop( Iop_CmpEQ32
,
15297 mkU32( BITS5(1,1,0,0,1) ) ) ) );
15298 assign( lmd_9_01_mask
,
15299 unop( Iop_1Sto32
, binop( Iop_CmpEQ32
,
15301 mkU32( BITS5(1,1,0,1,1) ) ) ) );
15302 assign( lmd_9_10_mask
,
15303 unop( Iop_1Sto32
, binop( Iop_CmpEQ32
,
15305 mkU32( BITS5(1,1,1,0,1) ) ) ) );
15307 /* Generate the values for each LMD condition, assuming the condition
15310 assign( lmd_07_val
, binop( Iop_And32
, gfield_0_4
, mkU32( 0x7 ) ) );
15311 assign( lmd_8_val
, mkU32( 0x8 ) );
15312 assign( lmd_9_val
, mkU32( 0x9 ) );
15315 OR( OR3 ( AND( mkexpr( lmd_07_mask
), mkexpr( lmd_07_val
) ),
15316 AND( mkexpr( lmd_8_00_mask
), mkexpr( lmd_8_val
) ),
15317 AND( mkexpr( lmd_8_01_mask
), mkexpr( lmd_8_val
) )),
15318 OR4( AND( mkexpr( lmd_8_10_mask
), mkexpr( lmd_8_val
) ),
15319 AND( mkexpr( lmd_9_00_mask
), mkexpr( lmd_9_val
) ),
15320 AND( mkexpr( lmd_9_01_mask
), mkexpr( lmd_9_val
) ),
15321 AND( mkexpr( lmd_9_10_mask
), mkexpr( lmd_9_val
) )
15325 #define DIGIT1_SHR 4 // shift digit 1 to bottom 4 bits
15326 #define DIGIT2_SHR 8 // shift digit 2 to bottom 4 bits
15327 #define DIGIT3_SHR 12
15328 #define DIGIT4_SHR 16
15329 #define DIGIT5_SHR 20
15330 #define DIGIT6_SHR 24
15331 #define DIGIT7_SHR 28
15333 static IRExpr
* bcd_digit_inval( IRExpr
* bcd_u
, IRExpr
* bcd_l
)
15335 /* 60-bit BCD string stored in two 32-bit values. Check that each,
15336 * digit is a valid BCD number, i.e. less then 9.
15338 IRTemp valid
= newTemp( Ity_I32
);
15341 AND4( AND4 ( unop( Iop_1Sto32
,
15342 binop( Iop_CmpLE32U
,
15348 binop( Iop_CmpLE32U
,
15352 mkU8 ( DIGIT1_SHR
) ),
15356 binop( Iop_CmpLE32U
,
15360 mkU8 ( DIGIT2_SHR
) ),
15364 binop( Iop_CmpLE32U
,
15368 mkU8 ( DIGIT3_SHR
) ),
15370 mkU32( 0x9 ) ) ) ),
15371 AND4 ( unop( Iop_1Sto32
,
15372 binop( Iop_CmpLE32U
,
15376 mkU8 ( DIGIT4_SHR
) ),
15380 binop( Iop_CmpLE32U
,
15384 mkU8 ( DIGIT5_SHR
) ),
15388 binop( Iop_CmpLE32U
,
15392 mkU8 ( DIGIT6_SHR
) ),
15396 binop( Iop_CmpLE32U
,
15400 mkU8 ( DIGIT7_SHR
) ),
15402 mkU32( 0x9 ) ) ) ),
15403 AND4( unop( Iop_1Sto32
,
15404 binop( Iop_CmpLE32U
,
15410 binop( Iop_CmpLE32U
,
15414 mkU8 ( DIGIT1_SHR
) ),
15418 binop( Iop_CmpLE32U
,
15422 mkU8 ( DIGIT2_SHR
) ),
15426 binop( Iop_CmpLE32U
,
15430 mkU8 ( DIGIT3_SHR
) ),
15432 mkU32( 0x9 ) ) ) ),
15433 AND4( unop( Iop_1Sto32
,
15434 binop( Iop_CmpLE32U
,
15438 mkU8 ( DIGIT4_SHR
) ),
15442 binop( Iop_CmpLE32U
,
15446 mkU8 ( DIGIT5_SHR
) ),
15450 binop( Iop_CmpLE32U
,
15454 mkU8 ( DIGIT6_SHR
) ),
15458 binop( Iop_CmpLE32U
,
15462 mkU8 ( DIGIT7_SHR
) ),
15464 mkU32( 0x9 ) ) ) ) ) );
15466 return unop( Iop_Not32
, mkexpr( valid
) );
15476 static IRExpr
* Generate_neg_sign_mask( IRExpr
* sign
)
15478 return binop( Iop_Or32
,
15479 unop( Iop_1Sto32
, binop( Iop_CmpEQ32
, sign
, mkU32( 0xB ) ) ),
15480 unop( Iop_1Sto32
, binop( Iop_CmpEQ32
, sign
, mkU32( 0xD ) ) )
15484 static IRExpr
* Generate_pos_sign_mask( IRExpr
* sign
)
15486 return binop( Iop_Or32
,
15489 binop( Iop_CmpEQ32
, sign
, mkU32( 0xA ) ) ),
15491 binop( Iop_CmpEQ32
, sign
, mkU32( 0xC ) ) ) ),
15494 binop( Iop_CmpEQ32
, sign
, mkU32( 0xE ) ) ),
15496 binop( Iop_CmpEQ32
, sign
, mkU32( 0xF ) ) ) ) );
15499 static IRExpr
* Generate_sign_bit( IRExpr
* pos_sign_mask
,
15500 IRExpr
* neg_sign_mask
)
15502 return binop( Iop_Or32
,
15503 binop( Iop_And32
, neg_sign_mask
, mkU32( 0x80000000 ) ),
15504 binop( Iop_And32
, pos_sign_mask
, mkU32( 0x00000000 ) ) );
15507 static IRExpr
* Generate_inv_mask( IRExpr
* invalid_bcd_mask
,
15508 IRExpr
* pos_sign_mask
,
15509 IRExpr
* neg_sign_mask
)
15510 /* first argument is all 1's if the BCD string had an invalid digit in it. */
15512 return binop( Iop_Or32
,
15515 binop( Iop_CmpEQ32
,
15516 binop( Iop_Or32
, pos_sign_mask
, neg_sign_mask
),
15517 mkU32( 0x0 ) ) ) );
15520 static void Generate_132_bit_bcd_string( IRExpr
* frBI64_hi
, IRExpr
* frBI64_lo
,
15521 IRTemp
* top_12_l
, IRTemp
* mid_60_u
,
15522 IRTemp
* mid_60_l
, IRTemp
* low_60_u
,
15525 IRTemp tmplow60
= newTemp( Ity_I64
);
15526 IRTemp tmpmid60
= newTemp( Ity_I64
);
15527 IRTemp tmptop12
= newTemp( Ity_I64
);
15528 IRTemp low_50
= newTemp( Ity_I64
);
15529 IRTemp mid_50
= newTemp( Ity_I64
);
15530 IRTemp top_10
= newTemp( Ity_I64
);
15531 IRTemp top_12_u
= newTemp( Ity_I32
); // only needed for a dummy arg
15533 /* Convert the 110-bit densely packed BCD string to a 128-bit BCD string */
15535 /* low_50[49:0] = ((frBI64_lo[49:32] << 14) | frBI64_lo[31:0]) */
15537 binop( Iop_32HLto64
,
15539 unop( Iop_64HIto32
, frBI64_lo
),
15540 mkU32( 0x3FFFF ) ),
15541 unop( Iop_64to32
, frBI64_lo
) ) );
15543 /* Convert the 50 bit densely packed BCD string to a 60 bit
15546 assign( tmplow60
, unop( Iop_DPBtoBCD
, mkexpr( low_50
) ) );
15547 assign( *low_60_u
, unop( Iop_64HIto32
, mkexpr( tmplow60
) ) );
15548 assign( *low_60_l
, unop( Iop_64to32
, mkexpr( tmplow60
) ) );
15550 /* mid_50[49:0] = ((frBI64_hi[35:32] << 14) | frBI64_hi[31:18]) |
15551 * ((frBI64_hi[17:0] << 14) | frBI64_lo[63:50])
15554 binop( Iop_32HLto64
,
15558 unop( Iop_64HIto32
, frBI64_hi
),
15562 unop( Iop_64to32
, frBI64_hi
),
15566 unop( Iop_64to32
, frBI64_hi
),
15569 unop( Iop_64HIto32
, frBI64_lo
),
15570 mkU8( 18 ) ) ) ) );
15572 /* Convert the 50 bit densely packed BCD string to a 60 bit
15575 assign( tmpmid60
, unop( Iop_DPBtoBCD
, mkexpr( mid_50
) ) );
15576 assign( *mid_60_u
, unop( Iop_64HIto32
, mkexpr( tmpmid60
) ) );
15577 assign( *mid_60_l
, unop( Iop_64to32
, mkexpr( tmpmid60
) ) );
15579 /* top_10[49:0] = frBI64_hi[45:36]) | */
15581 binop( Iop_32HLto64
,
15585 unop( Iop_64HIto32
, frBI64_hi
),
15587 mkU32( 0x3FF ) ) ) );
15589 /* Convert the 10 bit densely packed BCD string to a 12 bit
15592 assign( tmptop12
, unop( Iop_DPBtoBCD
, mkexpr( top_10
) ) );
15593 assign( top_12_u
, unop( Iop_64HIto32
, mkexpr( tmptop12
) ) );
15594 assign( *top_12_l
, unop( Iop_64to32
, mkexpr( tmptop12
) ) );
15597 static void Count_zeros( int start
, IRExpr
* init_cnt
, IRExpr
* init_flag
,
15598 IRTemp
* final_cnt
, IRTemp
* final_flag
,
15601 IRTemp cnt
[MAX_DIGITS_IN_STRING
+ 1];IRTemp flag
[MAX_DIGITS_IN_STRING
+1];
15602 int digits
= MAX_DIGITS_IN_STRING
;
15605 cnt
[start
-1] = newTemp( Ity_I8
);
15606 flag
[start
-1] = newTemp( Ity_I8
);
15607 assign( cnt
[start
-1], init_cnt
);
15608 assign( flag
[start
-1], init_flag
);
15610 for ( i
= start
; i
<= digits
; i
++) {
15611 cnt
[i
] = newTemp( Ity_I8
);
15612 flag
[i
] = newTemp( Ity_I8
);
15615 mkexpr( cnt
[i
-1] ),
15622 ( ( digits
- i
) * 4) ) ),
15624 binop( Iop_Xor8
, /* complement flag */
15625 mkexpr( flag
[i
- 1] ),
15626 mkU8( 0xFF ) ) ) ) );
15628 /* set flag to 1 if digit was not a zero */
15636 ( (digits
- i
) * 4) ) ),
15638 mkexpr( flag
[i
- 1] ) ) );
15641 *final_cnt
= cnt
[digits
];
15642 *final_flag
= flag
[digits
];
15645 static IRExpr
* Count_leading_zeros_60( IRExpr
* lmd
, IRExpr
* upper_28
,
15648 IRTemp num_lmd
= newTemp( Ity_I8
);
15649 IRTemp num_upper
= newTemp( Ity_I8
);
15650 IRTemp num_low
= newTemp( Ity_I8
);
15651 IRTemp lmd_flag
= newTemp( Ity_I8
);
15652 IRTemp upper_flag
= newTemp( Ity_I8
);
15653 IRTemp low_flag
= newTemp( Ity_I8
);
15655 assign( num_lmd
, unop( Iop_1Uto8
, binop( Iop_CmpEQ32
, lmd
, mkU32( 0 ) ) ) );
15656 assign( lmd_flag
, unop( Iop_Not8
, mkexpr( num_lmd
) ) );
15660 mkexpr( lmd_flag
),
15666 mkexpr( num_upper
),
15667 mkexpr( upper_flag
),
15672 return mkexpr( num_low
);
15675 static IRExpr
* Count_leading_zeros_128( IRExpr
* lmd
, IRExpr
* top_12_l
,
15676 IRExpr
* mid_60_u
, IRExpr
* mid_60_l
,
15677 IRExpr
* low_60_u
, IRExpr
* low_60_l
)
15679 IRTemp num_lmd
= newTemp( Ity_I8
);
15680 IRTemp num_top
= newTemp( Ity_I8
);
15681 IRTemp num_mid_u
= newTemp( Ity_I8
);
15682 IRTemp num_mid_l
= newTemp( Ity_I8
);
15683 IRTemp num_low_u
= newTemp( Ity_I8
);
15684 IRTemp num_low_l
= newTemp( Ity_I8
);
15686 IRTemp lmd_flag
= newTemp( Ity_I8
);
15687 IRTemp top_flag
= newTemp( Ity_I8
);
15688 IRTemp mid_u_flag
= newTemp( Ity_I8
);
15689 IRTemp mid_l_flag
= newTemp( Ity_I8
);
15690 IRTemp low_u_flag
= newTemp( Ity_I8
);
15691 IRTemp low_l_flag
= newTemp( Ity_I8
);
15693 /* Check the LMD, digit 34, to see if it is zero. */
15694 assign( num_lmd
, unop( Iop_1Uto8
, binop( Iop_CmpEQ32
, lmd
, mkU32( 0 ) ) ) );
15696 assign( lmd_flag
, unop( Iop_Not8
, mkexpr( num_lmd
) ) );
15700 mkexpr( lmd_flag
),
15707 mkexpr( top_flag
),
15711 binop( Iop_Shl32
, mid_60_u
, mkU8( 2 ) ),
15712 binop( Iop_Shr32
, mid_60_l
, mkU8( 30 ) ) ) );
15715 mkexpr( num_mid_u
),
15716 mkexpr( mid_u_flag
),
15722 mkexpr( num_mid_l
),
15723 mkexpr( mid_l_flag
),
15727 binop( Iop_Shl32
, low_60_u
, mkU8( 2 ) ),
15728 binop( Iop_Shr32
, low_60_l
, mkU8( 30 ) ) ) );
15731 mkexpr( num_low_u
),
15732 mkexpr( low_u_flag
),
15737 return mkexpr( num_low_l
);
15740 static IRExpr
* Check_unordered(IRExpr
* val
)
15742 IRTemp gfield0to5
= newTemp( Ity_I32
);
15744 /* Extract G[0:4] */
15745 assign( gfield0to5
,
15747 binop( Iop_Shr32
, unop( Iop_64HIto32
, val
), mkU8( 26 ) ),
15750 /* Check for unordered, return all 1'x if true */
15751 return binop( Iop_Or32
, /* QNaN check */
15753 binop( Iop_CmpEQ32
,
15754 mkexpr( gfield0to5
),
15756 unop( Iop_1Sto32
, /* SNaN check */
15757 binop( Iop_CmpEQ32
,
15758 mkexpr( gfield0to5
),
15759 mkU32( 0x1F ) ) ) );
15772 /*------------------------------------------------------------*/
15773 /*--- Decimal Floating Point (DFP) instruction translation ---*/
15774 /*------------------------------------------------------------*/
15776 /* DFP Arithmetic instructions */
15777 static Bool
dis_dfp_arith( UInt prefix
, UInt theInstr
)
15779 UInt opc2
= ifieldOPClo10( theInstr
);
15780 UChar frS_addr
= ifieldRegDS( theInstr
);
15781 UChar frA_addr
= ifieldRegA( theInstr
);
15782 UChar frB_addr
= ifieldRegB( theInstr
);
15783 UChar flag_rC
= ifieldBIT0( theInstr
);
15785 IRTemp frA
= newTemp( Ity_D64
);
15786 IRTemp frB
= newTemp( Ity_D64
);
15787 IRTemp frS
= newTemp( Ity_D64
);
15788 IRExpr
* round
= get_IR_roundingmode_DFP();
15790 /* By default, if flag_RC is set, we will clear cr1 after the
15791 * operation. In reality we should set cr1 to indicate the
15792 * exception status of the operation, but since we're not
15793 * simulating exceptions, the exception status will appear to be
15794 * zero. Hence cr1 should be cleared if this is a . form insn.
15796 Bool clear_CR1
= True
;
15798 /* There is no prefixed version of these instructions. */
15801 assign( frA
, getDReg( frA_addr
) );
15802 assign( frB
, getDReg( frB_addr
) );
15806 DIP( "dadd%s fr%u,fr%u,fr%u\n",
15807 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
15808 assign( frS
, triop( Iop_AddD64
, round
, mkexpr( frA
), mkexpr( frB
) ) );
15810 case 0x202: // dsub
15811 DIP( "dsub%s fr%u,fr%u,fr%u\n",
15812 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
15813 assign( frS
, triop( Iop_SubD64
, round
, mkexpr( frA
), mkexpr( frB
) ) );
15816 DIP( "dmul%s fr%u,fr%u,fr%u\n",
15817 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
15818 assign( frS
, triop( Iop_MulD64
, round
, mkexpr( frA
), mkexpr( frB
) ) );
15820 case 0x222: // ddiv
15821 DIP( "ddiv%s fr%u,fr%u,fr%u\n",
15822 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
15823 assign( frS
, triop( Iop_DivD64
, round
, mkexpr( frA
), mkexpr( frB
) ) );
15827 putDReg( frS_addr
, mkexpr( frS
) );
15829 if (flag_rC
&& clear_CR1
) {
15830 putCR321( 1, mkU8( 0 ) );
15831 putCR0( 1, mkU8( 0 ) );
15837 /* Quad DFP Arithmetic instructions */
15838 static Bool
dis_dfp_arithq( UInt prefix
, UInt theInstr
)
15840 UInt opc2
= ifieldOPClo10( theInstr
);
15841 UChar frS_addr
= ifieldRegDS( theInstr
);
15842 UChar frA_addr
= ifieldRegA( theInstr
);
15843 UChar frB_addr
= ifieldRegB( theInstr
);
15844 UChar flag_rC
= ifieldBIT0( theInstr
);
15846 IRTemp frA
= newTemp( Ity_D128
);
15847 IRTemp frB
= newTemp( Ity_D128
);
15848 IRTemp frS
= newTemp( Ity_D128
);
15849 IRExpr
* round
= get_IR_roundingmode_DFP();
15851 /* By default, if flag_RC is set, we will clear cr1 after the
15852 * operation. In reality we should set cr1 to indicate the
15853 * exception status of the operation, but since we're not
15854 * simulating exceptions, the exception status will appear to be
15855 * zero. Hence cr1 should be cleared if this is a . form insn.
15857 Bool clear_CR1
= True
;
15859 /* There is no prefixed version of these instructions. */
15862 assign( frA
, getDReg_pair( frA_addr
) );
15863 assign( frB
, getDReg_pair( frB_addr
) );
15867 DIP( "daddq%s fr%u,fr%u,fr%u\n",
15868 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
15869 assign( frS
, triop( Iop_AddD128
, round
, mkexpr( frA
), mkexpr( frB
) ) );
15871 case 0x202: // dsubq
15872 DIP( "dsubq%s fr%u,fr%u,fr%u\n",
15873 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
15874 assign( frS
, triop( Iop_SubD128
, round
, mkexpr( frA
), mkexpr( frB
) ) );
15876 case 0x22: // dmulq
15877 DIP( "dmulq%s fr%u,fr%u,fr%u\n",
15878 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
15879 assign( frS
, triop( Iop_MulD128
, round
, mkexpr( frA
), mkexpr( frB
) ) );
15881 case 0x222: // ddivq
15882 DIP( "ddivq%s fr%u,fr%u,fr%u\n",
15883 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
15884 assign( frS
, triop( Iop_DivD128
, round
, mkexpr( frA
), mkexpr( frB
) ) );
15888 putDReg_pair( frS_addr
, mkexpr( frS
) );
15890 if (flag_rC
&& clear_CR1
) {
15891 putCR321( 1, mkU8( 0 ) );
15892 putCR0( 1, mkU8( 0 ) );
15898 /* DFP 64-bit logical shift instructions */
15899 static Bool
dis_dfp_shift( UInt prefix
, UInt theInstr
) {
15900 UInt opc2
= ifieldOPClo9( theInstr
);
15901 UChar frS_addr
= ifieldRegDS( theInstr
);
15902 UChar frA_addr
= ifieldRegA( theInstr
);
15903 UChar shift_val
= IFIELD(theInstr
, 10, 6);
15904 UChar flag_rC
= ifieldBIT0( theInstr
);
15906 IRTemp frA
= newTemp( Ity_D64
);
15907 IRTemp frS
= newTemp( Ity_D64
);
15908 Bool clear_CR1
= True
;
15910 /* There is no prefixed version of these instructions. */
15913 assign( frA
, getDReg( frA_addr
) );
15916 case 0x42: // dscli
15917 DIP( "dscli%s fr%u,fr%u,%u\n",
15918 flag_rC
? ".":"", frS_addr
, frA_addr
, shift_val
);
15919 assign( frS
, binop( Iop_ShlD64
, mkexpr( frA
), mkU8( shift_val
) ) );
15921 case 0x62: // dscri
15922 DIP( "dscri%s fr%u,fr%u,%u\n",
15923 flag_rC
? ".":"", frS_addr
, frA_addr
, shift_val
);
15924 assign( frS
, binop( Iop_ShrD64
, mkexpr( frA
), mkU8( shift_val
) ) );
15928 putDReg( frS_addr
, mkexpr( frS
) );
15930 if (flag_rC
&& clear_CR1
) {
15931 putCR321( 1, mkU8( 0 ) );
15932 putCR0( 1, mkU8( 0 ) );
15938 /* Quad DFP logical shift instructions */
15939 static Bool
dis_dfp_shiftq( UInt prefix
, UInt theInstr
) {
15940 UInt opc2
= ifieldOPClo9( theInstr
);
15941 UChar frS_addr
= ifieldRegDS( theInstr
);
15942 UChar frA_addr
= ifieldRegA( theInstr
);
15943 UChar shift_val
= IFIELD(theInstr
, 10, 6);
15944 UChar flag_rC
= ifieldBIT0( theInstr
);
15946 IRTemp frA
= newTemp( Ity_D128
);
15947 IRTemp frS
= newTemp( Ity_D128
);
15948 Bool clear_CR1
= True
;
15950 /* There is no prefixed version of these instructions. */
15953 assign( frA
, getDReg_pair( frA_addr
) );
15956 case 0x42: // dscliq
15957 DIP( "dscliq%s fr%u,fr%u,%u\n",
15958 flag_rC
? ".":"", frS_addr
, frA_addr
, shift_val
);
15959 assign( frS
, binop( Iop_ShlD128
, mkexpr( frA
), mkU8( shift_val
) ) );
15961 case 0x62: // dscriq
15962 DIP( "dscriq%s fr%u,fr%u,%u\n",
15963 flag_rC
? ".":"", frS_addr
, frA_addr
, shift_val
);
15964 assign( frS
, binop( Iop_ShrD128
, mkexpr( frA
), mkU8( shift_val
) ) );
15968 putDReg_pair( frS_addr
, mkexpr( frS
) );
15970 if (flag_rC
&& clear_CR1
) {
15971 putCR321( 1, mkU8( 0 ) );
15972 putCR0( 1, mkU8( 0 ) );
15978 /* DFP 64-bit format conversion instructions */
15979 static Bool
dis_dfp_fmt_conv( UInt prefix
, UInt theInstr
) {
15980 UInt opc2
= ifieldOPClo10( theInstr
);
15981 UChar frS_addr
= ifieldRegDS( theInstr
);
15982 UChar frB_addr
= ifieldRegB( theInstr
);
15983 IRExpr
* round
= get_IR_roundingmode_DFP();
15984 UChar flag_rC
= ifieldBIT0( theInstr
);
15987 Bool clear_CR1
= True
;
15989 /* There is no prefixed version of these instructions. */
15993 case 0x102: //dctdp
15994 DIP( "dctdp%s fr%u,fr%u\n",
15995 flag_rC
? ".":"", frS_addr
, frB_addr
);
15997 frB
= newTemp( Ity_D32
);
15998 frS
= newTemp( Ity_D64
);
15999 assign( frB
, getDReg32( frB_addr
) );
16000 assign( frS
, unop( Iop_D32toD64
, mkexpr( frB
) ) );
16001 putDReg( frS_addr
, mkexpr( frS
) );
16003 case 0x302: // drsp
16004 DIP( "drsp%s fr%u,fr%u\n",
16005 flag_rC
? ".":"", frS_addr
, frB_addr
);
16006 frB
= newTemp( Ity_D64
);
16007 frS
= newTemp( Ity_D32
);
16008 assign( frB
, getDReg( frB_addr
) );
16009 assign( frS
, binop( Iop_D64toD32
, round
, mkexpr( frB
) ) );
16010 putDReg32( frS_addr
, mkexpr( frS
) );
16012 case 0x122: // dctfix
16014 IRTemp tmp
= newTemp( Ity_I64
);
16016 DIP( "dctfix%s fr%u,fr%u\n",
16017 flag_rC
? ".":"", frS_addr
, frB_addr
);
16018 frB
= newTemp( Ity_D64
);
16019 frS
= newTemp( Ity_D64
);
16020 assign( frB
, getDReg( frB_addr
) );
16021 assign( tmp
, binop( Iop_D64toI64S
, round
, mkexpr( frB
) ) );
16022 assign( frS
, unop( Iop_ReinterpI64asD64
, mkexpr( tmp
) ) );
16023 putDReg( frS_addr
, mkexpr( frS
) );
16026 case 0x322: // dcffix
16027 DIP( "dcffix%s fr%u,fr%u\n",
16028 flag_rC
? ".":"", frS_addr
, frB_addr
);
16029 frB
= newTemp( Ity_D64
);
16030 frS
= newTemp( Ity_D64
);
16031 assign( frB
, getDReg( frB_addr
) );
16032 assign( frS
, binop( Iop_I64StoD64
,
16034 unop( Iop_ReinterpD64asI64
, mkexpr( frB
) ) ) );
16035 putDReg( frS_addr
, mkexpr( frS
) );
16039 if (flag_rC
&& clear_CR1
) {
16040 putCR321( 1, mkU8( 0 ) );
16041 putCR0( 1, mkU8( 0 ) );
16047 /* Quad DFP format conversion instructions */
16048 static Bool
dis_dfp_fmt_convq( UInt prefix
, UInt theInstr
,
16049 const VexAbiInfo
* vbi
) {
16050 UInt opc2
= ifieldOPClo10( theInstr
);
16051 UChar frS_addr
= ifieldRegDS( theInstr
);
16052 UChar frB_addr
= ifieldRegB( theInstr
);
16053 IRExpr
* round
= get_IR_roundingmode_DFP();
16054 IRTemp frB64
= newTemp( Ity_D64
);
16055 IRTemp frB128
= newTemp( Ity_D128
);
16056 IRTemp frS64
= newTemp( Ity_D64
);
16057 IRTemp frS128
= newTemp( Ity_D128
);
16058 UChar flag_rC
= ifieldBIT0( theInstr
);
16059 Bool clear_CR1
= True
;
16061 /* There is no prefixed version of these instructions. */
16065 case 0x102: // dctqpq
16066 DIP( "dctqpq%s fr%u,fr%u\n",
16067 flag_rC
? ".":"", frS_addr
, frB_addr
);
16068 assign( frB64
, getDReg( frB_addr
) );
16069 assign( frS128
, unop( Iop_D64toD128
, mkexpr( frB64
) ) );
16070 putDReg_pair( frS_addr
, mkexpr( frS128
) );
16072 case 0x122: // dctfixq
16074 IRTemp tmp
= newTemp( Ity_I64
);
16076 DIP( "dctfixq%s fr%u,fr%u\n",
16077 flag_rC
? ".":"", frS_addr
, frB_addr
);
16078 assign( frB128
, getDReg_pair( frB_addr
) );
16079 assign( tmp
, binop( Iop_D128toI64S
, round
, mkexpr( frB128
) ) );
16080 assign( frS64
, unop( Iop_ReinterpI64asD64
, mkexpr( tmp
) ) );
16081 putDReg( frS_addr
, mkexpr( frS64
) );
16084 case 0x302: //drdpq
16085 DIP( "drdpq%s fr%u,fr%u\n",
16086 flag_rC
? ".":"", frS_addr
, frB_addr
);
16087 assign( frB128
, getDReg_pair( frB_addr
) );
16088 assign( frS64
, binop( Iop_D128toD64
, round
, mkexpr( frB128
) ) );
16089 putDReg( frS_addr
, mkexpr( frS64
) );
16091 case 0x322: // dcffixq
16093 /* Have to introduce an IOP for this instruction so it will work
16094 * on POWER 6 because emulating the instruction requires a POWER 7
16095 * DFP instruction in the emulation code.
16097 DIP( "dcffixq%s fr%u,fr%u\n",
16098 flag_rC
? ".":"", frS_addr
, frB_addr
);
16099 assign( frB64
, getDReg( frB_addr
) );
16100 assign( frS128
, unop( Iop_I64StoD128
,
16101 unop( Iop_ReinterpD64asI64
,
16102 mkexpr( frB64
) ) ) );
16103 putDReg_pair( frS_addr
, mkexpr( frS128
) );
16109 Int opc3
= IFIELD( theInstr
, 16, 5 );
16111 flag_rC
= 0; // These instructions do not set condition codes.
16113 if (opc3
== 0) { // dcffixqq
16114 IRTemp tmpD128
= newTemp( Ity_D128
);
16115 IRTemp vB_src
= newTemp( Ity_V128
);
16117 DIP( "dcffixqq fr%u,v%u\n", frS_addr
, frB_addr
);
16119 assign( vB_src
, getVReg( frB_addr
));
16120 assign( tmpD128
, binop( Iop_I128StoD128
, round
,
16121 unop( Iop_ReinterpV128asI128
,
16122 mkexpr( vB_src
) ) ) );
16123 /* tmp128 is a Dfp 128 value which is held in a hi/lo 64-bit values.
16125 generate_store_DFP_FPRF_value( Ity_D128
, mkexpr( tmpD128
), vbi
);
16126 putDReg_pair( frS_addr
, mkexpr( tmpD128
) );
16128 } else if (opc3
== 1) { // dctfixqq
16129 IRTemp tmp128
= newTemp(Ity_I128
);
16131 DIP( "dctfixqq v%u,fr%u\n", frS_addr
, frB_addr
);
16132 assign( tmp128
, binop( Iop_D128toI128S
, round
,
16133 getDReg_pair( frB_addr
) ) );
16136 unop( Iop_ReinterpI128asV128
, mkexpr( tmp128
) ) );
16139 vex_printf("ERROR: dis_dfp_fmt_convq unknown opc3 = %d value.\n",
16147 if (flag_rC
&& clear_CR1
) {
16148 putCR321( 1, mkU8( 0 ) );
16149 putCR0( 1, mkU8( 0 ) );
16155 static Bool
dis_dfp_round( UInt prefix
, UInt theInstr
) {
16156 UChar frS_addr
= ifieldRegDS(theInstr
);
16157 UChar R
= IFIELD(theInstr
, 16, 1);
16158 UChar RMC
= IFIELD(theInstr
, 9, 2);
16159 UChar frB_addr
= ifieldRegB( theInstr
);
16160 UChar flag_rC
= ifieldBIT0( theInstr
);
16161 IRTemp frB
= newTemp( Ity_D64
);
16162 IRTemp frS
= newTemp( Ity_D64
);
16163 UInt opc2
= ifieldOPClo8( theInstr
);
16164 Bool clear_CR1
= True
;
16166 /* There is no prefixed version of these instructions. */
16170 /* drintn, is the same as drintx. The only difference is this
16171 * instruction does not generate an exception for an inexact operation.
16172 * Currently not supporting inexact exceptions.
16174 case 0x63: // drintx
16175 case 0xE3: // drintn
16176 DIP( "drintx/drintn%s fr%u,fr%u\n",
16177 flag_rC
? ".":"", frS_addr
, frB_addr
);
16179 /* NOTE, this instruction takes a DFP value and rounds to the
16180 * neares floating point integer value, i.e. fractional part
16181 * is zero. The result is a floating point number.
16183 /* pass the value of R and RMC in the same field */
16184 assign( frB
, getDReg( frB_addr
) );
16185 assign( frS
, binop( Iop_RoundD64toInt
,
16186 mkU32( ( R
<< 3 ) | RMC
),
16188 putDReg( frS_addr
, mkexpr( frS
) );
16191 vex_printf("dis_dfp_round(ppc)(opc2)\n");
16195 if (flag_rC
&& clear_CR1
) {
16196 putCR321( 1, mkU8( 0 ) );
16197 putCR0( 1, mkU8( 0 ) );
16203 static Bool
dis_dfp_roundq( UInt prefix
, UInt theInstr
) {
16204 UChar frS_addr
= ifieldRegDS( theInstr
);
16205 UChar frB_addr
= ifieldRegB( theInstr
);
16206 UChar R
= IFIELD(theInstr
, 16, 1);
16207 UChar RMC
= IFIELD(theInstr
, 9, 2);
16208 UChar flag_rC
= ifieldBIT0( theInstr
);
16209 IRTemp frB
= newTemp( Ity_D128
);
16210 IRTemp frS
= newTemp( Ity_D128
);
16211 Bool clear_CR1
= True
;
16212 UInt opc2
= ifieldOPClo8( theInstr
);
16214 /* There is no prefixed version of these instructions. */
16218 /* drintnq, is the same as drintxq. The only difference is this
16219 * instruction does not generate an exception for an inexact operation.
16220 * Currently not supporting inexact exceptions.
16222 case 0x63: // drintxq
16223 case 0xE3: // drintnq
16224 DIP( "drintxq/drintnq%s fr%u,fr%u\n",
16225 flag_rC
? ".":"", frS_addr
, frB_addr
);
16227 /* pass the value of R and RMC in the same field */
16228 assign( frB
, getDReg_pair( frB_addr
) );
16229 assign( frS
, binop( Iop_RoundD128toInt
,
16230 mkU32( ( R
<< 3 ) | RMC
),
16232 putDReg_pair( frS_addr
, mkexpr( frS
) );
16235 vex_printf("dis_dfp_roundq(ppc)(opc2)\n");
16239 if (flag_rC
&& clear_CR1
) {
16240 putCR321( 1, mkU8( 0 ) );
16241 putCR0( 1, mkU8( 0 ) );
16247 static Bool
dis_dfp_quantize_sig_rrnd( UInt prefix
, UInt theInstr
) {
16248 UInt opc2
= ifieldOPClo8( theInstr
);
16249 UChar frS_addr
= ifieldRegDS( theInstr
);
16250 UChar frA_addr
= ifieldRegA( theInstr
);
16251 UChar frB_addr
= ifieldRegB( theInstr
);
16252 UChar flag_rC
= ifieldBIT0( theInstr
);
16253 UInt TE_value
= IFIELD(theInstr
, 16, 4);
16254 UInt TE_sign
= IFIELD(theInstr
, 20, 1);
16255 UInt RMC
= IFIELD(theInstr
, 9, 2);
16256 IRTemp frA
= newTemp( Ity_D64
);
16257 IRTemp frB
= newTemp( Ity_D64
);
16258 IRTemp frS
= newTemp( Ity_D64
);
16259 Bool clear_CR1
= True
;
16261 /* There is no prefixed version of these instructions. */
16264 assign( frB
, getDReg( frB_addr
) );
16267 case 0x43: // dquai
16268 DIP( "dquai%s fr%u,fr%u,fr%u\n",
16269 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
16270 IRTemp TE_I64
= newTemp( Ity_I64
);
16272 /* Generate a reference DFP value frA with the desired exponent
16273 * given by TE using significand from frB. Need to add the bias
16274 * 398 to TE. TE is stored as a 2's complement number.
16276 if (TE_sign
== 1) {
16277 /* Take 2's complement of the 5-bit value and subtract from bias.
16278 * Bias is adjusted for the +1 required when taking 2's complement.
16282 binop( Iop_Sub32
, mkU32( 397 ),
16283 binop( Iop_And32
, mkU32( 0xF ),
16284 unop( Iop_Not32
, mkU32( TE_value
) )
16290 binop( Iop_Add32
, mkU32( 398 ), mkU32( TE_value
) )
16294 assign( frA
, binop( Iop_InsertExpD64
, mkexpr( TE_I64
),
16295 unop( Iop_ReinterpI64asD64
, mkU64( 1 ) ) ) );
16297 assign( frS
, triop( Iop_QuantizeD64
,
16304 DIP( "dqua%s fr%u,fr%u,fr%u\n",
16305 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
16306 assign( frA
, getDReg( frA_addr
) );
16307 assign( frS
, triop( Iop_QuantizeD64
,
16312 case 0x23: // drrnd
16314 IRTemp tmp
= newTemp( Ity_I8
);
16316 DIP( "drrnd%s fr%u,fr%u,fr%u\n",
16317 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
16318 assign( frA
, getDReg( frA_addr
) );
16319 /* Iop_64to8 not supported in 32 bit mode, do it in two steps. */
16320 assign( tmp
, unop( Iop_32to8
,
16322 unop( Iop_ReinterpD64asI64
,
16323 mkexpr( frA
) ) ) ) );
16324 assign( frS
, triop( Iop_SignificanceRoundD64
,
16331 vex_printf("dis_dfp_quantize_sig_rrnd(ppc)(opc2)\n");
16334 putDReg( frS_addr
, mkexpr( frS
) );
16336 if (flag_rC
&& clear_CR1
) {
16337 putCR321( 1, mkU8( 0 ) );
16338 putCR0( 1, mkU8( 0 ) );
16344 static Bool
dis_dfp_quantize_sig_rrndq( UInt prefix
, UInt theInstr
) {
16345 UInt opc2
= ifieldOPClo8( theInstr
);
16346 UChar frS_addr
= ifieldRegDS( theInstr
);
16347 UChar frA_addr
= ifieldRegA( theInstr
);
16348 UChar frB_addr
= ifieldRegB( theInstr
);
16349 UChar flag_rC
= ifieldBIT0( theInstr
);
16350 UInt TE_value
= IFIELD(theInstr
, 16, 4);
16351 UInt TE_sign
= IFIELD(theInstr
, 20, 1);
16352 UInt RMC
= IFIELD(theInstr
, 9, 2);
16353 IRTemp frA
= newTemp( Ity_D128
);
16354 IRTemp frB
= newTemp( Ity_D128
);
16355 IRTemp frS
= newTemp( Ity_D128
);
16356 Bool clear_CR1
= True
;
16358 /* There is no prefixed version of these instructions. */
16361 assign( frB
, getDReg_pair( frB_addr
) );
16364 case 0x43: // dquaiq
16365 DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
16366 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
16367 IRTemp TE_I64
= newTemp( Ity_I64
);
16369 /* Generate a reference DFP value frA with the desired exponent
16370 * given by TE using significand of 1. Need to add the bias
16373 if (TE_sign
== 1) {
16374 /* Take 2's complement of the 5-bit value and subtract from bias.
16375 * Bias adjusted for the +1 required when taking 2's complement.
16379 binop( Iop_Sub32
, mkU32( 6175 ),
16380 binop( Iop_And32
, mkU32( 0xF ),
16381 unop( Iop_Not32
, mkU32( TE_value
) )
16389 mkU32( TE_value
) ) ) );
16393 binop( Iop_InsertExpD128
, mkexpr( TE_I64
),
16394 unop( Iop_D64toD128
,
16395 unop( Iop_ReinterpI64asD64
, mkU64( 1 ) ) ) ) );
16396 assign( frS
, triop( Iop_QuantizeD128
,
16402 DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
16403 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
16404 assign( frA
, getDReg_pair( frA_addr
) );
16405 assign( frS
, triop( Iop_QuantizeD128
,
16410 case 0x23: // drrndq
16412 IRTemp tmp
= newTemp( Ity_I8
);
16414 DIP( "drrndq%s fr%u,fr%u,fr%u\n",
16415 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
16416 assign( frA
, getDReg_pair( frA_addr
) );
16417 assign( tmp
, unop( Iop_32to8
,
16419 unop( Iop_ReinterpD64asI64
,
16420 unop( Iop_D128HItoD64
,
16421 mkexpr( frA
) ) ) ) ) );
16422 assign( frS
, triop( Iop_SignificanceRoundD128
,
16429 vex_printf("dis_dfp_quantize_sig_rrndq(ppc)(opc2)\n");
16432 putDReg_pair( frS_addr
, mkexpr( frS
) );
16434 if (flag_rC
&& clear_CR1
) {
16435 putCR321( 1, mkU8( 0 ) );
16436 putCR0( 1, mkU8( 0 ) );
16442 static Bool
dis_dfp_extract_insert( UInt prefix
, UInt theInstr
) {
16443 UInt opc2
= ifieldOPClo10( theInstr
);
16444 UChar frS_addr
= ifieldRegDS( theInstr
);
16445 UChar frA_addr
= ifieldRegA( theInstr
);
16446 UChar frB_addr
= ifieldRegB( theInstr
);
16447 UChar flag_rC
= ifieldBIT0( theInstr
);
16448 Bool clear_CR1
= True
;
16450 IRTemp frA
= newTemp( Ity_D64
);
16451 IRTemp frB
= newTemp( Ity_D64
);
16452 IRTemp frS
= newTemp( Ity_D64
);
16453 IRTemp tmp
= newTemp( Ity_I64
);
16455 /* There is no prefixed version of these instructions. */
16458 assign( frA
, getDReg( frA_addr
) );
16459 assign( frB
, getDReg( frB_addr
) );
16462 case 0x162: // dxex
16463 DIP( "dxex%s fr%u,fr%u,fr%u\n",
16464 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
16465 assign( tmp
, unop( Iop_ExtractExpD64
, mkexpr( frB
) ) );
16466 assign( frS
, unop( Iop_ReinterpI64asD64
, mkexpr( tmp
) ) );
16468 case 0x362: // diex
16469 DIP( "diex%s fr%u,fr%u,fr%u\n",
16470 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
16471 assign( frS
, binop( Iop_InsertExpD64
,
16472 unop( Iop_ReinterpD64asI64
,
16477 vex_printf("dis_dfp_extract_insert(ppc)(opc2)\n");
16481 putDReg( frS_addr
, mkexpr( frS
) );
16483 if (flag_rC
&& clear_CR1
) {
16484 putCR321( 1, mkU8( 0 ) );
16485 putCR0( 1, mkU8( 0 ) );
16491 static Bool
dis_dfp_extract_insertq( UInt prefix
, UInt theInstr
) {
16492 UInt opc2
= ifieldOPClo10( theInstr
);
16493 UChar frS_addr
= ifieldRegDS( theInstr
);
16494 UChar frA_addr
= ifieldRegA( theInstr
);
16495 UChar frB_addr
= ifieldRegB( theInstr
);
16496 UChar flag_rC
= ifieldBIT0( theInstr
);
16498 IRTemp frA
= newTemp( Ity_D64
);
16499 IRTemp frB
= newTemp( Ity_D128
);
16500 IRTemp frS64
= newTemp( Ity_D64
);
16501 IRTemp frS
= newTemp( Ity_D128
);
16502 IRTemp tmp
= newTemp( Ity_I64
);
16503 Bool clear_CR1
= True
;
16505 /* There is no prefixed version of these instructions. */
16508 assign( frB
, getDReg_pair( frB_addr
) );
16511 case 0x162: // dxexq
16512 DIP( "dxexq%s fr%u,fr%u\n",
16513 flag_rC
? ".":"", frS_addr
, frB_addr
);
16514 /* Instruction actually returns a 64-bit result. So as to be
16515 * consistent and not have to add a new struct, the emulation returns
16516 * the 64-bit result in the upper and lower register.
16518 assign( tmp
, unop( Iop_ExtractExpD128
, mkexpr( frB
) ) );
16519 assign( frS64
, unop( Iop_ReinterpI64asD64
, mkexpr( tmp
) ) );
16520 putDReg( frS_addr
, mkexpr( frS64
) );
16522 case 0x362: // diexq
16523 DIP( "diexq%s fr%u,fr%u,fr%u\n",
16524 flag_rC
? ".":"", frS_addr
, frA_addr
, frB_addr
);
16525 assign( frA
, getDReg( frA_addr
) );
16526 assign( frS
, binop( Iop_InsertExpD128
,
16527 unop( Iop_ReinterpD64asI64
, mkexpr( frA
) ),
16529 putDReg_pair( frS_addr
, mkexpr( frS
) );
16532 vex_printf("dis_dfp_extract_insertq(ppc)(opc2)\n");
16536 if (flag_rC
&& clear_CR1
) {
16537 putCR321( 1, mkU8( 0 ) );
16538 putCR0( 1, mkU8( 0 ) );
16544 /* DFP 64-bit comparison instructions */
16545 static Bool
dis_dfp_compare( UInt prefix
, UInt theInstr
) {
16547 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) ); // AKA BF
16548 UChar frA_addr
= ifieldRegA( theInstr
);
16549 UChar frB_addr
= ifieldRegB( theInstr
);
16550 UInt opc1
= ifieldOPC( theInstr
);
16554 IRTemp ccIR
= newTemp( Ity_I32
);
16555 IRTemp ccPPC32
= newTemp( Ity_I32
);
16557 /* There is no prefixed version of these instructions. */
16560 /* Note: Differences between dcmpu and dcmpo are only in exception
16561 flag settings, which aren't supported anyway. */
16563 case 0x3B: /* dcmpo and dcmpu, DFP 64-bit */
16564 DIP( "dcmpo %u,fr%u,fr%u\n", crfD
, frA_addr
, frB_addr
);
16565 frA
= newTemp( Ity_D64
);
16566 frB
= newTemp( Ity_D64
);
16568 assign( frA
, getDReg( frA_addr
) );
16569 assign( frB
, getDReg( frB_addr
) );
16571 assign( ccIR
, binop( Iop_CmpD64
, mkexpr( frA
), mkexpr( frB
) ) );
16573 case 0x3F: /* dcmpoq and dcmpuq,DFP 128-bit */
16574 DIP( "dcmpoq %u,fr%u,fr%u\n", crfD
, frA_addr
, frB_addr
);
16575 frA
= newTemp( Ity_D128
);
16576 frB
= newTemp( Ity_D128
);
16578 assign( frA
, getDReg_pair( frA_addr
) );
16579 assign( frB
, getDReg_pair( frB_addr
) );
16580 assign( ccIR
, binop( Iop_CmpD128
, mkexpr( frA
), mkexpr( frB
) ) );
16583 vex_printf("dis_dfp_compare(ppc)(opc2)\n");
16587 /* Map compare result from IR to PPC32 */
16589 FP cmp result | PPC | IR
16590 --------------------------
16614 mkU32( 1 ) ) ) ) ) );
16616 putGST_field( PPC_GST_CR
, mkexpr( ccPPC32
), crfD
);
16617 putFPCC( mkexpr( ccPPC32
) );
16621 /* Test class/group/exponent/significance instructions. */
16622 static Bool
dis_dfp_exponent_test ( UInt prefix
, UInt theInstr
)
16624 UChar frA_addr
= ifieldRegA( theInstr
);
16625 UChar frB_addr
= ifieldRegB( theInstr
);
16626 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) );
16627 IRTemp frA
= newTemp( Ity_D64
);
16628 IRTemp frB
= newTemp( Ity_D64
);
16629 IRTemp frA128
= newTemp( Ity_D128
);
16630 IRTemp frB128
= newTemp( Ity_D128
);
16631 UInt opc1
= ifieldOPC( theInstr
);
16632 IRTemp gfield_A
= newTemp( Ity_I32
);
16633 IRTemp gfield_B
= newTemp( Ity_I32
);
16634 IRTemp gfield_mask
= newTemp( Ity_I32
);
16635 IRTemp exponent_A
= newTemp( Ity_I32
);
16636 IRTemp exponent_B
= newTemp( Ity_I32
);
16637 IRTemp A_NaN_true
= newTemp( Ity_I32
);
16638 IRTemp B_NaN_true
= newTemp( Ity_I32
);
16639 IRTemp A_inf_true
= newTemp( Ity_I32
);
16640 IRTemp B_inf_true
= newTemp( Ity_I32
);
16641 IRTemp A_equals_B
= newTemp( Ity_I32
);
16642 IRTemp finite_number
= newTemp( Ity_I32
);
16643 IRTemp cc0
= newTemp( Ity_I32
);
16644 IRTemp cc1
= newTemp( Ity_I32
);
16645 IRTemp cc2
= newTemp( Ity_I32
);
16646 IRTemp cc3
= newTemp( Ity_I32
);
16647 IRTemp cc
= newTemp( Ity_I32
);
16649 /* There is no prefixed version of these instructions. */
16652 /* The dtstex and dtstexg instructions only differ in the size of the
16653 * exponent field. The following switch statement takes care of the size
16654 * specific setup. Once the value of the exponents, the G-field shift
16655 * and mask is setup the remaining code is identical.
16658 case 0x3b: // dtstex Extended instruction setup
16659 DIP("dtstex %u,r%u,r%d\n", crfD
, frA_addr
, frB_addr
);
16660 assign( frA
, getDReg( frA_addr
) );
16661 assign( frB
, getDReg( frB_addr
) );
16662 assign( gfield_mask
, mkU32( DFP_G_FIELD_LONG_MASK
) );
16663 assign(exponent_A
, unop( Iop_64to32
,
16664 unop( Iop_ExtractExpD64
,
16665 mkexpr( frA
) ) ) );
16666 assign(exponent_B
, unop( Iop_64to32
,
16667 unop( Iop_ExtractExpD64
,
16668 mkexpr( frB
) ) ) );
16671 case 0x3F: // dtstexq Quad instruction setup
16672 DIP("dtstexq %u,r%u,r%d\n", crfD
, frA_addr
, frB_addr
);
16673 assign( frA128
, getDReg_pair( frA_addr
) );
16674 assign( frB128
, getDReg_pair( frB_addr
) );
16675 assign( frA
, unop( Iop_D128HItoD64
, mkexpr( frA128
) ) );
16676 assign( frB
, unop( Iop_D128HItoD64
, mkexpr( frB128
) ) );
16677 assign( gfield_mask
, mkU32( DFP_G_FIELD_EXTND_MASK
) );
16678 assign( exponent_A
, unop( Iop_64to32
,
16679 unop( Iop_ExtractExpD128
,
16680 mkexpr( frA128
) ) ) );
16681 assign( exponent_B
, unop( Iop_64to32
,
16682 unop( Iop_ExtractExpD128
,
16683 mkexpr( frB128
) ) ) );
16686 vex_printf("dis_dfp_exponent_test(ppc)(opc2)\n");
16690 /* Extract the Gfield */
16691 assign( gfield_A
, binop( Iop_And32
,
16692 mkexpr( gfield_mask
),
16693 unop( Iop_64HIto32
,
16694 unop( Iop_ReinterpD64asI64
,
16695 mkexpr(frA
) ) ) ) );
16697 assign( gfield_B
, binop( Iop_And32
,
16698 mkexpr( gfield_mask
),
16699 unop( Iop_64HIto32
,
16700 unop( Iop_ReinterpD64asI64
,
16701 mkexpr(frB
) ) ) ) );
16703 /* check for NAN */
16704 assign( A_NaN_true
, binop(Iop_Or32
,
16706 binop( Iop_CmpEQ32
,
16707 mkexpr( gfield_A
),
16708 mkU32( 0x7C000000 ) ) ),
16710 binop( Iop_CmpEQ32
,
16711 mkexpr( gfield_A
),
16712 mkU32( 0x7E000000 ) )
16714 assign( B_NaN_true
, binop(Iop_Or32
,
16716 binop( Iop_CmpEQ32
,
16717 mkexpr( gfield_B
),
16718 mkU32( 0x7C000000 ) ) ),
16720 binop( Iop_CmpEQ32
,
16721 mkexpr( gfield_B
),
16722 mkU32( 0x7E000000 ) )
16725 /* check for infinity */
16726 assign( A_inf_true
,
16728 binop( Iop_CmpEQ32
,
16729 mkexpr( gfield_A
),
16730 mkU32( 0x78000000 ) ) ) );
16732 assign( B_inf_true
,
16734 binop( Iop_CmpEQ32
,
16735 mkexpr( gfield_B
),
16736 mkU32( 0x78000000 ) ) ) );
16738 assign( finite_number
,
16742 mkexpr( A_NaN_true
),
16743 mkexpr( B_NaN_true
) ),
16745 mkexpr( A_inf_true
),
16746 mkexpr( B_inf_true
) ) ) ) );
16748 /* Calculate the condition code bits
16749 * If QNaN,SNaN, +infinity, -infinity then cc0, cc1 and cc2 are zero
16750 * regardless of the value of the comparisons and cc3 is 1. Otherwise,
16751 * cc0, cc1 and cc0 reflect the results of the comparisons.
16753 assign( A_equals_B
,
16756 binop( Iop_CmpEQ32
,
16757 mkexpr( exponent_A
),
16758 mkexpr( exponent_B
) ) ),
16761 mkexpr( A_inf_true
),
16762 mkexpr( B_inf_true
) ),
16764 mkexpr( A_NaN_true
),
16765 mkexpr( B_NaN_true
) ) ) ) );
16767 assign( cc0
, binop( Iop_And32
,
16768 mkexpr( finite_number
),
16771 binop( Iop_CmpLT32U
,
16772 mkexpr( exponent_A
),
16773 mkexpr( exponent_B
) ) ),
16776 assign( cc1
, binop( Iop_And32
,
16777 mkexpr( finite_number
),
16780 binop( Iop_CmpLT32U
,
16781 mkexpr( exponent_B
),
16782 mkexpr( exponent_A
) ) ),
16785 assign( cc2
, binop( Iop_Shl32
,
16787 mkexpr( A_equals_B
),
16791 assign( cc3
, binop( Iop_And32
,
16792 unop( Iop_Not32
, mkexpr( A_equals_B
) ),
16797 mkexpr ( A_inf_true
),
16798 mkexpr ( B_inf_true
) ),
16800 mkexpr ( A_NaN_true
),
16801 mkexpr ( B_NaN_true
) ) )
16804 /* store the condition code */
16805 assign( cc
, binop( Iop_Or32
,
16811 mkexpr( cc3
) ) ) ) );
16812 putGST_field( PPC_GST_CR
, mkexpr( cc
), crfD
);
16813 putFPCC( mkexpr( cc
) );
16817 /* Test class/group/exponent/significance instructions. */
16818 static Bool
dis_dfp_class_test ( UInt prefix
, UInt theInstr
)
16820 UChar frA_addr
= ifieldRegA( theInstr
);
16821 IRTemp frA
= newTemp( Ity_D64
);
16822 IRTemp abs_frA
= newTemp( Ity_D64
);
16823 IRTemp frAI64_hi
= newTemp( Ity_I64
);
16824 IRTemp frAI64_lo
= newTemp( Ity_I64
);
16825 UInt opc1
= ifieldOPC( theInstr
);
16826 UInt opc2
= ifieldOPClo9( theInstr
);
16827 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) ); // AKA BF
16828 UInt DCM
= IFIELD( theInstr
, 10, 6 );
16829 IRTemp DCM_calc
= newTemp( Ity_I32
);
16832 IRTemp min_subnormalD64
= newTemp( Ity_D64
);
16833 IRTemp min_subnormalD128
= newTemp( Ity_D128
);
16834 IRTemp significand64
= newTemp( Ity_D64
);
16835 IRTemp significand128
= newTemp( Ity_D128
);
16836 IRTemp exp_min_normal
= newTemp( Ity_I64
);
16837 IRTemp exponent
= newTemp( Ity_I32
);
16839 IRTemp infinity_true
= newTemp( Ity_I32
);
16840 IRTemp SNaN_true
= newTemp( Ity_I32
);
16841 IRTemp QNaN_true
= newTemp( Ity_I32
);
16842 IRTemp subnormal_true
= newTemp( Ity_I32
);
16843 IRTemp normal_true
= newTemp( Ity_I32
);
16844 IRTemp extreme_true
= newTemp( Ity_I32
);
16845 IRTemp lmd
= newTemp( Ity_I32
);
16846 IRTemp lmd_zero_true
= newTemp( Ity_I32
);
16847 IRTemp zero_true
= newTemp( Ity_I32
);
16848 IRTemp sign
= newTemp( Ity_I32
);
16849 IRTemp field
= newTemp( Ity_I32
);
16850 IRTemp ccIR_zero
= newTemp( Ity_I32
);
16851 IRTemp ccIR_subnormal
= newTemp( Ity_I32
);
16853 /* UInt size = DFP_LONG; JRS:unused */
16854 IRTemp gfield
= newTemp( Ity_I32
);
16855 IRTemp gfield_0_4_shift
= newTemp( Ity_I8
);
16856 IRTemp gfield_mask
= newTemp( Ity_I32
);
16857 IRTemp dcm0
= newTemp( Ity_I32
);
16858 IRTemp dcm1
= newTemp( Ity_I32
);
16859 IRTemp dcm2
= newTemp( Ity_I32
);
16860 IRTemp dcm3
= newTemp( Ity_I32
);
16861 IRTemp dcm4
= newTemp( Ity_I32
);
16862 IRTemp dcm5
= newTemp( Ity_I32
);
16864 /* There is no prefixed version of these instructions. */
16867 /* The only difference between the dtstdc and dtstdcq instructions is
16868 * size of the T and G fields. The calculation of the 4 bit field
16869 * is the same. Setup the parameters and values that are DFP size
16870 * specific. The rest of the code is independent of the DFP size.
16872 * The Io_CmpD64 is used below. The instruction sets the ccIR values.
16873 * The interpretation of the ccIR values is as follows:
16875 * DFP cmp result | IR
16876 * --------------------------
16883 assign( frA
, getDReg( frA_addr
) );
16884 assign( frAI64_hi
, unop( Iop_ReinterpD64asI64
, mkexpr( frA
) ) );
16886 assign( abs_frA
, unop( Iop_ReinterpI64asD64
,
16888 unop( Iop_ReinterpD64asI64
,
16890 mkU64( 0x7FFFFFFFFFFFFFFFULL
) ) ) );
16891 assign( gfield_0_4_shift
, mkU8( 31 - 5 ) ); // G-field[0:4]
16893 case 0x3b: // dtstdc, dtstdg
16894 DIP("dtstd%s %u,r%u,%u\n", opc2
== 0xc2 ? "c" : "g",
16895 crfD
, frA_addr
, DCM
);
16896 /* setup the parameters for the long format of the two instructions */
16897 assign( frAI64_lo
, mkU64( 0 ) );
16898 assign( gfield_mask
, mkU32( DFP_G_FIELD_LONG_MASK
) );
16899 max_exp
= DFP_LONG_EXP_MAX
;
16900 min_exp
= DFP_LONG_EXP_MIN
;
16902 assign( exponent
, unop( Iop_64to32
,
16903 unop( Iop_ExtractExpD64
,
16904 mkexpr( frA
) ) ) );
16905 assign( significand64
,
16906 unop( Iop_ReinterpI64asD64
,
16907 mkU64( 0x2234000000000001ULL
) ) ); // dfp 1.0
16908 assign( exp_min_normal
,mkU64( 398 - 383 ) );
16909 assign( min_subnormalD64
,
16910 binop( Iop_InsertExpD64
,
16911 mkexpr( exp_min_normal
),
16912 mkexpr( significand64
) ) );
16914 assign( ccIR_subnormal
,
16917 mkexpr( min_subnormalD64
) ) );
16919 /* compare absolute value of frA with zero */
16923 unop( Iop_ReinterpI64asD64
,
16924 mkU64( 0x2238000000000000ULL
) ) ) );
16926 /* size = DFP_LONG; JRS: unused */
16929 case 0x3F: // dtstdcq, dtstdgq
16930 DIP("dtstd%sq %u,r%u,%u\n", opc2
== 0xc2 ? "c" : "g",
16931 crfD
, frA_addr
, DCM
);
16932 /* setup the parameters for the extended format of the
16935 assign( frAI64_lo
, unop( Iop_ReinterpD64asI64
,
16936 getDReg( frA_addr
+1 ) ) );
16938 assign( gfield_mask
, mkU32( DFP_G_FIELD_EXTND_MASK
) );
16939 max_exp
= DFP_EXTND_EXP_MAX
;
16940 min_exp
= DFP_EXTND_EXP_MIN
;
16941 assign( exponent
, unop( Iop_64to32
,
16942 unop( Iop_ExtractExpD128
,
16943 getDReg_pair( frA_addr
) ) ) );
16945 /* create quand exponent for minimum normal number */
16946 assign( exp_min_normal
, mkU64( 6176 - 6143 ) );
16947 assign( significand128
,
16948 unop( Iop_D64toD128
,
16949 unop( Iop_ReinterpI64asD64
,
16950 mkU64( 0x2234000000000001ULL
) ) ) ); // dfp 1.0
16952 assign( min_subnormalD128
,
16953 binop( Iop_InsertExpD128
,
16954 mkexpr( exp_min_normal
),
16955 mkexpr( significand128
) ) );
16957 assign( ccIR_subnormal
,
16958 binop( Iop_CmpD128
,
16959 binop( Iop_D64HLtoD128
,
16960 unop( Iop_ReinterpI64asD64
,
16962 unop( Iop_ReinterpD64asI64
,
16964 mkU64( 0x7FFFFFFFFFFFFFFFULL
) ) ),
16965 getDReg( frA_addr
+1 ) ),
16966 mkexpr( min_subnormalD128
) ) );
16968 binop( Iop_CmpD128
,
16969 binop( Iop_D64HLtoD128
,
16971 getDReg( frA_addr
+1 ) ),
16972 unop( Iop_D64toD128
,
16973 unop( Iop_ReinterpI64asD64
,
16974 mkU64( 0x0ULL
) ) ) ) );
16976 /* size = DFP_EXTND; JRS:unused */
16979 vex_printf("dis_dfp_class_test(ppc)(opc2)\n");
16983 /* The G-field is in the upper 32-bits. The I64 logical operations
16984 * do not seem to be supported in 32-bit mode so keep things as 32-bit
16987 assign( gfield
, binop( Iop_And32
,
16988 mkexpr( gfield_mask
),
16989 unop( Iop_64HIto32
,
16990 mkexpr(frAI64_hi
) ) ) );
16992 /* There is a lot of code that is the same to do the class and group
16993 * instructions. Later there is an if statement to handle the specific
16996 * Will be using I32 values, compares, shifts and logical operations for
16997 * this code as the 64-bit compare, shifts, logical operations are not
16998 * supported in 32-bit mode.
17001 /* Check the bits for Infinity, QNaN or Signaling NaN */
17002 assign( infinity_true
,
17004 binop( Iop_CmpEQ32
,
17006 mkU32( 0x7C000000 ),
17007 mkexpr( gfield
) ),
17008 mkU32( 0x78000000 ) ) ) );
17012 binop( Iop_CmpEQ32
,
17014 mkU32( 0x7E000000 ),
17015 mkexpr( gfield
) ),
17016 mkU32( 0x7E000000 ) ) ) );
17021 binop( Iop_CmpEQ32
,
17023 mkU32( 0x7E000000 ),
17024 mkexpr( gfield
) ),
17025 mkU32( 0x7C000000 ) ) ),
17027 mkexpr( SNaN_true
) ) ) );
17032 binop( Iop_CmpEQ32
,
17033 mkexpr( ccIR_zero
),
17034 mkU32( 0x40 ) ) ), // ccIR code for Equal
17037 mkexpr( infinity_true
),
17039 mkexpr( QNaN_true
),
17040 mkexpr( SNaN_true
) ) ) ) ) );
17042 /* Do compare of frA the minimum normal value. Comparison is size
17043 * depenent and was done above to get the ccIR value.
17045 assign( subnormal_true
,
17049 binop( Iop_CmpEQ32
,
17050 mkexpr( ccIR_subnormal
),
17051 mkU32( 0x40 ) ) ), // ccIR code for Equal
17053 binop( Iop_CmpEQ32
,
17054 mkexpr( ccIR_subnormal
),
17055 mkU32( 0x1 ) ) ) ), // ccIR code for LT
17059 mkexpr( infinity_true
),
17060 mkexpr( zero_true
) ),
17062 mkexpr( QNaN_true
),
17063 mkexpr( SNaN_true
) ) ) ) ) );
17065 /* Normal number is not subnormal, infinity, NaN or Zero */
17066 assign( normal_true
,
17070 mkexpr( infinity_true
),
17071 mkexpr( zero_true
) ),
17073 mkexpr( subnormal_true
),
17075 mkexpr( QNaN_true
),
17076 mkexpr( SNaN_true
) ) ) ) ) );
17078 /* Calculate the DCM bit field based on the tests for the specific
17081 if (opc2
== 0xC2) { // dtstdc, dtstdcq
17082 /* DCM[0:5] Bit Data Class definition
17091 assign( dcm0
, binop( Iop_Shl32
,
17092 mkexpr( zero_true
),
17094 assign( dcm1
, binop( Iop_Shl32
,
17096 mkexpr( subnormal_true
),
17099 assign( dcm2
, binop( Iop_Shl32
,
17101 mkexpr( normal_true
),
17104 assign( dcm3
, binop( Iop_Shl32
,
17106 mkexpr( infinity_true
),
17109 assign( dcm4
, binop( Iop_Shl32
,
17111 mkexpr( QNaN_true
),
17114 assign( dcm5
, binop( Iop_And32
, mkexpr( SNaN_true
), mkU32( 1 ) ) );
17116 } else if (opc2
== 0xE2) { // dtstdg, dtstdgq
17117 /* check if the exponent is extreme */
17118 assign( extreme_true
, binop( Iop_Or32
,
17120 binop( Iop_CmpEQ32
,
17121 mkexpr( exponent
),
17122 mkU32( max_exp
) ) ),
17124 binop( Iop_CmpEQ32
,
17125 mkexpr( exponent
),
17126 mkU32( min_exp
) ) ) ) );
17128 /* Check if LMD is zero */
17129 Get_lmd( &lmd
, binop( Iop_Shr32
,
17130 mkexpr( gfield
), mkU8( 31 - 5 ) ) );
17132 assign( lmd_zero_true
, unop( Iop_1Sto32
,
17133 binop( Iop_CmpEQ32
,
17137 /* DCM[0:5] Bit Data Class definition
17138 * 0 Zero with non-extreme exponent
17139 * 1 Zero with extreme exponent
17140 * 2 Subnormal or (Normal with extreme exponent)
17141 * 3 Normal with non-extreme exponent and
17142 * leftmost zero digit in significand
17143 * 4 Normal with non-extreme exponent and
17144 * leftmost nonzero digit in significand
17145 * 5 Special symbol (Infinity, QNaN, or SNaN)
17147 assign( dcm0
, binop( Iop_Shl32
,
17151 mkexpr( extreme_true
) ),
17152 mkexpr( zero_true
) ),
17156 assign( dcm1
, binop( Iop_Shl32
,
17159 mkexpr( extreme_true
),
17160 mkexpr( zero_true
) ),
17164 assign( dcm2
, binop( Iop_Shl32
,
17168 mkexpr( extreme_true
),
17169 mkexpr( normal_true
) ),
17170 mkexpr( subnormal_true
) ),
17174 assign( dcm3
, binop( Iop_Shl32
,
17179 mkexpr( extreme_true
) ),
17180 mkexpr( normal_true
) ),
17182 binop( Iop_CmpEQ32
,
17188 assign( dcm4
, binop( Iop_Shl32
,
17193 mkexpr( extreme_true
) ),
17194 mkexpr( normal_true
) ),
17196 binop( Iop_CmpNE32
,
17202 assign( dcm5
, binop( Iop_And32
,
17204 mkexpr( SNaN_true
),
17206 mkexpr( QNaN_true
),
17207 mkexpr( infinity_true
) ) ),
17211 /* create DCM field */
17223 mkexpr( dcm5
) ) ) ) ) ) );
17225 /* Get the sign of the DFP number, ignore sign for QNaN */
17228 binop( Iop_CmpEQ32
,
17230 unop( Iop_64HIto32
, mkexpr( frAI64_hi
) ),
17234 /* This instruction generates a four bit field to be stored in the
17235 * condition code register. The condition code register consists of 7
17236 * fields. The field to be written to is specified by the BF (AKA crfD)
17239 * The field layout is as follows:
17242 * 0000 Operand positive with no match
17243 * 0100 Operand positive with at least one match
17244 * 0001 Operand negative with no match
17245 * 0101 Operand negative with at least one match
17247 assign( field
, binop( Iop_Or32
,
17253 binop( Iop_CmpNE32
,
17256 mkexpr( DCM_calc
) ),
17260 putGST_field( PPC_GST_CR
, mkexpr( field
), crfD
);
17261 putFPCC( mkexpr( field
) );
17265 static Bool
dis_dfp_bcd( UInt prefix
, UInt theInstr
) {
17266 UInt opc2
= ifieldOPClo10( theInstr
);
17267 ULong sp
= IFIELD(theInstr
, 19, 2);
17268 ULong s
= IFIELD(theInstr
, 20, 1);
17269 UChar frT_addr
= ifieldRegDS( theInstr
);
17270 UChar frB_addr
= ifieldRegB( theInstr
);
17271 IRTemp frB
= newTemp( Ity_D64
);
17272 IRTemp frBI64
= newTemp( Ity_I64
);
17273 IRTemp result
= newTemp( Ity_I64
);
17274 IRTemp resultD64
= newTemp( Ity_D64
);
17275 IRTemp bcd64
= newTemp( Ity_I64
);
17276 IRTemp bcd_u
= newTemp( Ity_I32
);
17277 IRTemp bcd_l
= newTemp( Ity_I32
);
17278 IRTemp dbcd_u
= newTemp( Ity_I32
);
17279 IRTemp dbcd_l
= newTemp( Ity_I32
);
17280 IRTemp lmd
= newTemp( Ity_I32
);
17282 /* There is no prefixed version of these instructions. */
17285 assign( frB
, getDReg( frB_addr
) );
17286 assign( frBI64
, unop( Iop_ReinterpD64asI64
, mkexpr( frB
) ) );
17289 case 0x142: // ddedpd DFP Decode DPD to BCD
17290 DIP( "ddedpd %llu,r%u,r%u\n", sp
, frT_addr
, frB_addr
);
17292 assign( bcd64
, unop( Iop_DPBtoBCD
, mkexpr( frBI64
) ) );
17293 assign( bcd_u
, unop( Iop_64HIto32
, mkexpr( bcd64
) ) );
17294 assign( bcd_l
, unop( Iop_64to32
, mkexpr( bcd64
) ) );
17296 if ( ( sp
== 0 ) || ( sp
== 1 ) ) {
17297 /* Unsigned BCD string */
17300 unop( Iop_64HIto32
, mkexpr( frBI64
) ),
17301 mkU8( 31 - 5 ) ) ); // G-field[0:4]
17304 binop( Iop_32HLto64
,
17306 binop( Iop_Shl32
, mkexpr( lmd
), mkU8( 28 ) ),
17308 mkexpr( bcd_l
) ) );
17311 /* Signed BCD string, the cases for sp 2 and 3 only differ in how
17312 * the positive and negative values are encoded in the least
17313 * significant bits.
17315 IRTemp sign
= newTemp( Ity_I32
);
17318 /* Positive sign = 0xC, negative sign = 0xD */
17323 unop( Iop_64HIto32
, mkexpr( frBI64
) ),
17327 } else if ( sp
== 3 ) {
17328 /* Positive sign = 0xF, negative sign = 0xD */
17329 IRTemp tmp32
= newTemp( Ity_I32
);
17331 /* Complement sign bit then OR into bit position 1 */
17335 unop( Iop_64HIto32
, mkexpr( frBI64
) ),
17339 assign( sign
, binop( Iop_Or32
, mkexpr( tmp32
), mkU32( 0xD ) ) );
17342 vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
17345 /* Put sign in bottom 4 bits, move most significant 4-bits from
17349 binop( Iop_32HLto64
,
17364 putDReg( frT_addr
, unop( Iop_ReinterpI64asD64
, mkexpr( result
) ) );
17367 case 0x342: // denbcd DFP Encode BCD to DPD
17369 IRTemp valid_mask
= newTemp( Ity_I32
);
17370 IRTemp invalid_mask
= newTemp( Ity_I32
);
17371 IRTemp without_lmd
= newTemp( Ity_I64
);
17372 IRTemp tmp64
= newTemp( Ity_I64
);
17373 IRTemp dbcd64
= newTemp( Ity_I64
);
17374 IRTemp left_exp
= newTemp( Ity_I32
);
17375 IRTemp g0_4
= newTemp( Ity_I32
);
17377 DIP( "denbcd %llu,r%u,r%u\n", s
, frT_addr
, frB_addr
);
17380 /* Unsigned BCD string */
17381 assign( dbcd64
, unop( Iop_BCDtoDPB
, mkexpr(frBI64
) ) );
17382 assign( dbcd_u
, unop( Iop_64HIto32
, mkexpr( dbcd64
) ) );
17383 assign( dbcd_l
, unop( Iop_64to32
, mkexpr( dbcd64
) ) );
17388 unop( Iop_64HIto32
, mkexpr( frBI64
) ),
17389 mkU32( 0xF0000000 ) ),
17392 assign( invalid_mask
,
17393 bcd_digit_inval( unop( Iop_64HIto32
, mkexpr( frBI64
) ),
17394 unop( Iop_64to32
, mkexpr( frBI64
) ) ) );
17395 assign( valid_mask
, unop( Iop_Not32
, mkexpr( invalid_mask
) ) );
17397 assign( without_lmd
,
17398 unop( Iop_ReinterpD64asI64
,
17399 binop( Iop_InsertExpD64
,
17400 mkU64( DFP_LONG_BIAS
),
17401 unop( Iop_ReinterpI64asD64
,
17402 binop( Iop_32HLto64
,
17404 mkexpr( dbcd_l
) ) ) ) ) );
17408 unop( Iop_64HIto32
, mkexpr( without_lmd
) ),
17409 mkU32( 0x60000000 ) ),
17414 Gfield_encoding( mkexpr( left_exp
), mkexpr( lmd
) ),
17418 binop( Iop_32HLto64
,
17421 unop( Iop_64HIto32
,
17422 mkexpr( without_lmd
) ),
17423 mkU32( 0x83FFFFFF ) ),
17425 unop( Iop_64to32
, mkexpr( without_lmd
) ) ) );
17427 } else if ( s
== 1 ) {
17428 IRTemp sign
= newTemp( Ity_I32
);
17429 IRTemp sign_bit
= newTemp( Ity_I32
);
17430 IRTemp pos_sign_mask
= newTemp( Ity_I32
);
17431 IRTemp neg_sign_mask
= newTemp( Ity_I32
);
17432 IRTemp tmp
= newTemp( Ity_I64
);
17434 /* Signed BCD string, least significant 4 bits are sign bits
17435 * positive sign = 0xC, negative sign = 0xD
17437 assign( tmp
, unop( Iop_BCDtoDPB
,
17438 binop( Iop_32HLto64
,
17440 unop( Iop_64HIto32
,
17441 mkexpr( frBI64
) ),
17446 mkexpr( frBI64
) ),
17449 unop( Iop_64HIto32
,
17450 mkexpr( frBI64
) ),
17451 mkU8( 28 ) ) ) ) ) );
17453 assign( dbcd_u
, unop( Iop_64HIto32
, mkexpr( tmp
) ) );
17454 assign( dbcd_l
, unop( Iop_64to32
, mkexpr( tmp
) ) );
17456 /* Get the sign of the BCD string. */
17459 unop( Iop_64to32
, mkexpr( frBI64
) ),
17462 assign( neg_sign_mask
, Generate_neg_sign_mask( mkexpr( sign
) ) );
17463 assign( pos_sign_mask
, Generate_pos_sign_mask( mkexpr( sign
) ) );
17465 Generate_sign_bit( mkexpr( pos_sign_mask
),
17466 mkexpr( neg_sign_mask
) ) );
17468 /* Check for invalid sign and BCD digit. Don't check the bottom
17469 * four bits of bcd_l as that is the sign value.
17471 assign( invalid_mask
,
17473 bcd_digit_inval( unop( Iop_64HIto32
,
17474 mkexpr( frBI64
) ),
17477 mkexpr( frBI64
) ),
17479 mkexpr( pos_sign_mask
),
17480 mkexpr( neg_sign_mask
) ) );
17482 assign( valid_mask
, unop( Iop_Not32
, mkexpr( invalid_mask
) ) );
17484 /* Generate the result assuming the sign value was valid. */
17486 unop( Iop_ReinterpD64asI64
,
17487 binop( Iop_InsertExpD64
,
17488 mkU64( DFP_LONG_BIAS
),
17489 unop( Iop_ReinterpI64asD64
,
17490 binop( Iop_32HLto64
,
17493 mkexpr( sign_bit
) ),
17494 mkexpr( dbcd_l
) ) ) ) ) );
17497 /* Generate the value to store depending on the validity of the
17498 * sign value and the validity of the BCD digits.
17501 unop( Iop_ReinterpI64asD64
,
17502 binop( Iop_32HLto64
,
17505 mkexpr( valid_mask
),
17506 unop( Iop_64HIto32
,
17507 mkexpr( tmp64
) ) ),
17509 mkU32( 0x7C000000 ),
17510 mkexpr( invalid_mask
) ) ),
17513 mkexpr( valid_mask
),
17514 unop( Iop_64to32
, mkexpr( tmp64
) ) ),
17517 mkexpr( invalid_mask
) ) ) ) ) );
17518 putDReg( frT_addr
, mkexpr( resultD64
) );
17522 vpanic( "ERROR: dis_dfp_bcd(ppc), undefined opc2 case " );
17528 static Bool
dis_dfp_bcdq( UInt prefix
, UInt theInstr
)
17530 UInt opc2
= ifieldOPClo10( theInstr
);
17531 ULong sp
= IFIELD(theInstr
, 19, 2);
17532 ULong s
= IFIELD(theInstr
, 20, 1);
17533 IRTemp frB_hi
= newTemp( Ity_D64
);
17534 IRTemp frB_lo
= newTemp( Ity_D64
);
17535 IRTemp frBI64_hi
= newTemp( Ity_I64
);
17536 IRTemp frBI64_lo
= newTemp( Ity_I64
);
17537 UChar frT_addr
= ifieldRegDS( theInstr
);
17538 UChar frB_addr
= ifieldRegB( theInstr
);
17540 IRTemp lmd
= newTemp( Ity_I32
);
17541 IRTemp result_hi
= newTemp( Ity_I64
);
17542 IRTemp result_lo
= newTemp( Ity_I64
);
17544 /* There is no prefixed version of these instructions. */
17547 assign( frB_hi
, getDReg( frB_addr
) );
17548 assign( frB_lo
, getDReg( frB_addr
+ 1 ) );
17549 assign( frBI64_hi
, unop( Iop_ReinterpD64asI64
, mkexpr( frB_hi
) ) );
17550 assign( frBI64_lo
, unop( Iop_ReinterpD64asI64
, mkexpr( frB_lo
) ) );
17553 case 0x142: // ddedpdq DFP Decode DPD to BCD
17555 IRTemp low_60_u
= newTemp( Ity_I32
);
17556 IRTemp low_60_l
= newTemp( Ity_I32
);
17557 IRTemp mid_60_u
= newTemp( Ity_I32
);
17558 IRTemp mid_60_l
= newTemp( Ity_I32
);
17559 IRTemp top_12_l
= newTemp( Ity_I32
);
17561 DIP( "ddedpdq %llu,r%u,r%u\n", sp
, frT_addr
, frB_addr
);
17563 /* Note, instruction only stores the lower 32 BCD digits in
17566 Generate_132_bit_bcd_string( mkexpr( frBI64_hi
),
17567 mkexpr( frBI64_lo
),
17574 if ( ( sp
== 0 ) || ( sp
== 1 ) ) {
17575 /* Unsigned BCD string */
17577 binop( Iop_32HLto64
,
17580 mkexpr( top_12_l
),
17583 mkexpr( mid_60_u
),
17587 mkexpr( mid_60_u
),
17590 mkexpr( mid_60_l
),
17594 binop( Iop_32HLto64
,
17597 mkexpr( mid_60_l
),
17599 mkexpr( low_60_u
) ),
17600 mkexpr( low_60_l
) ) );
17603 /* Signed BCD string, the cases for sp 2 and 3 only differ in how
17604 * the positive and negative values are encoded in the least
17605 * significant bits.
17607 IRTemp sign
= newTemp( Ity_I32
);
17610 /* Positive sign = 0xC, negative sign = 0xD */
17614 unop( Iop_64HIto32
, mkexpr( frBI64_hi
) ),
17618 } else if ( sp
== 3 ) {
17619 IRTemp tmp32
= newTemp( Ity_I32
);
17621 /* Positive sign = 0xF, negative sign = 0xD.
17622 * Need to complement sign bit then OR into bit position 1.
17627 unop( Iop_64HIto32
, mkexpr( frBI64_hi
) ),
17631 assign( sign
, binop( Iop_Or32
, mkexpr( tmp32
), mkU32( 0xD ) ) );
17634 vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
17638 binop( Iop_32HLto64
,
17641 mkexpr( top_12_l
),
17643 mkexpr( mid_60_u
) ),
17644 mkexpr( mid_60_l
) ) );
17647 binop( Iop_32HLto64
,
17650 mkexpr( low_60_u
),
17653 mkexpr( low_60_l
),
17657 mkexpr( low_60_l
),
17659 mkexpr( sign
) ) ) );
17662 putDReg( frT_addr
, unop( Iop_ReinterpI64asD64
, mkexpr( result_hi
) ) );
17663 putDReg( frT_addr
+ 1,
17664 unop( Iop_ReinterpI64asD64
, mkexpr( result_lo
) ) );
17667 case 0x342: // denbcdq DFP Encode BCD to DPD
17669 IRTemp valid_mask
= newTemp( Ity_I32
);
17670 IRTemp invalid_mask
= newTemp( Ity_I32
);
17671 IRTemp result128
= newTemp( Ity_D128
);
17672 IRTemp dfp_significand
= newTemp( Ity_D128
);
17673 IRTemp tmp_hi
= newTemp( Ity_I64
);
17674 IRTemp tmp_lo
= newTemp( Ity_I64
);
17675 IRTemp dbcd_top_l
= newTemp( Ity_I32
);
17676 IRTemp dbcd_mid_u
= newTemp( Ity_I32
);
17677 IRTemp dbcd_mid_l
= newTemp( Ity_I32
);
17678 IRTemp dbcd_low_u
= newTemp( Ity_I32
);
17679 IRTemp dbcd_low_l
= newTemp( Ity_I32
);
17680 IRTemp bcd_top_8
= newTemp( Ity_I64
);
17681 IRTemp bcd_mid_60
= newTemp( Ity_I64
);
17682 IRTemp bcd_low_60
= newTemp( Ity_I64
);
17683 IRTemp sign_bit
= newTemp( Ity_I32
);
17684 IRTemp tmptop10
= newTemp( Ity_I64
);
17685 IRTemp tmpmid50
= newTemp( Ity_I64
);
17686 IRTemp tmplow50
= newTemp( Ity_I64
);
17687 IRTemp inval_bcd_digit_mask
= newTemp( Ity_I32
);
17689 DIP( "denbcd %llu,r%u,r%u\n", s
, frT_addr
, frB_addr
);
17692 /* Unsigned BCD string */
17693 assign( sign_bit
, mkU32( 0 ) ); // set to zero for unsigned string
17696 binop( Iop_32HLto64
,
17700 unop( Iop_64HIto32
,
17701 mkexpr( frBI64_hi
) ),
17703 mkU32( 0xFF ) ) ) );
17704 assign( bcd_mid_60
,
17705 binop( Iop_32HLto64
,
17709 mkexpr( frBI64_hi
) ),
17712 unop( Iop_64HIto32
,
17713 mkexpr( frBI64_hi
) ),
17718 mkexpr( frBI64_hi
) ),
17721 unop( Iop_64HIto32
,
17722 mkexpr( frBI64_lo
) ),
17723 mkU8( 28 ) ) ) ) );
17725 /* Note, the various helper functions ignores top 4-bits */
17726 assign( bcd_low_60
, mkexpr( frBI64_lo
) );
17728 assign( tmptop10
, unop( Iop_BCDtoDPB
, mkexpr( bcd_top_8
) ) );
17729 assign( dbcd_top_l
, unop( Iop_64to32
, mkexpr( tmptop10
) ) );
17731 assign( tmpmid50
, unop( Iop_BCDtoDPB
, mkexpr( bcd_mid_60
) ) );
17732 assign( dbcd_mid_u
, unop( Iop_64HIto32
, mkexpr( tmpmid50
) ) );
17733 assign( dbcd_mid_l
, unop( Iop_64to32
, mkexpr( tmpmid50
) ) );
17735 assign( tmplow50
, unop( Iop_BCDtoDPB
, mkexpr( bcd_low_60
) ) );
17736 assign( dbcd_low_u
, unop( Iop_64HIto32
, mkexpr( tmplow50
) ) );
17737 assign( dbcd_low_l
, unop( Iop_64to32
, mkexpr( tmplow50
) ) );
17739 /* The entire BCD string fits in lower 110-bits. The LMD = 0,
17740 * value is not part of the final result. Only the right most
17741 * BCD digits are stored.
17743 assign( lmd
, mkU32( 0 ) );
17745 assign( invalid_mask
,
17747 bcd_digit_inval( mkU32( 0 ),
17749 mkexpr( bcd_top_8
) ) ),
17751 bcd_digit_inval( unop( Iop_64HIto32
,
17752 mkexpr( bcd_mid_60
) ),
17754 mkexpr( bcd_mid_60
) ) ),
17755 bcd_digit_inval( unop( Iop_64HIto32
,
17756 mkexpr( bcd_low_60
) ),
17758 mkexpr( bcd_low_60
) )
17761 } else if ( s
== 1 ) {
17762 IRTemp sign
= newTemp( Ity_I32
);
17763 IRTemp zero
= newTemp( Ity_I32
);
17764 IRTemp pos_sign_mask
= newTemp( Ity_I32
);
17765 IRTemp neg_sign_mask
= newTemp( Ity_I32
);
17767 /* The sign of the BCD string is stored in lower 4 bits */
17770 unop( Iop_64to32
, mkexpr( frBI64_lo
) ),
17772 assign( neg_sign_mask
, Generate_neg_sign_mask( mkexpr( sign
) ) );
17773 assign( pos_sign_mask
, Generate_pos_sign_mask( mkexpr( sign
) ) );
17775 Generate_sign_bit( mkexpr( pos_sign_mask
),
17776 mkexpr( neg_sign_mask
) ) );
17778 /* Generate the value assuminig the sign and BCD digits are vaild */
17780 binop( Iop_32HLto64
,
17783 unop( Iop_64HIto32
, mkexpr( frBI64_hi
) ),
17786 /* The various helper routines ignore the upper 4-bits */
17787 assign( bcd_mid_60
, mkexpr( frBI64_hi
) );
17789 /* Remove bottom four sign bits */
17790 assign( bcd_low_60
,
17791 binop( Iop_32HLto64
,
17793 unop( Iop_64HIto32
,
17794 mkexpr( frBI64_lo
) ),
17798 unop( Iop_64HIto32
,
17799 mkexpr( frBI64_lo
) ),
17803 mkexpr( frBI64_lo
) ),
17805 assign( tmptop10
, unop( Iop_BCDtoDPB
, mkexpr(bcd_top_8
) ) );
17806 assign( dbcd_top_l
, unop( Iop_64to32
, mkexpr( tmptop10
) ) );
17808 assign( tmpmid50
, unop( Iop_BCDtoDPB
, mkexpr(bcd_mid_60
) ) );
17809 assign( dbcd_mid_u
, unop( Iop_64HIto32
, mkexpr( tmpmid50
) ) );
17810 assign( dbcd_mid_l
, unop( Iop_64to32
, mkexpr( tmpmid50
) ) );
17812 assign( tmplow50
, unop( Iop_BCDtoDPB
, mkexpr( bcd_low_60
) ) );
17813 assign( dbcd_low_u
, unop( Iop_64HIto32
, mkexpr( tmplow50
) ) );
17814 assign( dbcd_low_l
, unop( Iop_64to32
, mkexpr( tmplow50
) ) );
17816 /* The entire BCD string fits in lower 110-bits. The LMD value
17817 * is not stored in the final result for the DFP Long instruction.
17819 assign( lmd
, mkU32( 0 ) );
17821 /* Check for invalid sign and invalid BCD digit. Don't check the
17822 * bottom four bits of frBI64_lo as that is the sign value.
17824 assign( zero
, mkU32( 0 ) );
17825 assign( inval_bcd_digit_mask
,
17827 bcd_digit_inval( mkexpr( zero
),
17829 mkexpr( bcd_top_8
) ) ),
17831 bcd_digit_inval( unop( Iop_64HIto32
,
17832 mkexpr( bcd_mid_60
) ),
17834 mkexpr( bcd_mid_60
) ) ),
17835 bcd_digit_inval( unop( Iop_64HIto32
,
17836 mkexpr( frBI64_lo
) ),
17839 mkexpr( frBI64_lo
) ),
17840 mkU8( 4 ) ) ) ) ) );
17841 assign( invalid_mask
,
17842 Generate_inv_mask( mkexpr( inval_bcd_digit_mask
),
17843 mkexpr( pos_sign_mask
),
17844 mkexpr( neg_sign_mask
) ) );
17848 assign( valid_mask
, unop( Iop_Not32
, mkexpr( invalid_mask
) ) );
17850 /* Calculate the value of the result assuming sign and BCD digits
17853 assign( dfp_significand
,
17854 binop( Iop_D64HLtoD128
,
17855 unop( Iop_ReinterpI64asD64
,
17856 binop( Iop_32HLto64
,
17858 mkexpr( sign_bit
),
17859 mkexpr( dbcd_top_l
) ),
17862 mkexpr( dbcd_mid_u
),
17865 mkexpr( dbcd_mid_l
),
17866 mkU8( 14 ) ) ) ) ),
17867 unop( Iop_ReinterpI64asD64
,
17868 binop( Iop_32HLto64
,
17870 mkexpr( dbcd_low_u
),
17872 mkexpr( dbcd_mid_l
),
17874 mkexpr( dbcd_low_l
) ) ) ) );
17876 /* Break the result back down to 32-bit chunks and replace chunks.
17877 * If there was an invalid BCD digit or invalid sign value, replace
17878 * the calculated result with the invalid bit string.
17881 binop( Iop_InsertExpD128
,
17882 mkU64( DFP_EXTND_BIAS
),
17883 mkexpr( dfp_significand
) ) );
17886 unop( Iop_ReinterpD64asI64
,
17887 unop( Iop_D128HItoD64
, mkexpr( result128
) ) ) );
17890 unop( Iop_ReinterpD64asI64
,
17891 unop( Iop_D128LOtoD64
, mkexpr( result128
) ) ) );
17894 binop( Iop_32HLto64
,
17897 mkexpr( valid_mask
),
17898 unop( Iop_64HIto32
, mkexpr( tmp_hi
) ) ),
17900 mkU32( 0x7C000000 ),
17901 mkexpr( invalid_mask
) ) ),
17904 mkexpr( valid_mask
),
17905 unop( Iop_64to32
, mkexpr( tmp_hi
) ) ),
17908 mkexpr( invalid_mask
) ) ) ) );
17911 binop( Iop_32HLto64
,
17914 mkexpr( valid_mask
),
17915 unop( Iop_64HIto32
, mkexpr( tmp_lo
) ) ),
17918 mkexpr( invalid_mask
) ) ),
17921 mkexpr( valid_mask
),
17922 unop( Iop_64to32
, mkexpr( tmp_lo
) ) ),
17925 mkexpr( invalid_mask
) ) ) ) );
17927 putDReg( frT_addr
, unop( Iop_ReinterpI64asD64
, mkexpr( result_hi
) ) );
17928 putDReg( frT_addr
+ 1,
17929 unop( Iop_ReinterpI64asD64
, mkexpr( result_lo
) ) );
17934 vpanic( "ERROR: dis_dfp_bcdq(ppc), undefined opc2 case " );
17940 static Bool
dis_dfp_significant_digits( UInt prefix
, UInt theInstr
)
17942 UInt opc1
= ifieldOPC( theInstr
);
17943 UInt opc2
= ifieldOPClo10(theInstr
);
17944 UChar frA_addr
= ifieldRegA( theInstr
);
17945 UChar frB_addr
= ifieldRegB( theInstr
);
17946 IRTemp frA
= newTemp( Ity_D64
);
17947 IRTemp B_sig
= newTemp( Ity_I8
);
17948 IRTemp K
= newTemp( Ity_I8
);
17949 IRTemp lmd_B
= newTemp( Ity_I32
);
17950 IRTemp field
= newTemp( Ity_I32
);
17951 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) ); // AKA BF
17952 IRTemp Unordered_true
= newTemp( Ity_I32
);
17953 IRTemp Eq_true_mask
= newTemp( Ity_I32
);
17954 IRTemp Lt_true_mask
= newTemp( Ity_I32
);
17955 IRTemp Gt_true_mask
= newTemp( Ity_I32
);
17956 IRTemp KisZero_true_mask
= newTemp( Ity_I32
);
17957 IRTemp KisZero_false_mask
= newTemp( Ity_I32
);
17958 IRTemp cc
= newTemp( Ity_I32
);
17959 UChar UIM
= toUChar( IFIELD( theInstr
, 16, 6 ) );
17960 IRTemp BCD_valid
= newTemp( Ity_I32
);
17962 /* There is no prefixed version of these instructions. */
17965 if (opc2
== 0x2A2) { // dtstsf DFP Test Significance
17966 // dtstsfq DFP Test Significance Quad
17967 /* Get the reference singificance stored in frA */
17968 assign( frA
, getDReg( frA_addr
) );
17970 /* Convert from 64 bit to 8 bits in two steps. The Iop_64to8 is not
17971 * supported in 32-bit mode.
17973 assign( K
, unop( Iop_32to8
,
17976 unop( Iop_ReinterpD64asI64
,
17978 mkU32( 0x3F ) ) ) );
17980 } else if (opc2
== 0x2A3) { // dtstsfi DFP Test Significance Immediate
17981 // dtstsfiq DFP Test Significance Quad Immediate
17982 /* get the significane from the immediate field */
17983 assign( K
, mkU8( UIM
) );
17986 vex_printf("dis_dfp_significant_digits(ppc)(opc2) wrong\n");
17991 case 0x3b: // dtstsf DFP Test Significance
17992 // dtstsfi DFP Test Significance Immediate
17994 IRTemp frB
= newTemp( Ity_D64
);
17995 IRTemp frBI64
= newTemp( Ity_I64
);
17996 IRTemp B_bcd_u
= newTemp( Ity_I32
);
17997 IRTemp B_bcd_l
= newTemp( Ity_I32
);
17998 IRTemp tmp64
= newTemp( Ity_I64
);
18000 if (opc2
== 0x2A2) {
18001 DIP( "dtstsf %u,r%u,r%u\n", crfD
, frA_addr
, frB_addr
);
18003 DIP( "dtstsfi %u,%u,r%u\n", crfD
, UIM
, frB_addr
);
18006 assign( frB
, getDReg( frB_addr
) );
18007 assign( frBI64
, unop( Iop_ReinterpD64asI64
, mkexpr( frB
) ) );
18009 /* Get the BCD string for the value stored in a series of I32 values.
18010 * Count the number of leading zeros. Subtract the number of leading
18011 * zeros from 16 (maximum number of significant digits in DFP
18016 unop( Iop_64HIto32
, mkexpr( frBI64
) ),
18017 mkU8( 31 - 5 ) ) ); // G-field[0:4]
18019 assign( tmp64
, unop( Iop_DPBtoBCD
, mkexpr( frBI64
) ) );
18020 assign( B_bcd_u
, unop( Iop_64HIto32
, mkexpr( tmp64
) ) );
18021 assign( B_bcd_l
, unop( Iop_64to32
, mkexpr( tmp64
) ) );
18025 mkU8( DFP_LONG_MAX_SIG_DIGITS
),
18026 Count_leading_zeros_60( mkexpr( lmd_B
),
18028 mkexpr( B_bcd_l
) ) ) );
18032 bcd_digit_inval( mkexpr( B_bcd_u
), mkexpr( B_bcd_l
) ),
18033 bcd_digit_inval( mkexpr( lmd_B
), mkU32( 0 ) ) ) );
18035 /* Set unordered to True if the number is NaN, Inf or an invalid
18038 assign( Unordered_true
,
18040 Check_unordered( mkexpr( frBI64
) ),
18041 mkexpr( BCD_valid
) ) );
18044 case 0x3F: // dtstsfq DFP Test Significance
18045 // dtstsfqi DFP Test Significance Immediate
18047 IRTemp frB_hi
= newTemp( Ity_D64
);
18048 IRTemp frB_lo
= newTemp( Ity_D64
);
18049 IRTemp frBI64_hi
= newTemp( Ity_I64
);
18050 IRTemp frBI64_lo
= newTemp( Ity_I64
);
18051 IRTemp B_low_60_u
= newTemp( Ity_I32
);
18052 IRTemp B_low_60_l
= newTemp( Ity_I32
);
18053 IRTemp B_mid_60_u
= newTemp( Ity_I32
);
18054 IRTemp B_mid_60_l
= newTemp( Ity_I32
);
18055 IRTemp B_top_12_l
= newTemp( Ity_I32
);
18057 if (opc2
== 0x2A2) {
18058 DIP( "dtstsfq %u,r%u,r%u\n", crfD
, frA_addr
, frB_addr
);
18060 DIP( "dtstsfiq %u,%u,r%u\n", crfD
, UIM
, frB_addr
);
18063 assign( frB_hi
, getDReg( frB_addr
) );
18064 assign( frB_lo
, getDReg( frB_addr
+ 1 ) );
18066 assign( frBI64_hi
, unop( Iop_ReinterpD64asI64
, mkexpr( frB_hi
) ) );
18067 assign( frBI64_lo
, unop( Iop_ReinterpD64asI64
, mkexpr( frB_lo
) ) );
18069 /* Get the BCD string for the value stored in a series of I32 values.
18070 * Count the number of leading zeros. Subtract the number of leading
18071 * zeros from 32 (maximum number of significant digits in DFP
18076 unop( Iop_64HIto32
, mkexpr( frBI64_hi
) ),
18077 mkU8( 31 - 5 ) ) ); // G-field[0:4]
18079 Generate_132_bit_bcd_string( mkexpr( frBI64_hi
),
18080 mkexpr( frBI64_lo
),
18090 bcd_digit_inval( mkexpr( lmd_B
),
18091 mkexpr( B_top_12_l
) ),
18092 bcd_digit_inval( mkexpr( B_mid_60_u
),
18093 mkexpr( B_mid_60_l
) ) ),
18094 bcd_digit_inval( mkexpr( B_low_60_u
),
18095 mkexpr( B_low_60_l
) ) ) );
18099 mkU8( DFP_EXTND_MAX_SIG_DIGITS
),
18100 Count_leading_zeros_128( mkexpr( lmd_B
),
18101 mkexpr( B_top_12_l
),
18102 mkexpr( B_mid_60_u
),
18103 mkexpr( B_mid_60_l
),
18104 mkexpr( B_low_60_u
),
18105 mkexpr( B_low_60_l
) ) ) );
18107 /* Set unordered to True if the number is NaN, Inf or an invalid
18110 assign( Unordered_true
,
18112 Check_unordered( mkexpr( frBI64_hi
) ),
18113 mkexpr( BCD_valid
) ) );
18118 /* Compare (16 - cnt[0]) against K and set the condition code field
18121 * The field layout is as follows:
18123 * bit[3:0] Description
18124 * 3 K != 0 and K < Number of significant digits if FRB
18125 * 2 K != 0 and K > Number of significant digits if FRB OR K = 0
18126 * 1 K != 0 and K = Number of significant digits if FRB
18127 * 0 K ? Number of significant digits if FRB
18129 assign( Eq_true_mask
,
18131 binop( Iop_CmpEQ32
,
18132 unop( Iop_8Uto32
, mkexpr( K
) ),
18133 unop( Iop_8Uto32
, mkexpr( B_sig
) ) ) ) );
18134 assign( Lt_true_mask
,
18136 binop( Iop_CmpLT32U
,
18137 unop( Iop_8Uto32
, mkexpr( K
) ),
18138 unop( Iop_8Uto32
, mkexpr( B_sig
) ) ) ) );
18139 assign( Gt_true_mask
,
18141 binop( Iop_CmpLT32U
,
18142 unop( Iop_8Uto32
, mkexpr( B_sig
) ),
18143 unop( Iop_8Uto32
, mkexpr( K
) ) ) ) );
18145 assign( KisZero_true_mask
,
18147 binop( Iop_CmpEQ32
,
18148 unop( Iop_8Uto32
, mkexpr( K
) ),
18150 assign( KisZero_false_mask
,
18152 binop( Iop_CmpNE32
,
18153 unop( Iop_8Uto32
, mkexpr( K
) ),
18159 mkexpr( KisZero_false_mask
),
18162 mkexpr( Lt_true_mask
),
18166 mkexpr( Gt_true_mask
),
18169 mkexpr( Eq_true_mask
),
18170 mkU32( 0x2 ) ) ) ) ),
18172 mkexpr( KisZero_true_mask
),
18173 mkU32( 0x4 ) ) ) );
18175 assign( cc
, binop( Iop_Or32
,
18177 mkexpr( Unordered_true
),
18180 unop( Iop_Not32
, mkexpr( Unordered_true
) ),
18181 mkexpr( field
) ) ) );
18183 putGST_field( PPC_GST_CR
, mkexpr( cc
), crfD
);
18184 putFPCC( mkexpr( cc
) );
18188 /*------------------------------------------------------------*/
18189 /*--- AltiVec Instruction Translation ---*/
18190 /*------------------------------------------------------------*/
18193 Altivec Cache Control Instructions (Data Streams)
18195 static Bool
dis_av_datastream ( UInt prefix
, UInt theInstr
)
18198 UChar opc1
= ifieldOPC(theInstr
);
18199 UChar flag_T
= toUChar( IFIELD( theInstr
, 25, 1 ) );
18200 UChar flag_A
= flag_T
;
18201 UChar b23to24
= toUChar( IFIELD( theInstr
, 23, 2 ) );
18202 UChar STRM
= toUChar( IFIELD( theInstr
, 21, 2 ) );
18203 UChar rA_addr
= ifieldRegA(theInstr
);
18204 UChar rB_addr
= ifieldRegB(theInstr
);
18205 UInt opc2
= ifieldOPClo10(theInstr
);
18206 UChar b0
= ifieldBIT0(theInstr
);
18208 /* There is no prefixed version of these instructions. */
18211 if (opc1
!= 0x1F || b23to24
!= 0 || b0
!= 0) {
18212 vex_printf("dis_av_datastream(ppc)(instr)\n");
18217 case 0x156: // dst (Data Stream Touch, AV p115)
18218 DIP("dst%s r%u,r%u,%d\n", flag_T
? "t" : "",
18219 rA_addr
, rB_addr
, STRM
);
18222 case 0x176: // dstst (Data Stream Touch for Store, AV p117)
18223 DIP("dstst%s r%u,r%u,%d\n", flag_T
? "t" : "",
18224 rA_addr
, rB_addr
, STRM
);
18227 case 0x336: // dss (Data Stream Stop, AV p114)
18228 if (rA_addr
!= 0 || rB_addr
!= 0) {
18229 vex_printf("dis_av_datastream(ppc)(opc2,dst)\n");
18233 DIP("dss %d\n", STRM
);
18240 vex_printf("dis_av_datastream(ppc)(opc2)\n");
18247 AltiVec Processor Control Instructions
18249 static Bool
dis_av_procctl ( UInt prefix
, UInt theInstr
)
18252 UChar opc1
= ifieldOPC(theInstr
);
18253 UChar vD_addr
= ifieldRegDS(theInstr
);
18254 UChar vA_addr
= ifieldRegA(theInstr
);
18255 UChar vB_addr
= ifieldRegB(theInstr
);
18256 UInt opc2
= IFIELD( theInstr
, 0, 11 );
18258 /* There is no prefixed version of these instructions. */
18262 vex_printf("dis_av_procctl(ppc)(instr)\n");
18267 case 0x604: // mfvscr (Move from VSCR, AV p129)
18268 if (vA_addr
!= 0 || vB_addr
!= 0) {
18269 vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
18272 DIP("mfvscr v%d\n", vD_addr
);
18273 putVReg( vD_addr
, unop(Iop_32UtoV128
, getGST( PPC_GST_VSCR
)) );
18276 case 0x644: { // mtvscr (Move to VSCR, AV p130)
18277 IRTemp vB
= newTemp(Ity_V128
);
18278 if (vD_addr
!= 0 || vA_addr
!= 0) {
18279 vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
18282 DIP("mtvscr v%d\n", vB_addr
);
18283 assign( vB
, getVReg(vB_addr
));
18284 putGST( PPC_GST_VSCR
, unop(Iop_V128to32
, mkexpr(vB
)) );
18288 vex_printf("dis_av_procctl(ppc)(opc2)\n");
18295 Vector Extend Sign Instructions
18297 static Bool
dis_av_extend_sign_count_zero ( UInt prefix
, UInt theInstr
,
18298 UInt allow_isa_3_0
)
18300 /* VX-Form, sort of, the A register field is used to select the specific
18301 * sign extension instruction or count leading/trailing zero LSB
18305 UChar opc1
= ifieldOPC( theInstr
);
18306 UChar rT_addr
= ifieldRegDS (theInstr
);
18307 UChar rA_addr
= ifieldRegA( theInstr
);
18308 UChar vB_addr
= ifieldRegB( theInstr
);
18309 UInt opc2
= IFIELD( theInstr
, 0, 11 );
18311 IRTemp vB
= newTemp( Ity_V128
);
18312 IRTemp vT
= newTemp( Ity_V128
);
18314 /* There is no prefixed version of these instructions. */
18317 assign( vB
, getVReg ( vB_addr
) );
18319 if ( ( opc1
!= 0x4 ) && ( opc2
!= 0x602 ) ) {
18320 vex_printf("dis_av_extend_sign(ppc)(instr)\n");
18324 switch ( rA_addr
) {
18330 IRTemp bit_zero
[16];
18331 IRTemp byte_mask
[17];
18333 /* These instructions store the result in the general purpose
18334 * register in the rT_addr field.
18337 byte_mask
[0] = newTemp( Ity_I32
);
18338 count
[0] = newTemp( Ity_I32
);
18339 assign( count
[0], mkU32( 0 ) );
18340 assign( byte_mask
[0], mkU32( 0x1 ) );
18342 if ( rA_addr
== 0 ) {
18343 // vclzlsbb (Vector Count Leading Zero Least-Significant Bits Byte)
18344 DIP("vclzlsbb %d,v%d\n", rT_addr
, vB_addr
);
18347 // vctzlsbb (Vector Count Trailing Zero Least-Significant Bits Byte)
18348 DIP("vctzlsbb %d,v%d\n", rT_addr
, vB_addr
);
18351 for( i
= 0; i
< 16; i
++ ) {
18352 byte_mask
[i
+1] = newTemp( Ity_I32
);
18353 count
[i
+1] = newTemp( Ity_I32
);
18354 bit_zero
[i
] = newTemp( Ity_I1
);
18356 /* bit_zero[i] = 0x0 until the first 1 bit is found in lsb of
18357 * byte. When the first 1 bit is found it causes the byte_mask
18358 * to change from 0x1 to 0x0. Thus the AND of the lsb and byte_mask
18359 * will be zero which will be equal to the zero byte_mask causing
18360 * the value of bit_zero[i] to be equal to 0x1 for all remaining bits.
18363 if ( rA_addr
== 0 )
18364 /* leading zero bit in byte count,
18365 work bytes from left to right
18367 assign( bit_zero
[i
],
18368 binop( Iop_CmpEQ32
,
18370 unop( Iop_V128to32
,
18371 binop( Iop_ShrV128
,
18373 mkU8( ( 15 - i
) * 8 ) ) ),
18374 mkexpr( byte_mask
[i
] ) ),
18375 mkexpr( byte_mask
[i
] ) ) );
18377 else if ( rA_addr
== 1 )
18378 /* trailing zero bit in byte count,
18379 * work bytes from right to left
18381 assign( bit_zero
[i
],
18382 binop( Iop_CmpEQ32
,
18384 unop( Iop_V128to32
,
18385 binop( Iop_ShrV128
,
18388 mkexpr( byte_mask
[i
] ) ),
18389 mkexpr( byte_mask
[i
] ) ) );
18391 /* Increment count as long as bit_zero = 0 */
18392 assign( count
[i
+1], binop( Iop_Add32
,
18393 mkexpr( count
[i
] ),
18396 mkexpr( bit_zero
[i
] ) ) ) ) );
18398 /* If comparison fails to find a zero bit, set the byte_mask to zero
18399 * for all future comparisons so there will be no more matches.
18401 assign( byte_mask
[i
+1],
18405 mkexpr( bit_zero
[i
] ) ) ),
18406 mkexpr( byte_mask
[i
] ) ) );
18408 putIReg( rT_addr
, unop( Iop_32Uto64
, mkexpr( count
[16] ) ) );
18412 case 6: // vnegw, Vector Negate Word
18413 DIP("vnegw v%u,v%u", rT_addr
, vB_addr
);
18415 /* multiply each word by -1 */
18416 assign( vT
, binop( Iop_Mul32x4
, mkexpr( vB
), mkV128( 0xFFFF ) ) );
18419 case 7: // vnegd, Vector Negate Doubleword
18420 DIP("vnegd v%u,v%u", rT_addr
, vB_addr
);
18422 /* multiply each word by -1 */
18423 assign( vT
, binop( Iop_64HLtoV128
,
18425 unop( Iop_V128HIto64
,
18427 mkU64( 0xFFFFFFFFFFFFFFFF ) ),
18429 unop( Iop_V128to64
,
18431 mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) );
18434 case 8: // vprtybw, Vector Parity Byte Word
18435 case 9: // vprtybd, Vector Parity Byte Doubleword
18436 case 10: // vprtybq, Vector Parity Byte Quadword
18439 IRTemp bit_in_byte
[16];
18440 IRTemp word_parity
[4];
18442 for( i
= 0; i
< 16; i
++ ) {
18443 bit_in_byte
[i
] = newTemp( Ity_I32
);
18444 assign( bit_in_byte
[i
],
18446 unop( Iop_V128to32
,
18447 binop( Iop_ShrV128
,
18449 mkU8( ( 15 - i
) * 8 ) ) ),
18453 for( i
= 0; i
< 4; i
++ ) {
18454 word_parity
[i
] = newTemp(Ity_I32
);
18455 assign( word_parity
[i
],
18456 mkXOr4_32( bit_in_byte
[0 + i
* 4],
18457 bit_in_byte
[1 + i
* 4],
18458 bit_in_byte
[2 + i
* 4],
18459 bit_in_byte
[3 + i
* 4] ) );
18462 if ( rA_addr
== 8 ) {
18463 DIP("vprtybw v%d,v%d", rT_addr
, vB_addr
);
18465 assign( vT
, mkV128from32( word_parity
[0], word_parity
[1],
18466 word_parity
[2], word_parity
[3] ) );
18468 } else if ( rA_addr
== 9 ) {
18469 DIP("vprtybd v%d,v%d", rT_addr
, vB_addr
);
18472 binop( Iop_64HLtoV128
,
18473 binop( Iop_32HLto64
,
18476 mkexpr( word_parity
[0] ),
18477 mkexpr( word_parity
[1] ) ) ),
18478 binop( Iop_32HLto64
,
18481 mkexpr( word_parity
[2] ),
18482 mkexpr( word_parity
[3] ) ) ) ) );
18484 } else if ( rA_addr
== 10 ) {
18485 DIP("vprtybq v%d,v%d", rT_addr
, vB_addr
);
18488 binop( Iop_64HLtoV128
,
18491 mkXOr4_32( word_parity
[0],
18494 word_parity
[3] ) ) ) );
18499 case 16: // vextsb2w, Vector Extend Sign Byte to Word
18500 DIP("vextsb2w v%u,v%u", rT_addr
, vB_addr
);
18502 /* Iop_MullEven8Sx16 does a signed widening multiplication of byte to
18503 * two byte sign extended result. Then do a two byte to four byte sign
18504 * extended multiply. Note contents of upper three bytes in word are
18505 * "over written". So just take source and multiply by 1.
18507 assign( vT
, binop( Iop_MullEven16Sx8
,
18508 binop( Iop_64HLtoV128
,
18509 mkU64( 0x0000000100000001 ),
18510 mkU64( 0x0000000100000001 ) ),
18511 binop( Iop_MullEven8Sx16
,
18513 binop( Iop_64HLtoV128
,
18514 mkU64( 0x0001000100010001 ),
18515 mkU64( 0x0001000100010001 ) ) ) ) );
18518 case 17: // vextsh2w, Vector Extend Sign Halfword to Word
18519 DIP("vextsh2w v%u,v%u", rT_addr
, vB_addr
);
18521 /* Iop_MullEven16Sx8 does a signed widening multiply of four byte
18522 * 8 bytes. Note contents of upper two bytes in word are
18523 * "over written". So just take source and multiply by 1.
18525 assign( vT
, binop( Iop_MullEven16Sx8
,
18526 binop( Iop_64HLtoV128
,
18527 mkU64( 0x0000000100000001 ),
18528 mkU64( 0x0000000100000001 ) ),
18533 case 24: // vextsb2d, Vector Extend Sign Byte to Doubleword
18534 DIP("vextsb2d v%u,v%u", rT_addr
, vB_addr
);
18536 /* Iop_MullEven8Sx16 does a signed widening multiplication of byte to
18537 * two byte sign extended result. Then do a two byte to four byte sign
18538 * extended multiply. Then do four byte to eight byte multiply.
18540 assign( vT
, binop( Iop_MullEven32Sx4
,
18541 binop( Iop_64HLtoV128
,
18542 mkU64( 0x0000000000000001 ),
18543 mkU64( 0x0000000000000001 ) ),
18544 binop( Iop_MullEven16Sx8
,
18545 binop( Iop_64HLtoV128
,
18546 mkU64( 0x0000000100000001 ),
18547 mkU64( 0x0000000100000001 ) ),
18548 binop( Iop_MullEven8Sx16
,
18549 binop( Iop_64HLtoV128
,
18550 mkU64( 0x0001000100010001 ),
18551 mkU64( 0x0001000100010001 ) ),
18552 mkexpr( vB
) ) ) ) );
18555 case 25: // vextsh2d, Vector Extend Sign Halfword to Doubleword
18556 DIP("vextsh2d v%u,v%u", rT_addr
, vB_addr
);
18558 assign( vT
, binop( Iop_MullEven32Sx4
,
18559 binop( Iop_64HLtoV128
,
18560 mkU64( 0x0000000000000001 ),
18561 mkU64( 0x0000000000000001 ) ),
18562 binop( Iop_MullEven16Sx8
,
18563 binop( Iop_64HLtoV128
,
18564 mkU64( 0x0000000100000001 ),
18565 mkU64( 0x0000000100000001 ) ),
18566 mkexpr( vB
) ) ) );
18569 case 26: // vextsw2d, Vector Extend Sign Word to Doubleword
18570 DIP("vextsw2d v%u,v%u", rT_addr
, vB_addr
);
18572 assign( vT
, binop( Iop_MullEven32Sx4
,
18573 binop( Iop_64HLtoV128
,
18574 mkU64( 0x0000000000000001 ),
18575 mkU64( 0x0000000000000001 ) ),
18578 case 27: // vextsd2q Vector Extend Sign Doubleword to Quadword
18580 IRTemp sb
= newTemp(Ity_I64
); // sign bit extended
18581 IRTemp tmp
= newTemp(Ity_I64
);
18583 DIP("vextsd2q v%u,v%u\n", rT_addr
, vB_addr
);
18584 assign( tmp
, unop( Iop_V128to64
, mkexpr( vB
) ) );
18585 assign( sb
, unop( Iop_1Sto64
,
18589 mkU8( 63 ) ) ) ) );
18591 assign( vT
, binop( Iop_64HLtoV128
, mkexpr( sb
), mkexpr( tmp
) ) );
18596 case 28: // vctzb, Vector Count Trailing Zeros Byte
18598 DIP("vctzb v%d,v%d", rT_addr
, vB_addr
);
18600 /* This instruction is only available in the ISA 3.0 */
18601 if ( !mode64
|| !allow_isa_3_0
) {
18602 vex_printf("\n vctzb instruction not supported on non ISA 3.0 platform\n\n");
18605 assign( vT
, unop( Iop_Ctz8x16
, mkexpr( vB
) ) );
18609 case 29: // vctzh, Vector Count Trailing Zeros Halfword
18611 DIP("vctzh v%d,v%d", rT_addr
, vB_addr
);
18613 /* This instruction is only available in the ISA 3.0 */
18614 if ( !mode64
|| !allow_isa_3_0
) {
18615 vex_printf("\n vctzh instruction not supported on non ISA 3.0 platform\n\n");
18618 assign( vT
, unop( Iop_Ctz16x8
, mkexpr( vB
) ) );
18622 case 30: // vctzw, Vector Count Trailing Zeros Word
18624 DIP("vctzw v%d,v%d", rT_addr
, vB_addr
);
18626 /* This instruction is only available in the ISA 3.0 */
18627 if ( !mode64
|| !allow_isa_3_0
) {
18628 vex_printf("\n vctzw instruction not supported on non ISA 3.0 platform\n\n");
18631 assign( vT
, unop( Iop_Ctz32x4
, mkexpr( vB
) ) );
18635 case 31: // vctzd, Vector Count Trailing Zeros Double word
18637 DIP("vctzd v%d,v%d", rT_addr
, vB_addr
);
18639 /* This instruction is only available in the ISA 3.0 */
18640 if ( !mode64
|| !allow_isa_3_0
) {
18641 vex_printf("\n vctzd instruction not supported on non ISA 3.0 platform\n\n");
18644 assign( vT
, unop( Iop_Ctz64x2
, mkexpr( vB
) ) );
18649 vex_printf("dis_av_extend_sign(ppc)(Unsupported vector extend sign instruction)\n");
18653 putVReg( rT_addr
, mkexpr( vT
) );
18658 Vector Rotate Instructions
18660 static Bool
dis_av_rotate ( UInt prefix
, UInt theInstr
)
18664 UChar opc1
= ifieldOPC( theInstr
);
18665 UChar vT_addr
= ifieldRegDS( theInstr
);
18666 UChar vA_addr
= ifieldRegA( theInstr
);
18667 UChar vB_addr
= ifieldRegB( theInstr
);
18668 UInt opc2
= IFIELD( theInstr
, 0, 11 );
18670 IRTemp vA
= newTemp( Ity_V128
);
18671 IRTemp vB
= newTemp( Ity_V128
);
18672 IRTemp src3
= newTemp( Ity_V128
);
18673 IRTemp vT
= newTemp( Ity_V128
);
18674 IRTemp field_mask
= newTemp( Ity_V128
);
18675 IRTemp mask128
= newTemp( Ity_V128
);
18677 IRTemp left_bits
[4];
18678 IRTemp right_bits
[4];
18683 IRTemp tmp_mask
[4];
18684 IRTemp invert_mask
[4];
18689 unsigned long long word_mask
;
18691 /* There is no prefixed version of these instructions. */
18694 if ( opc1
!= 0x4 ) {
18695 vex_printf("dis_av_rotate(ppc)(instr)\n");
18699 assign( vA
, getVReg( vA_addr
) );
18700 assign( vB
, getVReg( vB_addr
) );
18703 case 0x85: // vrlwmi, Vector Rotate Left Word then Mask Insert
18704 case 0x185: // vrlwnm, Vector Rotate Left Word then AND with Mask
18707 assign( field_mask
, binop( Iop_64HLtoV128
,
18710 word_mask
= 0xFFFFFFFF;
18713 case 0x0C5: // vrldmi, Vector Rotate Left Doubleword then Mask Insert
18714 case 0x1C5: // vrldnm, Vector Rotate Left Doubleword then AND with Mask
18717 assign( field_mask
, binop( Iop_64HLtoV128
,
18720 word_mask
= 0xFFFFFFFFFFFFFFFFULL
;
18723 vex_printf("dis_av_rotate(ppc)(opc2)\n");
18727 for( i
= 0; i
< num_words
; i
++ ) {
18728 left_bits
[i
] = newTemp( Ity_I8
);
18729 right_bits
[i
] = newTemp( Ity_I8
);
18730 shift
[i
] = newTemp( Ity_I8
);
18731 mb
[i
] = newTemp( Ity_I64
);
18732 me
[i
] = newTemp( Ity_I64
);
18733 tmp_mask
[i
] = newTemp( Ity_I64
);
18734 invert_mask
[i
] = newTemp( Ity_I64
);
18735 mask
[i
] = newTemp( Ity_V128
);
18736 tmp128
[i
] = newTemp( Ity_V128
);
18737 vA_word
[i
] = newTemp( Ity_V128
);
18741 unop( Iop_V128to64
,
18742 binop( Iop_AndV128
,
18743 binop( Iop_ShrV128
,
18745 mkU8( (num_words
- 1 - i
)
18747 mkexpr( field_mask
) ) ) ) );
18749 assign( mb
[i
], unop( Iop_V128to64
,
18750 binop( Iop_AndV128
,
18751 binop( Iop_ShrV128
,
18753 mkU8( ( num_words
- 1 - i
)
18754 * word_size
+ 16 ) ),
18755 mkexpr( field_mask
) ) ) );
18757 assign( me
[i
], unop( Iop_V128to64
,
18758 binop( Iop_AndV128
,
18759 binop( Iop_ShrV128
,
18761 mkU8( ( num_words
- 1 - i
)
18762 * word_size
+ 8 ) ),
18763 mkexpr( field_mask
) ) ) );
18765 /* If me < mb, we have to flip things around and invert the mask */
18766 assign( invert_mask
[i
],
18767 unop( Iop_1Sto64
, binop( Iop_CmpLT64U
,
18768 mkexpr( me
[i
] ), mkexpr( mb
[i
] ) ) ) );
18770 /* left_bits = 63 - mb. Tells us how many bits to the left
18771 * of mb to clear. Note for a word left_bits = 32+mb, for a double
18772 * word left_bits = mb
18774 assign( left_bits
[i
],
18777 binop( Iop_And64
, // mb < me
18778 unop( Iop_Not64
, mkexpr( invert_mask
[i
] ) ),
18780 mkU64( 64 - word_size
),
18781 mkexpr( mb
[i
] ) ) ),
18782 binop( Iop_And64
, // me < mb
18783 mkexpr( invert_mask
[i
] ),
18785 mkU64( 64 + 1 - word_size
),
18786 mkexpr( me
[i
] ) ) ) ) ) );
18788 /* right_bits = 63 - me. Tells us how many bits to the right
18789 * of me to clear. Note for a word, left_bits = me+32, for a double
18790 * word left_bits = me
18792 assign( right_bits
[i
],
18795 binop( Iop_And64
, // mb < me
18796 unop( Iop_Not64
, mkexpr( invert_mask
[i
] ) ),
18798 mkU64( word_size
- 1 ),
18799 mkexpr( me
[i
] ) ) ),
18800 binop( Iop_And64
, // me < mb
18801 mkexpr( invert_mask
[i
] ),
18803 mkU64( word_size
- 1 + 1),
18804 mkexpr( mb
[i
] ) ) ) ) ) );
18806 /* create mask for 32-bit word or 64-bit word */
18807 assign( tmp_mask
[i
],
18812 mkU64( 0xFFFFFFFFFFFFFFFF ),
18813 mkexpr( left_bits
[i
] ) ),
18814 mkexpr( left_bits
[i
] ) ),
18815 mkexpr( right_bits
[i
] ) ),
18816 mkexpr( right_bits
[i
] ) ) );
18819 binop( Iop_64HLtoV128
,
18823 unop( Iop_Not64
, mkexpr( invert_mask
[i
] ) ),
18824 mkexpr( tmp_mask
[i
] ) ),
18826 mkexpr( invert_mask
[i
] ),
18827 /* Need to make sure mask is only the size
18830 mkU64( word_mask
),
18832 mkexpr( tmp_mask
[i
] ) ) ) ))));
18834 /* Need to rotate vA using a left and right shift of vA OR'd together
18835 * then ANDed with the mask.
18837 assign( vA_word
[i
], binop( Iop_AndV128
,
18839 binop( Iop_ShlV128
,
18840 binop( Iop_64HLtoV128
,
18842 mkU64( word_mask
) ),
18843 mkU8( ( num_words
- 1 - i
)
18844 * word_size
) ) ) );
18846 binop( Iop_AndV128
,
18847 binop( Iop_ShlV128
,
18849 mkU8( ( num_words
- 1 - i
) * word_size
) ),
18851 binop( Iop_ShlV128
,
18852 mkexpr( vA_word
[i
] ),
18853 mkexpr( shift
[i
] ) ),
18854 binop( Iop_ShrV128
,
18855 mkexpr( vA_word
[i
] ),
18858 mkU32( word_size
),
18860 mkexpr( shift
[i
] ) ) )
18865 case 0x85: // vrlwmi, Vector Rotate Left Word then Mask Insert
18866 DIP("vrlwmi %d,%d,v%d", vT_addr
, vA_addr
, vB_addr
);
18868 assign( src3
, getVReg( vT_addr
) );
18869 assign( mask128
, unop( Iop_NotV128
,
18870 mkOr4_V128_expr( binop( Iop_ShlV128
,
18873 binop( Iop_ShlV128
,
18876 binop( Iop_ShlV128
,
18879 mkexpr( mask
[3] ) ) ) );
18880 assign( vT
, binop( Iop_OrV128
,
18881 binop( Iop_AndV128
,
18883 mkexpr( mask128
) ),
18884 mkOr4_V128( tmp128
[0], tmp128
[1],
18885 tmp128
[2], tmp128
[3] ) ) );
18888 case 0xC5: // vrldmi, Vector Rotate Left Double word then Mask Insert
18889 DIP("vrldmi %d,%d,v%d", vT_addr
, vA_addr
, vB_addr
);
18891 assign( src3
, getVReg( vT_addr
) );
18892 assign( mask128
, unop( Iop_NotV128
,
18894 binop( Iop_ShlV128
,
18897 mkexpr( mask
[1] ) ) ) );
18899 assign( vT
, binop( Iop_OrV128
,
18900 binop( Iop_AndV128
,
18902 mkexpr( mask128
) ),
18904 mkexpr( tmp128
[0] ),
18905 mkexpr( tmp128
[1] ) ) ) );
18908 case 0x185: // vrlwnm, Vector Rotate Left Word then AND with Mask
18909 DIP("vrlwnm %d,%d,v%d", vT_addr
, vA_addr
, vB_addr
);
18910 assign( vT
, mkOr4_V128( tmp128
[0], tmp128
[1], tmp128
[2], tmp128
[3] ) );
18913 case 0x1C5: // vrldnm, Vector Rotate Left Doubleword then AND with Mask
18914 DIP("vrldnm %d,%d,v%d", vT_addr
, vA_addr
, vB_addr
);
18915 assign( vT
, binop( Iop_OrV128
,
18916 mkexpr( tmp128
[0] ),
18917 mkexpr( tmp128
[1] ) ) );
18921 putVReg( vT_addr
, mkexpr( vT
) );
18926 AltiVec Vector Extract Element Instructions
18928 static Bool
dis_av_insert_element ( UInt prefix
, UInt theInstr
)
18931 * Source, index and value are GPR, destination is a vector register.
18933 UChar opc1
= ifieldOPC( theInstr
);
18934 UChar VRT
= ifieldRegDS( theInstr
);
18935 UChar rA_addr
= ifieldRegA( theInstr
);
18936 UChar VRB
= ifieldRegB( theInstr
);
18937 UInt opc2
= IFIELD( theInstr
, 0, 11 );
18938 UChar rVT_addr
= VRT
;
18939 UChar rVB_addr
= VRB
;
18941 IRTemp rA
= newTemp( Ity_I64
);
18942 IRTemp vTmp
= newTemp( Ity_V128
);
18943 IRTemp index
= newTemp( Ity_I64
);
18944 UInt max_index_in_src
= 15;
18946 /* There is no prefixed version of these instructions. */
18947 vassert( !prefix_instruction( prefix
) );
18949 assign( vTmp
, getVReg( rVT_addr
) );
18950 assign( rA
, getIReg( rA_addr
) );
18951 assign ( index
, binop( Iop_Sub64
,
18955 if ( opc1
!= 0x4 ) {
18956 vex_printf("dis_av_insert_element(ppc)(instr)\n");
18961 case 0x00F: // vinsbvlx, vector insert Byte from VSR Left-indexed VX form
18963 IRTemp src
= newTemp( Ity_I64
);
18964 IRTemp adj_index
= newTemp( Ity_I64
);
18965 IRTemp rVB
= newTemp( Ity_V128
);
18967 DIP("vinsbvlx v%d,%d,v%d", VRT
, rA_addr
, VRB
);
18969 assign( rVB
, getVReg( rVB_addr
) );
18970 assign( adj_index
, binop( Iop_Sub64
,
18971 mkU64( max_index_in_src
),
18974 mkexpr( rA
) ) ) );
18976 /* Extract byte in rVB[56:63], that is byte 8 counting from the right */
18977 assign( src
, extract_field_from_vector( rVB
, mkU64( 8 ), 0xFF ) );
18979 insert_field_into_vector( vTmp
, mkexpr( adj_index
),
18980 mkexpr( src
), mkU64( 0xFF ) ) );
18984 case 0x10F: // vinsbvrx, vector insert Byte from VSR Right-indexed VX form
18986 IRTemp src
= newTemp( Ity_I64
);
18987 IRTemp rVB
= newTemp( Ity_V128
);
18988 IRTemp adj_index
= newTemp( Ity_I64
);
18990 DIP("vinsbvrx v%d,%d,v%d", VRT
, rA_addr
, VRB
);
18992 assign( rVB
, getVReg( rVB_addr
) );
18994 assign( adj_index
, binop( Iop_And64
, mkexpr( rA
), mkU64( 0xF ) ) );
18995 /* Extract byte in rVB[56:63], that is byte 8 counting from the right */
18996 assign( src
, extract_field_from_vector( rVB
, mkU64( 8 ), 0xFF ) );
18998 insert_field_into_vector( vTmp
, mkexpr( rA
),
18999 mkexpr( src
), mkU64( 0xFF ) ) );
19004 // vinshvlx, vector insert Halfword from VSR Left-indexed VX form
19006 IRTemp src
= newTemp( Ity_I64
);
19007 IRTemp adj_index
= newTemp( Ity_I64
);
19008 IRTemp rVB
= newTemp( Ity_V128
);
19010 DIP("vinshvlx v%d,%d,v%d", VRT
, rA_addr
, VRB
);
19012 assign( rVB
, getVReg( rVB_addr
) );
19013 assign( adj_index
, binop( Iop_Sub64
,
19014 mkU64( max_index_in_src
- 1 ),
19017 mkU64( 0xF ) ) ) );
19019 /* Extract half word rVB[48:63], bytes [9:8] counting from the right */
19020 assign( src
, extract_field_from_vector( rVB
, mkU64( 8 ), 0xFFFF ) );
19022 insert_field_into_vector( vTmp
, mkexpr( adj_index
),
19023 mkexpr( src
), mkU64( 0xFFFF ) ) );
19028 // vinshvrx, vector insert Halfword from VSR Right-indexed VX form
19030 IRTemp src
= newTemp( Ity_I64
);
19031 IRTemp rVB
= newTemp( Ity_V128
);
19032 IRTemp adj_index
= newTemp( Ity_I64
);
19034 DIP("vinshvrx v%d,%d,v%d", VRT
, rA_addr
, VRB
);
19036 assign( rVB
, getVReg( rVB_addr
) );
19038 assign( adj_index
, binop( Iop_And64
, mkexpr( rA
), mkU64( 0xF ) ) );
19040 /* Extract half word rVB[48:63], bytes [9:8] counting from the right */
19041 assign( src
, extract_field_from_vector( rVB
, mkU64( 8 ), 0xFFFF ) );
19043 insert_field_into_vector( vTmp
, mkexpr( rA
), mkexpr( src
),
19044 mkU64( 0xFFFF ) ) );
19049 // vinswvlx, vector insert Word from VSR Left-indexed VX form
19051 IRTemp src
= newTemp( Ity_I64
);
19052 IRTemp adj_index
= newTemp( Ity_I64
);
19053 IRTemp rVB
= newTemp( Ity_V128
);
19055 DIP("vinswvlx v%u,%u,v%u", VRT
, rA_addr
, VRB
);
19057 assign( rVB
, getVReg( rVB_addr
) );
19058 assign( adj_index
, binop( Iop_Sub64
,
19059 mkU64( max_index_in_src
- 3 ),
19062 mkexpr( rA
) ) ) );
19064 /* Extract word rVB[32:63], bytes [15:8] counting from the right */
19065 assign( src
, extract_field_from_vector( rVB
, mkU64( 8 ), 0xFFFFFFFF ) );
19067 insert_field_into_vector( vTmp
, mkexpr( adj_index
),
19068 mkexpr( src
), mkU64( 0xFFFFFFFF ) ) );
19073 // vinswvrx, vector insert Word from VSR Right-indexed VX form
19075 IRTemp src
= newTemp( Ity_I64
);
19076 IRTemp rVB
= newTemp( Ity_V128
);
19077 IRTemp adj_index
= newTemp( Ity_I64
);
19079 DIP("vinswvrx v%u,%u,v%u", VRT
, rA_addr
, VRB
);
19081 assign( rVB
, getVReg( rVB_addr
) );
19083 assign( adj_index
, binop( Iop_And64
, mkexpr( rA
), mkU64( 0xF ) ) );
19084 /* Extract word in rVB[32:63], bytes [15:8] counting from the right */
19085 assign( src
, extract_field_from_vector( rVB
, mkU64( 8 ), 0xFFFFFFFF ) );
19088 insert_field_into_vector( vTmp
, mkexpr( rA
),
19089 mkexpr( src
), mkU64( 0xFFFFFFFF ) ) );
19094 // vinsw, vector insert Word from GPR VX form
19096 IRTemp rB
= newTemp( Ity_I64
);
19097 UChar rB_addr
= ifieldRegB( theInstr
);
19098 UInt UIM
= IFIELD( theInstr
, 16, 4 );
19099 UInt max_bytes_in_src
= 15;
19101 DIP("vinsw v%u,%u,%u", VRT
, rB_addr
, UIM
);
19103 assign( rB
, getIReg( rB_addr
) );
19106 insert_field_into_vector( vTmp
,
19107 mkU64( max_bytes_in_src
- 3 - UIM
),
19108 mkexpr( rB
), mkU64( 0xFFFFFFFF ) ) );
19113 // vinsd, vector insert Doubleword from GPR VX form
19115 IRTemp rB
= newTemp( Ity_I64
);
19116 UChar rB_addr
= ifieldRegB( theInstr
);
19117 UInt UIM
= IFIELD( theInstr
, 16, 4 );
19118 UInt max_bytes_in_src
= 15;
19120 DIP("vinsd v%u,%u,%u", VRT
, rB_addr
, UIM
);
19122 assign( rB
, getIReg( rB_addr
) );
19125 insert_field_into_vector( vTmp
,
19126 mkU64( max_bytes_in_src
- 7 - UIM
),
19128 mkU64( 0xFFFFFFFFFFFFFFFFULL
) ) );
19132 case 0x20F: // vinsblx, vector insert Byte from GPR Left-indexed VX form
19134 IRTemp rB
= newTemp( Ity_I64
);
19135 UChar rB_addr
= ifieldRegB( theInstr
);
19137 DIP("vinsblx v%u,%u,%u", VRT
, rA_addr
, rB_addr
);
19139 assign( rB
, getIReg( rB_addr
) );
19141 insert_field_into_vector( vTmp
,
19143 mkU64( max_index_in_src
),
19145 mkexpr( rB
), mkU64( 0xFF ) ) );
19148 case 0x30F: // vinsbrx, vector insert Byte from GPR Right-indexed VX form
19150 IRTemp rB
= newTemp( Ity_I64
);
19151 UChar rB_addr
= ifieldRegB( theInstr
);
19153 DIP("vinsbrx v%u,%u,%u", VRT
, rA_addr
, rB_addr
);
19155 assign( rB
, getIReg( rB_addr
) );
19157 insert_field_into_vector( vTmp
, mkexpr( rA
),
19158 mkexpr( rB
), mkU64( 0xFF ) ) );
19161 case 0x24F: // vinshlx, vector insert Halfword from GPR Left-indexed VX form
19163 IRTemp rB
= newTemp( Ity_I64
);
19164 UChar rB_addr
= ifieldRegB( theInstr
);
19166 DIP("vinshlx v%u,%u,%u", VRT
, rA_addr
, rB_addr
);
19168 /* insert_field_into_vector assumes right-indexed, convert argument */
19169 assign( rB
, getIReg( rB_addr
) );
19171 insert_field_into_vector( vTmp
,
19173 mkU64( max_index_in_src
-1 ),
19175 mkexpr( rB
), mkU64( 0xFFFF ) ) );
19178 case 0x34F:// vinshrx, vector insert Halfword from GPR Right-indexed VX form
19180 IRTemp rB
= newTemp( Ity_I64
);
19181 UChar rB_addr
= ifieldRegB( theInstr
);
19183 DIP("vinshrx v%u,%u,%u", VRT
, rA_addr
, rB_addr
);
19185 assign( rB
, getIReg( rB_addr
) );
19187 insert_field_into_vector( vTmp
, mkexpr( rA
),
19188 mkexpr( rB
), mkU64( 0xFFFF ) ) );
19191 case 0x28F: // vinswlx, vector insert Word from GPR Left-indexed VX form
19193 IRTemp rB
= newTemp( Ity_I64
);
19194 UChar rB_addr
= ifieldRegB( theInstr
);
19196 DIP("vinswlx v%u,%u,%u", VRT
, rA_addr
, rB_addr
);
19198 /* insert_field_into_vector assumes right-indexed, convert argument */
19199 assign( rB
, getIReg( rB_addr
) );
19201 insert_field_into_vector( vTmp
,
19203 mkU64( max_index_in_src
-3 ),
19205 mkexpr( rB
), mkU64( 0xFFFFFFFF ) ) );
19208 case 0x38F:// vinswrx, vector insert Word from GPR Right-indexed VX form
19210 IRTemp rB
= newTemp( Ity_I64
);
19211 UChar rB_addr
= ifieldRegB( theInstr
);
19213 DIP("vinswrx v%u,%u,%u", VRT
, rA_addr
, rB_addr
);
19215 assign( rB
, getIReg( rB_addr
) );
19217 insert_field_into_vector( vTmp
, mkexpr( rA
),
19218 mkexpr( rB
), mkU64( 0xFFFFFFFF ) ) );
19223 // vinsdlx, vector insert Doubleword from GPR Left-indexed VX form
19224 IRTemp rB
= newTemp( Ity_I64
);
19225 UChar rB_addr
= ifieldRegB( theInstr
);
19227 DIP("vinsdlx v%u,%u,%u", VRT
, rA_addr
, rB_addr
);
19229 /* insert_field_into_vector assumes right-indexed, convert argument */
19230 assign( rB
, getIReg( rB_addr
) );
19232 insert_field_into_vector( vTmp
,
19234 mkU64( max_index_in_src
-7 ),
19237 mkU64( 0xFFFFFFFFFFFFFFFFULL
) ) );
19242 // vinsdrx, vector insert Doubleword from GPR Right-indexed VX form
19243 IRTemp rB
= newTemp( Ity_I64
);
19244 UChar rB_addr
= ifieldRegB( theInstr
);
19246 DIP("vinsdrx v%u,%u,%u", VRT
, rA_addr
, rB_addr
);
19248 assign( rB
, getIReg( rB_addr
) );
19250 insert_field_into_vector( vTmp
, mkexpr( rA
),
19252 mkU64( 0xFFFFFFFFFFFFFFFFULL
) ) );
19256 vex_printf("dis_av_extract_element(ppc)(opc2)\n");
19263 AltiVec Vector Extract Element Instructions
19265 static Bool
dis_av_extract_element ( UInt prefix
, UInt theInstr
)
19268 * sorta destination and first source are GPR not vector registers
19271 UChar opc1
= ifieldOPC( theInstr
);
19272 UChar rT_addr
= ifieldRegDS( theInstr
);
19273 UChar rA_addr
= ifieldRegA( theInstr
);
19274 UChar vB_addr
= ifieldRegB( theInstr
);
19275 UInt opc2
= IFIELD( theInstr
, 0, 11 );
19277 IRTemp vB
= newTemp( Ity_V128
);
19278 IRTemp rA
= newTemp( Ity_I64
);
19279 IRTemp rT
= newTemp( Ity_I64
);
19281 /* There is no prefixed version of these instructions. */
19284 assign( vB
, getVReg( vB_addr
) );
19285 assign( rA
, getIReg( rA_addr
) );
19287 if ( opc1
!= 0x4 ) {
19288 vex_printf("dis_av_extract_element(ppc)(instr)\n");
19293 case 0x60D: // vextublx, vector extract unsigned Byte Left-indexed
19294 DIP("vextublx %d,%d,v%d", rT_addr
, rA_addr
, vB_addr
);
19296 assign( rT
, extract_field_from_vector( vB
,
19304 case 0x64D: // vextuhlx, vector extract unsigned Halfword Left-indexed
19305 DIP("vextuhlx %d,%d,v%d", rT_addr
, rA_addr
, vB_addr
);
19307 assign( rT
, extract_field_from_vector( vB
,
19314 case 0x68D: // vextuwlx, vector extract unsigned Word Left-indexed
19315 DIP("vextuwlx %d,%d,v%d", rT_addr
, rA_addr
, vB_addr
);
19317 assign( rT
, extract_field_from_vector( vB
,
19324 case 0x70D: // vextubrx, vector extract unsigned Byte Right-indexed
19325 DIP("vextubrx %d,%d,v%d", rT_addr
, rA_addr
, vB_addr
);
19327 assign( rT
, extract_field_from_vector( vB
, mkexpr( rA
), 0xFF ) );
19330 case 0x74D: // vextuhrx, vector extract unsigned Halfword Right-indexed
19331 DIP("vextuhrx %d,%d,v%d", rT_addr
, rA_addr
, vB_addr
);
19333 assign( rT
, extract_field_from_vector( vB
, mkexpr( rA
), 0xFFFF ) );
19336 case 0x78D: // vextuwrx, vector extract unsigned Word Right-indexed
19337 DIP("vextuwrx %d,%d,v%d", rT_addr
, rA_addr
, vB_addr
);
19339 assign( rT
, extract_field_from_vector( vB
, mkexpr( rA
), 0xFFFFFFFF ) );
19343 vex_printf("dis_av_extract_element(ppc)(opc2)\n");
19346 putIReg( rT_addr
, mkexpr( rT
) );
19351 * VSX scalar and vector convert instructions
19354 dis_vx_conv ( UInt prefix
, UInt theInstr
, UInt opc2
)
19357 UChar opc1
= ifieldOPC( theInstr
);
19358 UChar XT
= ifieldRegXT( theInstr
);
19359 UChar XB
= ifieldRegXB( theInstr
);
19361 IRTemp b3
, b2
, b1
, b0
;
19363 /* There is no prefixed version of these instructions. */
19366 xB
= xB2
= IRTemp_INVALID
;
19368 if (opc1
!= 0x3C) {
19369 vex_printf( "dis_vx_conv(ppc)(instr)\n" );
19373 /* Create and assign temps only as needed for the given instruction. */
19375 // scalar double-precision floating point argument
19376 case 0x2B0: case 0x0b0: case 0x290: case 0x212: case 0x216: case 0x090:
19377 xB
= newTemp(Ity_F64
);
19379 unop( Iop_ReinterpI64asF64
,
19380 unop( Iop_V128HIto64
, getVSReg( XB
) ) ) );
19382 // vector double-precision floating point arguments
19383 case 0x1b0: case 0x312: case 0x390: case 0x190: case 0x3B0:
19385 xB
= newTemp(Ity_F64
);
19386 xB2
= newTemp(Ity_F64
);
19388 unop( Iop_ReinterpI64asF64
,
19389 unop( Iop_V128HIto64
, getVSReg( XB
) ) ) );
19391 unop( Iop_ReinterpI64asF64
,
19392 unop( Iop_V128to64
, getVSReg( XB
) ) ) );
19394 // vector single precision or [un]signed integer word arguments
19395 case 0x130: case 0x392: case 0x330: case 0x310: case 0x110:
19396 case 0x1f0: case 0x1d0:
19397 b3
= b2
= b1
= b0
= IRTemp_INVALID
;
19398 breakV128to4x32(getVSReg(XB
), &b3
, &b2
, &b1
, &b0
);
19400 // vector [un]signed integer doubleword argument
19401 case 0x3f0: case 0x370: case 0x3d0: case 0x350:
19402 xB
= newTemp(Ity_I64
);
19403 assign( xB
, unop( Iop_V128HIto64
, getVSReg( XB
) ) );
19404 xB2
= newTemp(Ity_I64
);
19405 assign( xB2
, unop( Iop_V128to64
, getVSReg( XB
) ) );
19407 // scalar [un]signed integer doubleword argument
19408 case 0x250: case 0x270: case 0x2D0: case 0x2F0:
19409 xB
= newTemp(Ity_I64
);
19410 assign( xB
, unop( Iop_V128HIto64
, getVSReg( XB
) ) );
19412 // scalar single precision argument
19413 case 0x292: // xscvspdp
19414 xB
= newTemp(Ity_I32
);
19416 assign( xB
, handle_SNaN_to_QNaN_32(unop( Iop_64HIto32
,
19417 unop( Iop_V128HIto64
,
19418 getVSReg( XB
) ) ) ) );
19420 case 0x296: // xscvspdpn (non signaling version of xscvpdp)
19421 xB
= newTemp(Ity_I32
);
19423 unop( Iop_64HIto32
, unop( Iop_V128HIto64
, getVSReg( XB
) ) ) );
19426 /* Certain instructions have their complete implementation in the main switch statement
19427 * that follows this one; thus we have a "do nothing" case for those instructions here.
19429 case 0x170: case 0x150:
19430 break; // do nothing
19433 vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
19440 // xscvdpsxds (VSX Scalar truncate Double-Precision to integer and Convert
19441 // to Signed Integer Doubleword format with Saturate)
19442 DIP("xscvdpsxds v%u,v%u\n", XT
, XB
);
19444 binop( Iop_64HLtoV128
, binop( Iop_F64toI64S
,
19445 mkU32( Irrm_ZERO
),
19446 mkexpr( xB
) ), mkU64( 0 ) ) );
19448 case 0x0b0: // xscvdpsxws (VSX Scalar truncate Double-Precision to integer and
19449 // Convert to Signed Integer Word format with Saturate)
19450 DIP("xscvdpsxws v%u,v%u\n", XT
, XB
);
19452 binop( Iop_64HLtoV128
,
19454 binop( Iop_F64toI32S
,
19455 mkU32( Irrm_ZERO
),
19459 case 0x290: // xscvdpuxds (VSX Scalar truncate Double-Precision integer and Convert
19460 // to Unsigned Integer Doubleword format with Saturate)
19461 DIP("xscvdpuxds v%u,v%u\n", XT
, XB
);
19463 binop( Iop_64HLtoV128
,
19464 binop( Iop_F64toI64U
,
19465 mkU32( Irrm_ZERO
),
19470 // xscvsxdsp (VSX Scalar Convert and round Signed Integer Doubleword
19471 // to Single-Precision format)
19472 DIP("xscvsxdsp v%u,v%u\n", XT
, XB
);
19474 binop( Iop_64HLtoV128
,
19475 unop( Iop_ReinterpF64asI64
,
19476 binop( Iop_RoundF64toF32
,
19477 get_IR_roundingmode(),
19478 binop( Iop_I64StoF64
,
19479 get_IR_roundingmode(),
19480 mkexpr( xB
) ) ) ),
19484 // xscvsxddp (VSX Scalar Convert and round Signed Integer Doubleword to
19485 // Double-Precision format)
19486 DIP("xscvsxddp v%u,v%u\n", XT
, XB
);
19488 binop( Iop_64HLtoV128
, unop( Iop_ReinterpF64asI64
,
19489 binop( Iop_I64StoF64
, get_IR_roundingmode(),
19494 // xscvuxdsp (VSX Scalar Convert and round Unsigned Integer
19495 // Doubleword to Singel-Precision format)
19496 DIP("xscvuxdsp v%u,v%u\n", XT
, XB
);
19498 binop( Iop_64HLtoV128
,
19499 unop( Iop_ReinterpF64asI64
,
19500 binop( Iop_RoundF64toF32
,
19501 get_IR_roundingmode(),
19502 binop( Iop_I64UtoF64
,
19503 get_IR_roundingmode(),
19504 mkexpr( xB
) ) ) ),
19508 // xscvuxddp (VSX Scalar Convert and round Unsigned Integer Doubleword to
19509 // Double-Precision format)
19510 DIP("xscvuxddp v%u,v%u\n", XT
, XB
);
19512 binop( Iop_64HLtoV128
, unop( Iop_ReinterpF64asI64
,
19513 binop( Iop_I64UtoF64
, get_IR_roundingmode(),
19517 case 0x1b0: // xvcvdpsxws (VSX Vector truncate Double-Precision to integer and Convert
19518 // to Signed Integer Word format with Saturate)
19519 case 0x190: // xvcvdpuxws (VSX Vector truncate Double-Precision to integer and
19520 // Convert to Unsigned Integer Word format with Saturate)
19522 IRTemp value_f64
[2];
19523 IRTemp Result_32
[2];
19524 IRTemp Result_32_tmp
[2];
19525 IRTemp nan_mask
[2];
19526 IRTemp underflow_mask
[2];
19527 IRTemp overflow_mask
[2];
19528 IRTemp error_mask
[2];
19529 IRTemp error_value
[2];
19533 Int underflow_value
;
19534 Int overflow_value
;
19535 IRExpr
* rmZero
= mkU32(Irrm_ZERO
);
19537 value_f64
[0] = newTemp(Ity_F64
);
19538 assign( value_f64
[0], mkexpr( xB
) );
19540 value_f64
[1] = newTemp(Ity_F64
);
19541 assign( value_f64
[1], mkexpr( xB2
) );
19543 for ( i
= 0; i
< 2; i
++) {
19544 Result_32
[i
] = newTemp(Ity_I32
);
19545 Result_32_tmp
[i
] = newTemp(Ity_I32
);
19546 nan_mask
[i
] = newTemp(Ity_I32
);
19547 underflow_mask
[i
] = newTemp(Ity_I32
);
19548 overflow_mask
[i
] = newTemp(Ity_I32
);
19549 error_mask
[i
] = newTemp(Ity_I32
);
19550 error_value
[i
] = newTemp(Ity_I32
);
19551 tmp_64
[i
] = newTemp(Ity_I64
);
19553 if ( opc2
== 0x1b0 ) { // xvcvdpsxws
19554 assign(Result_32_tmp
[i
], binop(Iop_F64toI32S
,
19555 rmZero
, mkexpr( value_f64
[i
] ) ) );
19557 /* result of Iop_CmpF64 is 0x01 if A < -2^31. */
19558 assign( underflow_mask
[i
],
19562 mkexpr( value_f64
[i
] ),
19563 unop( Iop_ReinterpI64asF64
,
19564 mkU64( 0xC1E0000000000000 ))))));
19565 overflow_value
= 0x7FFFFFFF;
19566 underflow_value
= 0x80000000;
19568 } else { // xvcvdpuxws
19569 assign( Result_32_tmp
[i
],
19570 binop( Iop_F64toI32U
,
19571 mkU32( Irrm_ZERO
),
19572 mkexpr( value_f64
[i
] ) ) );
19574 /* result of Iop_CmpF64 is 0x01 if A < 0. */
19575 assign( underflow_mask
[i
],
19579 mkexpr( value_f64
[i
] ),
19580 unop( Iop_ReinterpI64asF64
,
19581 mkU64( 0x0 ) ) ) ) ) );
19582 overflow_value
= 0xFFFFFFFF;
19583 underflow_value
= 0;
19586 /* Check if input is NaN, output is 0x80000000.
19587 if input < -2^31, output is 0x80000000.
19588 if input > 2^31 - 1, output is 0x7FFFFFFF */
19589 assign( tmp_64
[i
], unop (Iop_ReinterpF64asI64
,
19590 mkexpr( value_f64
[i
] ) ) );
19592 assign( nan_mask
[i
], unop( Iop_1Sto32
,
19593 is_NaN( Ity_I64
, tmp_64
[i
] ) ) );
19595 /* result of Iop_CmpF64 is 0x00 if A > 2^31 - 1. */
19596 assign( overflow_mask
[i
],
19598 binop( Iop_CmpEQ32
,
19601 mkexpr( value_f64
[i
] ),
19602 unop( Iop_ReinterpI64asF64
,
19603 mkU64( 0x41DFFFFFFFC00000 ))))));
19605 assign( error_mask
[i
], binop( Iop_Or32
, mkexpr( overflow_mask
[i
] ),
19607 mkexpr( underflow_mask
[i
] ),
19608 mkexpr( nan_mask
[i
] ) ) ) );
19610 if ( opc2
== 0x1b0 ) { // xvcvdpsxws
19611 /* NaN takes precedence over underflow/overflow for vxcvdpsxws */
19612 assign( error_value
[i
],
19615 unop( Iop_Not32
, mkexpr( nan_mask
[i
] ) ),
19618 mkexpr( overflow_mask
[i
] ),
19619 mkU32( overflow_value
) ),
19621 mkexpr( underflow_mask
[i
] ),
19622 mkU32( underflow_value
) ) ) ),
19624 mkexpr( nan_mask
[i
] ),
19625 mkU32( 0x80000000 ) ) ) );
19627 /* Less then zeo takes precedence over NaN/overflow
19628 for vxcvdpuxws in the hardware. Matching the HW here
19629 but it does not appear to match ISA. */
19630 assign( error_value
[i
],
19634 mkexpr( underflow_mask
[i
] ) ),
19637 mkexpr( overflow_mask
[i
] ),
19638 mkU32( overflow_value
) ),
19640 mkexpr( nan_mask
[i
] ),
19641 mkU32( 0x80000000 ) ) ) ),
19643 mkexpr( underflow_mask
[i
] ),
19644 mkU32( underflow_value
) ) ) );
19647 assign( Result_32
[i
], binop( Iop_Or32
,
19649 mkexpr( Result_32_tmp
[i
] ),
19651 mkexpr( error_mask
[i
] ) ) ),
19653 mkexpr( error_value
[i
] ),
19654 mkexpr( error_mask
[i
] ) ) ) );
19657 if ( opc2
== 0x1b0 ) {
19658 DIP("xvcvdpsxws v%u,v%u\n", XT
, XB
);
19661 DIP("xvcvdpuxws v%u,v%u", XT
, XB
);
19664 /* Result is put in the hi and low 32-bits of the double word result. */
19666 binop( Iop_64HLtoV128
,
19667 binop( Iop_32HLto64
,
19668 mkexpr( Result_32
[0] ),
19669 mkexpr( Result_32
[0] ) ),
19670 binop( Iop_32HLto64
,
19671 mkexpr( Result_32
[1] ),
19672 mkexpr( Result_32
[1] ) ) ) );
19675 case 0x130: case 0x110: // xvcvspsxws, xvcvspuxws
19676 // (VSX Vector truncate Single-Precision to integer and
19677 // Convert to [Un]signed Integer Word format with Saturate)
19679 IRExpr
* b0_result
, * b1_result
, * b2_result
, * b3_result
;
19680 IRTemp tempResult
= newTemp(Ity_V128
);
19681 IRTemp res0
= newTemp(Ity_I32
);
19682 IRTemp res1
= newTemp(Ity_I32
);
19683 IRTemp res2
= newTemp(Ity_I32
);
19684 IRTemp res3
= newTemp(Ity_I32
);
19685 IRTemp hi64
= newTemp(Ity_I64
);
19686 IRTemp lo64
= newTemp(Ity_I64
);
19687 Bool un_signed
= (opc2
== 0x110);
19688 IROp op
= un_signed
? Iop_QF32toI32Ux4_RZ
: Iop_QF32toI32Sx4_RZ
;
19690 DIP("xvcvsp%sxws v%u,v%u\n", un_signed
? "u" : "s", XT
, XB
);
19691 /* The xvcvsp{s|u}xws instruction is similar to vct{s|u}xs, except if src is a NaN,
19692 * then result is set to 0x80000000. */
19693 assign(tempResult
, unop(op
, getVSReg(XB
)));
19694 assign( hi64
, unop(Iop_V128HIto64
, mkexpr(tempResult
)) );
19695 assign( lo64
, unop(Iop_V128to64
, mkexpr(tempResult
)) );
19696 assign( res3
, unop(Iop_64HIto32
, mkexpr(hi64
)) );
19697 assign( res2
, unop(Iop_64to32
, mkexpr(hi64
)) );
19698 assign( res1
, unop(Iop_64HIto32
, mkexpr(lo64
)) );
19699 assign( res0
, unop(Iop_64to32
, mkexpr(lo64
)) );
19701 b3_result
= IRExpr_ITE(is_NaN(Ity_I32
, b3
),
19702 // then: result is 0x{8|0}80000000
19703 mkU32(un_signed
? 0x00000000 : 0x80000000),
19704 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
19706 b2_result
= IRExpr_ITE(is_NaN(Ity_I32
, b2
),
19707 // then: result is 0x{8|0}80000000
19708 mkU32(un_signed
? 0x00000000 : 0x80000000),
19709 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
19711 b1_result
= IRExpr_ITE(is_NaN(Ity_I32
, b1
),
19712 // then: result is 0x{8|0}80000000
19713 mkU32(un_signed
? 0x00000000 : 0x80000000),
19714 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
19716 b0_result
= IRExpr_ITE(is_NaN(Ity_I32
, b0
),
19717 // then: result is 0x{8|0}80000000
19718 mkU32(un_signed
? 0x00000000 : 0x80000000),
19719 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
19723 binop( Iop_64HLtoV128
,
19724 binop( Iop_32HLto64
, b3_result
, b2_result
),
19725 binop( Iop_32HLto64
, b1_result
, b0_result
) ) );
19728 case 0x212: // xscvdpsp (VSX Scalar round Double-Precision to single-precision and
19729 // Convert to Single-Precision format
19730 // Apr 2019 update - write the result to both halves of the
19731 // target VSR. (see bug 401827,401828).
19732 DIP("xscvdpsp v%u,v%u\n", XT
, XB
);
19733 IRTemp ResultI32a
= newTemp(Ity_I32
);
19734 assign(ResultI32a
, unop( Iop_ReinterpF32asI32
,
19735 unop( Iop_TruncF64asF32
,
19736 binop( Iop_RoundF64toF32
,
19737 get_IR_roundingmode(),
19738 mkexpr( xB
) ) ) ) );
19740 binop( Iop_64HLtoV128
,
19741 binop( Iop_32HLto64
,
19742 mkexpr(ResultI32a
),
19743 mkexpr(ResultI32a
) ),
19746 case 0x216: /* xscvdpspn (VSX Scalar convert scalar Single-Precision to
19747 vector Single-Precision non-signalling */
19748 // Apr 2019 update - write the result to both halves of the
19749 // target VSR. (see bug 401827,401828).
19750 DIP("xscvdpspn v%u,v%u\n", XT
, XB
);
19751 IRTemp ResultI32b
= newTemp(Ity_I32
);
19752 assign(ResultI32b
, unop( Iop_ReinterpF32asI32
,
19753 unop( Iop_TruncF64asF32
,
19754 mkexpr( xB
) ) ) );
19756 binop( Iop_64HLtoV128
,
19757 binop( Iop_32HLto64
,
19758 mkexpr(ResultI32b
),
19759 mkexpr(ResultI32b
) ),
19762 case 0x090: // xscvdpuxws (VSX Scalar truncate Double-Precision to integer
19763 // and Convert to Unsigned Integer Word format with Saturate)
19764 DIP("xscvdpuxws v%u,v%u\n", XT
, XB
);
19766 binop( Iop_64HLtoV128
,
19767 binop( Iop_32HLto64
,
19769 binop( Iop_F64toI32U
,
19770 mkU32( Irrm_ZERO
),
19774 case 0x292: // xscvspdp (VSX Scalar Convert Single-Precision to Double-Precision format, signaling)
19775 DIP("xscvspdp v%u,v%u\n", XT
, XB
);
19777 binop( Iop_64HLtoV128
,
19778 unop( Iop_ReinterpF64asI64
,
19779 unop( Iop_F32toF64
,
19780 unop( Iop_ReinterpI32asF32
, mkexpr( xB
) ) ) ),
19783 case 0x296: // xscvspdpn (VSX Scalar Convert Single-Precision to Double-Precision format Non signaling)
19784 DIP("xscvspdpn v%u,v%u\n", XT
, XB
);
19786 binop( Iop_64HLtoV128
,
19787 unop( Iop_ReinterpF64asI64
,
19788 unop( Iop_F32toF64
,
19789 unop( Iop_ReinterpI32asF32
, mkexpr( xB
) ) ) ),
19792 case 0x312: // xvcvdpsp (VSX Vector round Double-Precision to single-precision
19793 // and Convert to Single-Precision format)
19794 DIP("xvcvdpsp v%u,v%u\n", XT
, XB
);
19796 /* Note, the 32-bit result is put into the upper and lower bits of the
19797 doubleword result. */
19799 binop( Iop_64HLtoV128
,
19800 binop( Iop_32HLto64
,
19801 unop( Iop_ReinterpF32asI32
,
19802 unop( Iop_TruncF64asF32
,
19803 binop( Iop_RoundF64toF32
,
19804 get_IR_roundingmode(),
19805 mkexpr( xB
) ) ) ),
19806 unop( Iop_ReinterpF32asI32
,
19807 unop( Iop_TruncF64asF32
,
19808 binop( Iop_RoundF64toF32
,
19809 get_IR_roundingmode(),
19810 mkexpr( xB
) ) ) ) ),
19811 binop( Iop_32HLto64
,
19812 unop( Iop_ReinterpF32asI32
,
19813 unop( Iop_TruncF64asF32
,
19814 binop( Iop_RoundF64toF32
,
19815 get_IR_roundingmode(),
19816 mkexpr( xB2
) ) ) ),
19817 unop( Iop_ReinterpF32asI32
,
19818 unop( Iop_TruncF64asF32
,
19819 binop( Iop_RoundF64toF32
,
19820 get_IR_roundingmode(),
19821 mkexpr( xB2
) ) ) ) ) ) );
19823 case 0x390: // xvcvdpuxds (VSX Vector truncate Double-Precision to integer
19824 // and Convert to Unsigned Integer Doubleword format
19826 DIP("xvcvdpuxds v%u,v%u\n", XT
, XB
);
19828 binop( Iop_64HLtoV128
,
19829 binop( Iop_F64toI64U
, mkU32( Irrm_ZERO
), mkexpr( xB
) ),
19830 binop( Iop_F64toI64U
, mkU32( Irrm_ZERO
), mkexpr( xB2
) ) ) );
19832 case 0x392: // xvcvspdp (VSX Vector Convert Single-Precision to Double-Precision format)
19833 DIP("xvcvspdp v%u,v%u\n", XT
, XB
);
19835 binop( Iop_64HLtoV128
,
19836 unop( Iop_ReinterpF64asI64
,
19837 unop( Iop_F32toF64
,
19838 unop( Iop_ReinterpI32asF32
,
19839 handle_SNaN_to_QNaN_32( mkexpr( b3
) ) ) ) ),
19840 unop( Iop_ReinterpF64asI64
,
19841 unop( Iop_F32toF64
,
19842 unop( Iop_ReinterpI32asF32
,
19843 handle_SNaN_to_QNaN_32( mkexpr( b1
) ) ) ) ) ) );
19845 case 0x330: // xvcvspsxds (VSX Vector truncate Single-Precision to integer and
19846 // Convert to Signed Integer Doubleword format with Saturate)
19847 DIP("xvcvspsxds v%u,v%u\n", XT
, XB
);
19849 binop( Iop_64HLtoV128
,
19850 binop( Iop_F64toI64S
,
19851 mkU32( Irrm_ZERO
),
19852 unop( Iop_F32toF64
,
19853 unop( Iop_ReinterpI32asF32
, mkexpr( b3
) ) ) ),
19854 binop( Iop_F64toI64S
,
19855 mkU32( Irrm_ZERO
),
19856 unop( Iop_F32toF64
,
19857 unop( Iop_ReinterpI32asF32
, mkexpr( b1
) ) ) ) ) );
19859 case 0x310: // xvcvspuxds (VSX Vector truncate Single-Precision to integer and
19860 // Convert to Unsigned Integer Doubleword format with Saturate)
19861 DIP("xvcvspuxds v%u,v%u\n", XT
, XB
);
19863 binop( Iop_64HLtoV128
,
19864 binop( Iop_F64toI64U
,
19865 mkU32( Irrm_ZERO
),
19866 unop( Iop_F32toF64
,
19867 unop( Iop_ReinterpI32asF32
, mkexpr( b3
) ) ) ),
19868 binop( Iop_F64toI64U
,
19869 mkU32( Irrm_ZERO
),
19870 unop( Iop_F32toF64
,
19871 unop( Iop_ReinterpI32asF32
, mkexpr( b1
) ) ) ) ) );
19873 case 0x3B0: // xvcvdpsxds (VSX Vector truncate Double-Precision to integer and
19874 // Convert to Signed Integer Doubleword format with Saturate)
19875 DIP("xvcvdpsxds v%u,v%u\n", XT
, XB
);
19877 binop( Iop_64HLtoV128
,
19878 binop( Iop_F64toI64S
, mkU32( Irrm_ZERO
), mkexpr( xB
) ),
19879 binop( Iop_F64toI64S
, mkU32( Irrm_ZERO
), mkexpr( xB2
) ) ) );
19881 case 0x3f0: // xvcvsxddp (VSX Vector Convert and round Signed Integer Doubleword
19882 // to Double-Precision format)
19883 DIP("xvcvsxddp v%u,v%u\n", XT
, XB
);
19885 binop( Iop_64HLtoV128
,
19886 unop( Iop_ReinterpF64asI64
,
19887 binop( Iop_I64StoF64
,
19888 get_IR_roundingmode(),
19890 unop( Iop_ReinterpF64asI64
,
19891 binop( Iop_I64StoF64
,
19892 get_IR_roundingmode(),
19893 mkexpr( xB2
) ) ) ) );
19895 case 0x3d0: // xvcvuxddp (VSX Vector Convert and round Unsigned Integer Doubleword
19896 // to Double-Precision format)
19897 DIP("xvcvuxddp v%u,v%u\n", XT
, XB
);
19899 binop( Iop_64HLtoV128
,
19900 unop( Iop_ReinterpF64asI64
,
19901 binop( Iop_I64UtoF64
,
19902 get_IR_roundingmode(),
19904 unop( Iop_ReinterpF64asI64
,
19905 binop( Iop_I64UtoF64
,
19906 get_IR_roundingmode(),
19907 mkexpr( xB2
) ) ) ) );
19910 case 0x370: // xvcvsxdsp (VSX Vector Convert and round Signed Integer Doubleword
19911 // to Single-Precision format)
19913 IRTemp result32hi
= newTemp(Ity_I32
);
19914 IRTemp result32lo
= newTemp(Ity_I32
);
19916 DIP("xvcvsxdsp v%u,v%u\n", XT
, XB
);
19917 assign( result32hi
,
19918 unop( Iop_ReinterpF32asI32
,
19919 unop( Iop_TruncF64asF32
,
19920 binop( Iop_RoundF64toF32
,
19921 get_IR_roundingmode(),
19922 binop( Iop_I64StoF64
,
19923 get_IR_roundingmode(),
19924 mkexpr( xB
) ) ) ) ) );
19925 assign( result32lo
,
19926 unop( Iop_ReinterpF32asI32
,
19927 unop( Iop_TruncF64asF32
,
19928 binop( Iop_RoundF64toF32
,
19929 get_IR_roundingmode(),
19930 binop( Iop_I64StoF64
,
19931 get_IR_roundingmode(),
19932 mkexpr( xB2
) ) ) ) ) );
19935 binop( Iop_64HLtoV128
,
19936 binop( Iop_32HLto64
,
19937 mkexpr( result32hi
),
19938 mkexpr( result32hi
) ),
19939 binop( Iop_32HLto64
,
19940 mkexpr( result32lo
),
19941 mkexpr( result32lo
) ) ) );
19944 case 0x350: // xvcvuxdsp (VSX Vector Convert and round Unsigned Integer Doubleword
19945 // to Single-Precision format)
19947 IRTemp result32hi
= newTemp(Ity_I32
);
19948 IRTemp result32lo
= newTemp(Ity_I32
);
19950 DIP("xvcvuxdsp v%u,v%u\n", XT
, XB
);
19951 assign( result32hi
,
19952 unop( Iop_ReinterpF32asI32
,
19953 unop( Iop_TruncF64asF32
,
19954 binop( Iop_RoundF64toF32
,
19955 get_IR_roundingmode(),
19956 binop( Iop_I64UtoF64
,
19957 get_IR_roundingmode(),
19958 mkexpr( xB
) ) ) ) ) );
19959 assign( result32lo
,
19960 unop( Iop_ReinterpF32asI32
,
19961 unop( Iop_TruncF64asF32
,
19962 binop( Iop_RoundF64toF32
,
19963 get_IR_roundingmode(),
19964 binop( Iop_I64UtoF64
,
19965 get_IR_roundingmode(),
19966 mkexpr( xB2
) ) ) ) ) );
19968 binop( Iop_64HLtoV128
,
19969 binop( Iop_32HLto64
,
19970 mkexpr( result32hi
),
19971 mkexpr( result32hi
) ),
19972 binop( Iop_32HLto64
,
19973 mkexpr( result32lo
),
19974 mkexpr( result32lo
) ) ) );
19978 case 0x1f0: // xvcvsxwdp (VSX Vector Convert Signed Integer Word to Double-Precision format)
19979 DIP("xvcvsxwdp v%u,v%u\n", XT
, XB
);
19981 binop( Iop_64HLtoV128
,
19982 unop( Iop_ReinterpF64asI64
,
19983 binop( Iop_I64StoF64
, get_IR_roundingmode(),
19984 unop( Iop_32Sto64
, mkexpr( b3
) ) ) ),
19985 unop( Iop_ReinterpF64asI64
,
19986 binop( Iop_I64StoF64
, get_IR_roundingmode(),
19987 unop( Iop_32Sto64
, mkexpr( b1
) ) ) ) ) );
19989 case 0x1d0: // xvcvuxwdp (VSX Vector Convert Unsigned Integer Word to Double-Precision format)
19990 DIP("xvcvuxwdp v%u,v%u\n", XT
, XB
);
19992 binop( Iop_64HLtoV128
,
19993 unop( Iop_ReinterpF64asI64
,
19994 binop( Iop_I64UtoF64
, get_IR_roundingmode(),
19995 unop( Iop_32Uto64
, mkexpr( b3
) ) ) ),
19996 unop( Iop_ReinterpF64asI64
,
19997 binop( Iop_I64UtoF64
, get_IR_roundingmode(),
19998 unop( Iop_32Uto64
, mkexpr( b1
) ) ) ) ) );
20000 case 0x170: // xvcvsxwsp (VSX Vector Convert Signed Integer Word to Single-Precision format)
20001 DIP("xvcvsxwsp v%u,v%u\n", XT
, XB
);
20002 putVSReg( XT
, unop( Iop_I32StoF32x4_DEP
, getVSReg( XB
) ) );
20004 case 0x150: // xvcvuxwsp (VSX Vector Convert Unsigned Integer Word to Single-Precision format)
20005 DIP("xvcvuxwsp v%u,v%u\n", XT
, XB
);
20006 putVSReg( XT
, unop( Iop_I32UtoF32x4_DEP
, getVSReg( XB
) ) );
20010 vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
20017 * VSX vector Double Precision Floating Point Arithmetic Instructions
20020 dis_vxv_dp_arith ( UInt prefix
, UInt theInstr
, UInt opc2
)
20023 UChar opc1
= ifieldOPC( theInstr
);
20024 UChar XT
= ifieldRegXT( theInstr
);
20025 UChar XA
= ifieldRegXA( theInstr
);
20026 UChar XB
= ifieldRegXB( theInstr
);
20027 IRExpr
* rm
= get_IR_roundingmode();
20028 IRTemp frA
= newTemp(Ity_F64
);
20029 IRTemp frB
= newTemp(Ity_F64
);
20030 IRTemp frA2
= newTemp(Ity_F64
);
20031 IRTemp frB2
= newTemp(Ity_F64
);
20033 /* There is no prefixed version of these instructions. */
20036 if (opc1
!= 0x3C) {
20037 vex_printf( "dis_vxv_dp_arith(ppc)(instr)\n" );
20041 assign(frA
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128HIto64
, getVSReg( XA
))));
20042 assign(frB
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128HIto64
, getVSReg( XB
))));
20043 assign(frA2
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128to64
, getVSReg( XA
))));
20044 assign(frB2
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128to64
, getVSReg( XB
))));
20047 case 0x1E0: // xvdivdp (VSX Vector Divide Double-Precision)
20048 case 0x1C0: // xvmuldp (VSX Vector Multiply Double-Precision)
20049 case 0x180: // xvadddp (VSX Vector Add Double-Precision)
20050 case 0x1A0: // xvsubdp (VSX Vector Subtract Double-Precision)
20053 const HChar
* oper_name
;
20073 vpanic("The impossible happened: dis_vxv_dp_arith(ppc)");
20075 IRTemp hiResult
= newTemp(Ity_I64
);
20076 IRTemp loResult
= newTemp(Ity_I64
);
20077 DIP("xv%sdp v%d,v%d,v%d\n", oper_name
, XT
, XA
, XB
);
20080 unop( Iop_ReinterpF64asI64
,
20081 triop( mOp
, rm
, mkexpr( frA
), mkexpr( frB
) ) ) );
20083 unop( Iop_ReinterpF64asI64
,
20084 triop( mOp
, rm
, mkexpr( frA2
), mkexpr( frB2
) ) ) );
20086 binop( Iop_64HLtoV128
, mkexpr( hiResult
), mkexpr( loResult
) ) );
20089 case 0x196: // xvsqrtdp
20091 IRTemp hiResult
= newTemp(Ity_I64
);
20092 IRTemp loResult
= newTemp(Ity_I64
);
20093 DIP("xvsqrtdp v%d,v%d\n", XT
, XB
);
20096 unop( Iop_ReinterpF64asI64
,
20097 binop( Iop_SqrtF64
, rm
, mkexpr( frB
) ) ) );
20099 unop( Iop_ReinterpF64asI64
,
20100 binop( Iop_SqrtF64
, rm
, mkexpr( frB2
) ) ) );
20102 binop( Iop_64HLtoV128
, mkexpr( hiResult
), mkexpr( loResult
) ) );
20105 case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp (VSX Vector Multiply-Add Double-Precision)
20106 case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp (VSX Vector Multiply-Subtract Double-Precision)
20107 case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp (VSX Vector Negate Multiply-Add Double-Precision)
20108 case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp (VSX Vector Negate Multiply-Subtract Double-Precision)
20110 /* xvm{add|sub}mdp XT,XA,XB is element-wise equivalent to fm{add|sub} FRT,FRA,FRC,FRB with . . .
20115 * and for xvm{add|sub}adp . . .
20121 IROp mOp
= Iop_INVALID
;
20122 const HChar
* oper_name
= NULL
;
20126 case 0x184: case 0x1A4:
20127 case 0x384: case 0x3A4:
20130 mdp
= (opc2
& 0x0FF) == 0x0A4;
20133 case 0x1C4: case 0x1E4:
20134 case 0x3C4: case 0x3E4:
20137 mdp
= (opc2
& 0x0FF) == 0x0E4;
20141 vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
20145 case 0x384: case 0x3A4:
20146 case 0x3C4: case 0x3E4:
20152 IRTemp hiResult
= newTemp(Ity_I64
);
20153 IRTemp loResult
= newTemp(Ity_I64
);
20154 IRTemp frT
= newTemp(Ity_F64
);
20155 IRTemp frT2
= newTemp(Ity_F64
);
20156 DIP("xv%sm%s%s v%d,v%d,v%d\n", negate
? "n" : "", oper_name
, mdp
? "mdp" : "adp",
20158 assign(frT
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128HIto64
, getVSReg( XT
) ) ) );
20159 assign(frT2
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128to64
, getVSReg( XT
) ) ) );
20162 unop( Iop_ReinterpF64asI64
,
20166 mkexpr( mdp
? frT
: frB
),
20167 mkexpr( mdp
? frB
: frT
) ) ) );
20169 unop( Iop_ReinterpF64asI64
,
20173 mkexpr( mdp
? frT2
: frB2
),
20174 mkexpr( mdp
? frB2
: frT2
) ) ) );
20176 binop( Iop_64HLtoV128
,
20177 mkexpr( negate
? getNegatedResult( hiResult
)
20179 mkexpr( negate
? getNegatedResult( loResult
)
20183 case 0x1D4: // xvtsqrtdp (VSX Vector Test for software Square Root Double-Precision)
20185 IRTemp frBHi_I64
= newTemp(Ity_I64
);
20186 IRTemp frBLo_I64
= newTemp(Ity_I64
);
20187 IRTemp flagsHi
= newTemp(Ity_I32
);
20188 IRTemp flagsLo
= newTemp(Ity_I32
);
20189 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) );
20190 IRTemp fe_flagHi
, fg_flagHi
, fe_flagLo
, fg_flagLo
;
20191 fe_flagHi
= fg_flagHi
= fe_flagLo
= fg_flagLo
= IRTemp_INVALID
;
20193 DIP("xvtsqrtdp cr%d,v%d\n", crfD
, XB
);
20194 assign( frBHi_I64
, unop(Iop_V128HIto64
, getVSReg( XB
)) );
20195 assign( frBLo_I64
, unop(Iop_V128to64
, getVSReg( XB
)) );
20196 do_fp_tsqrt(frBHi_I64
, False
/*not single precision*/, &fe_flagHi
, &fg_flagHi
);
20197 do_fp_tsqrt(frBLo_I64
, False
/*not single precision*/, &fe_flagLo
, &fg_flagLo
);
20198 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
20199 * where fl_flag == 1 on ppc64.
20203 binop( Iop_Or32
, mkU32( 8 ), // fl_flag
20204 binop( Iop_Shl32
, mkexpr(fg_flagHi
), mkU8( 2 ) ) ),
20205 binop( Iop_Shl32
, mkexpr(fe_flagHi
), mkU8( 1 ) ) ) );
20208 binop( Iop_Or32
, mkU32( 8 ), // fl_flag
20209 binop( Iop_Shl32
, mkexpr(fg_flagLo
), mkU8( 2 ) ) ),
20210 binop( Iop_Shl32
, mkexpr(fe_flagLo
), mkU8( 1 ) ) ) );
20211 putGST_field( PPC_GST_CR
,
20212 binop( Iop_Or32
, mkexpr( flagsHi
), mkexpr( flagsLo
) ),
20216 case 0x1F4: // xvtdivdp (VSX Vector Test for software Divide Double-Precision)
20218 IRTemp frBHi_I64
= newTemp(Ity_I64
);
20219 IRTemp frBLo_I64
= newTemp(Ity_I64
);
20220 IRTemp frAHi_I64
= newTemp(Ity_I64
);
20221 IRTemp frALo_I64
= newTemp(Ity_I64
);
20222 IRTemp flagsHi
= newTemp(Ity_I32
);
20223 IRTemp flagsLo
= newTemp(Ity_I32
);
20224 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) );
20225 IRTemp fe_flagHi
, fg_flagHi
, fe_flagLo
, fg_flagLo
;
20226 fe_flagHi
= fg_flagHi
= fe_flagLo
= fg_flagLo
= IRTemp_INVALID
;
20228 DIP("xvtdivdp cr%d,v%d,v%d\n", crfD
, XA
, XB
);
20229 assign( frAHi_I64
, unop(Iop_V128HIto64
, getVSReg( XA
)) );
20230 assign( frALo_I64
, unop(Iop_V128to64
, getVSReg( XA
)) );
20231 assign( frBHi_I64
, unop(Iop_V128HIto64
, getVSReg( XB
)) );
20232 assign( frBLo_I64
, unop(Iop_V128to64
, getVSReg( XB
)) );
20234 _do_fp_tdiv(frAHi_I64
, frBHi_I64
, False
/*dp*/, &fe_flagHi
, &fg_flagHi
);
20235 _do_fp_tdiv(frALo_I64
, frBLo_I64
, False
/*dp*/, &fe_flagLo
, &fg_flagLo
);
20236 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
20237 * where fl_flag == 1 on ppc64.
20241 binop( Iop_Or32
, mkU32( 8 ), // fl_flag
20242 binop( Iop_Shl32
, mkexpr(fg_flagHi
), mkU8( 2 ) ) ),
20243 binop( Iop_Shl32
, mkexpr(fe_flagHi
), mkU8( 1 ) ) ) );
20246 binop( Iop_Or32
, mkU32( 8 ), // fl_flag
20247 binop( Iop_Shl32
, mkexpr(fg_flagLo
), mkU8( 2 ) ) ),
20248 binop( Iop_Shl32
, mkexpr(fe_flagLo
), mkU8( 1 ) ) ) );
20249 putGST_field( PPC_GST_CR
,
20250 binop( Iop_Or32
, mkexpr( flagsHi
), mkexpr( flagsLo
) ),
20256 vex_printf( "dis_vxv_dp_arith(ppc)(opc2)\n" );
20263 * VSX vector Single Precision Floating Point Arithmetic Instructions
20266 dis_vxv_sp_arith ( UInt prefix
, UInt theInstr
, UInt opc2
)
20269 UChar opc1
= ifieldOPC( theInstr
);
20270 UChar XT
= ifieldRegXT( theInstr
);
20271 UChar XA
= ifieldRegXA( theInstr
);
20272 UChar XB
= ifieldRegXB( theInstr
);
20273 IRExpr
* rm
= get_IR_roundingmode();
20274 IRTemp a3
, a2
, a1
, a0
;
20275 IRTemp b3
, b2
, b1
, b0
;
20276 IRTemp res0
= newTemp(Ity_I32
);
20277 IRTemp res1
= newTemp(Ity_I32
);
20278 IRTemp res2
= newTemp(Ity_I32
);
20279 IRTemp res3
= newTemp(Ity_I32
);
20281 /* There is no prefixed version of these instructions. */
20284 a3
= a2
= a1
= a0
= IRTemp_INVALID
;
20285 b3
= b2
= b1
= b0
= IRTemp_INVALID
;
20287 if (opc1
!= 0x3C) {
20288 vex_printf( "dis_vxv_sp_arith(ppc)(instr)\n" );
20293 case 0x100: // xvaddsp (VSX Vector Add Single-Precision)
20294 DIP("xvaddsp v%d,v%d,v%d\n", XT
, XA
, XB
);
20295 // WARNING: BOGUS! The backend ignores rm on Iop_Add32Fx4
20296 putVSReg( XT
, triop(Iop_Add32Fx4
, rm
,
20297 getVSReg( XA
), getVSReg( XB
)) );
20300 case 0x140: // xvmulsp (VSX Vector Multiply Single-Precision)
20301 DIP("xvmulsp v%d,v%d,v%d\n", XT
, XA
, XB
);
20302 // WARNING: BOGUS! The backend ignores rm on Iop_Mul32Fx4
20303 putVSReg( XT
, triop(Iop_Mul32Fx4
, rm
,
20304 getVSReg( XA
), getVSReg( XB
)) );
20307 case 0x120: // xvsubsp (VSX Vector Subtract Single-Precision)
20308 DIP("xvsubsp v%d,v%d,v%d\n", XT
, XA
, XB
);
20309 // WARNING: BOGUS! The backend ignores rm on Iop_Sub32Fx4
20310 putVSReg( XT
, triop(Iop_Sub32Fx4
, rm
,
20311 getVSReg( XA
), getVSReg( XB
)) );
20314 case 0x160: // xvdivsp (VSX Vector Divide Single-Precision)
20316 /* Iop_Div32Fx4 is not implemented for ppc64 (in host_ppc_{isel|defs}.c.
20317 * So there are two choices:
20318 * 1. Implement the xvdivsp with a native insn; or
20319 * 2. Extract the 4 single precision floats from each vector
20320 * register inputs and perform fdivs on each pair
20321 * I will do the latter, due to the general philosophy of
20322 * reusing existing implementations when practical.
20324 DIP("xvdivsp v%d,v%d,v%d\n", XT
, XA
, XB
);
20325 breakV128to4xF64( getVSReg( XA
), &a3
, &a2
, &a1
, &a0
);
20326 breakV128to4xF64( getVSReg( XB
), &b3
, &b2
, &b1
, &b0
);
20329 unop( Iop_ReinterpF32asI32
,
20330 unop( Iop_TruncF64asF32
,
20331 triop( Iop_DivF64r32
, rm
, mkexpr( a0
), mkexpr( b0
) ) ) ) );
20333 unop( Iop_ReinterpF32asI32
,
20334 unop( Iop_TruncF64asF32
,
20335 triop( Iop_DivF64r32
, rm
, mkexpr( a1
), mkexpr( b1
) ) ) ) );
20337 unop( Iop_ReinterpF32asI32
,
20338 unop( Iop_TruncF64asF32
,
20339 triop( Iop_DivF64r32
, rm
, mkexpr( a2
), mkexpr( b2
) ) ) ) );
20341 unop( Iop_ReinterpF32asI32
,
20342 unop( Iop_TruncF64asF32
,
20343 triop( Iop_DivF64r32
, rm
, mkexpr( a3
), mkexpr( b3
) ) ) ) );
20346 binop( Iop_64HLtoV128
,
20347 binop( Iop_32HLto64
, mkexpr( res3
), mkexpr( res2
) ),
20348 binop( Iop_32HLto64
, mkexpr( res1
), mkexpr( res0
) ) ) );
20351 case 0x116: // xvsqrtsp (VSX Vector Square Root Single-Precision)
20353 DIP("xvsqrtsp v%d,v%d\n", XT
, XB
);
20354 breakV128to4xF64( getVSReg( XB
), &b3
, &b2
, &b1
, &b0
);
20355 /* Note: The native xvsqrtsp insruction does not always give the same precision
20356 * as what we get with Iop_SqrtF64. But it doesn't seem worthwhile to implement
20357 * an Iop_SqrtF32 that would give us a lower precision result, albeit more true
20358 * to the actual instruction.
20362 unop( Iop_ReinterpF32asI32
,
20363 unop( Iop_TruncF64asF32
,
20364 binop(Iop_SqrtF64
, rm
, mkexpr( b0
) ) ) ) );
20366 unop( Iop_ReinterpF32asI32
,
20367 unop( Iop_TruncF64asF32
,
20368 binop(Iop_SqrtF64
, rm
, mkexpr( b1
) ) ) ) );
20370 unop( Iop_ReinterpF32asI32
,
20371 unop( Iop_TruncF64asF32
,
20372 binop(Iop_SqrtF64
, rm
, mkexpr( b2
) ) ) ) );
20374 unop( Iop_ReinterpF32asI32
,
20375 unop( Iop_TruncF64asF32
,
20376 binop(Iop_SqrtF64
, rm
, mkexpr( b3
) ) ) ) );
20379 binop( Iop_64HLtoV128
,
20380 binop( Iop_32HLto64
, mkexpr( res3
), mkexpr( res2
) ),
20381 binop( Iop_32HLto64
, mkexpr( res1
), mkexpr( res0
) ) ) );
20385 case 0x104: case 0x124: // xvmaddasp, xvmaddmsp (VSX Vector Multiply-Add Single-Precision)
20386 case 0x144: case 0x164: // xvmsubasp, xvmsubmsp (VSX Vector Multiply-Subtract Single-Precision)
20387 case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp (VSX Vector Negate Multiply-Add Single-Precision)
20388 case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp (VSX Vector Negate Multiply-Subtract Single-Precision)
20390 IRTemp t3
, t2
, t1
, t0
;
20393 const HChar
* oper_name
= NULL
;
20394 IROp mOp
= Iop_INVALID
;
20396 case 0x104: case 0x124:
20397 case 0x304: case 0x324:
20398 msp
= (opc2
& 0x0FF) == 0x024;
20399 mOp
= Iop_MAddF64r32
;
20400 oper_name
= "madd";
20403 case 0x144: case 0x164:
20404 case 0x344: case 0x364:
20405 msp
= (opc2
& 0x0FF) == 0x064;
20406 mOp
= Iop_MSubF64r32
;
20411 vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
20415 case 0x304: case 0x324:
20416 case 0x344: case 0x364:
20424 DIP("xv%sm%s%s v%d,v%d,v%d\n", negate
? "n" : "", oper_name
,
20425 msp
? "msp" : "asp", XT
, XA
, XB
);
20427 t3
= t2
= t1
= t0
= IRTemp_INVALID
;
20428 breakV128to4xF64( getVSReg( XA
), &a3
, &a2
, &a1
, &a0
);
20429 breakV128to4xF64( getVSReg( XB
), &b3
, &b2
, &b1
, &b0
);
20430 breakV128to4xF64( getVSReg( XT
), &t3
, &t2
, &t1
, &t0
);
20433 unop( Iop_ReinterpF32asI32
,
20434 unop( Iop_TruncF64asF32
,
20438 mkexpr( msp
? t0
: b0
),
20439 mkexpr( msp
? b0
: t0
) ) ) ) );
20441 unop( Iop_ReinterpF32asI32
,
20442 unop( Iop_TruncF64asF32
,
20446 mkexpr( msp
? t1
: b1
),
20447 mkexpr( msp
? b1
: t1
) ) ) ) );
20449 unop( Iop_ReinterpF32asI32
,
20450 unop( Iop_TruncF64asF32
,
20454 mkexpr( msp
? t2
: b2
),
20455 mkexpr( msp
? b2
: t2
) ) ) ) );
20457 unop( Iop_ReinterpF32asI32
,
20458 unop( Iop_TruncF64asF32
,
20462 mkexpr( msp
? t3
: b3
),
20463 mkexpr( msp
? b3
: t3
) ) ) ) );
20466 binop( Iop_64HLtoV128
,
20467 binop( Iop_32HLto64
, mkexpr( negate
? getNegatedResult_32( res3
) : res3
),
20468 mkexpr( negate
? getNegatedResult_32( res2
) : res2
) ),
20469 binop( Iop_32HLto64
, mkexpr( negate
? getNegatedResult_32( res1
) : res1
),
20470 mkexpr( negate
? getNegatedResult_32( res0
) : res0
) ) ) );
20474 case 0x154: // xvtsqrtsp (VSX Vector Test for software Square Root Single-Precision)
20476 IRTemp flags0
= newTemp(Ity_I32
);
20477 IRTemp flags1
= newTemp(Ity_I32
);
20478 IRTemp flags2
= newTemp(Ity_I32
);
20479 IRTemp flags3
= newTemp(Ity_I32
);
20480 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) );
20481 IRTemp fe_flag0
, fg_flag0
, fe_flag1
, fg_flag1
;
20482 IRTemp fe_flag2
, fg_flag2
, fe_flag3
, fg_flag3
;
20483 fe_flag0
= fg_flag0
= fe_flag1
= fg_flag1
= IRTemp_INVALID
;
20484 fe_flag2
= fg_flag2
= fe_flag3
= fg_flag3
= IRTemp_INVALID
;
20485 DIP("xvtsqrtsp cr%d,v%d\n", crfD
, XB
);
20487 breakV128to4x32( getVSReg( XB
), &b3
, &b2
, &b1
, &b0
);
20488 do_fp_tsqrt(b0
, True
/* single precision*/, &fe_flag0
, &fg_flag0
);
20489 do_fp_tsqrt(b1
, True
/* single precision*/, &fe_flag1
, &fg_flag1
);
20490 do_fp_tsqrt(b2
, True
/* single precision*/, &fe_flag2
, &fg_flag2
);
20491 do_fp_tsqrt(b3
, True
/* single precision*/, &fe_flag3
, &fg_flag3
);
20493 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
20494 * where fl_flag == 1 on ppc64.
20498 binop( Iop_Or32
, mkU32( 8 ), // fl_flag
20499 binop( Iop_Shl32
, mkexpr(fg_flag0
), mkU8( 2 ) ) ),
20500 binop( Iop_Shl32
, mkexpr(fe_flag0
), mkU8( 1 ) ) ) );
20503 binop( Iop_Or32
, mkU32( 8 ), // fl_flag
20504 binop( Iop_Shl32
, mkexpr(fg_flag1
), mkU8( 2 ) ) ),
20505 binop( Iop_Shl32
, mkexpr(fe_flag1
), mkU8( 1 ) ) ) );
20508 binop( Iop_Or32
, mkU32( 8 ), // fl_flag
20509 binop( Iop_Shl32
, mkexpr(fg_flag2
), mkU8( 2 ) ) ),
20510 binop( Iop_Shl32
, mkexpr(fe_flag2
), mkU8( 1 ) ) ) );
20513 binop( Iop_Or32
, mkU32( 8 ), // fl_flag
20514 binop( Iop_Shl32
, mkexpr(fg_flag3
), mkU8( 2 ) ) ),
20515 binop( Iop_Shl32
, mkexpr(fe_flag3
), mkU8( 1 ) ) ) );
20516 putGST_field( PPC_GST_CR
,
20523 mkexpr( flags3
) ) ) ),
20528 case 0x174: // xvtdivsp (VSX Vector Test for software Divide Single-Precision)
20530 IRTemp flags0
= newTemp(Ity_I32
);
20531 IRTemp flags1
= newTemp(Ity_I32
);
20532 IRTemp flags2
= newTemp(Ity_I32
);
20533 IRTemp flags3
= newTemp(Ity_I32
);
20534 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) );
20535 IRTemp fe_flag0
, fg_flag0
, fe_flag1
, fg_flag1
;
20536 IRTemp fe_flag2
, fg_flag2
, fe_flag3
, fg_flag3
;
20537 fe_flag0
= fg_flag0
= fe_flag1
= fg_flag1
= IRTemp_INVALID
;
20538 fe_flag2
= fg_flag2
= fe_flag3
= fg_flag3
= IRTemp_INVALID
;
20539 DIP("xvtdivsp cr%d,v%d,v%d\n", crfD
, XA
, XB
);
20541 breakV128to4x32( getVSReg( XA
), &a3
, &a2
, &a1
, &a0
);
20542 breakV128to4x32( getVSReg( XB
), &b3
, &b2
, &b1
, &b0
);
20543 _do_fp_tdiv(a0
, b0
, True
/* single precision*/, &fe_flag0
, &fg_flag0
);
20544 _do_fp_tdiv(a1
, b1
, True
/* single precision*/, &fe_flag1
, &fg_flag1
);
20545 _do_fp_tdiv(a2
, b2
, True
/* single precision*/, &fe_flag2
, &fg_flag2
);
20546 _do_fp_tdiv(a3
, b3
, True
/* single precision*/, &fe_flag3
, &fg_flag3
);
20548 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
20549 * where fl_flag == 1 on ppc64.
20553 binop( Iop_Or32
, mkU32( 8 ), // fl_flag
20554 binop( Iop_Shl32
, mkexpr(fg_flag0
), mkU8( 2 ) ) ),
20555 binop( Iop_Shl32
, mkexpr(fe_flag0
), mkU8( 1 ) ) ) );
20558 binop( Iop_Or32
, mkU32( 8 ), // fl_flag
20559 binop( Iop_Shl32
, mkexpr(fg_flag1
), mkU8( 2 ) ) ),
20560 binop( Iop_Shl32
, mkexpr(fe_flag1
), mkU8( 1 ) ) ) );
20563 binop( Iop_Or32
, mkU32( 8 ), // fl_flag
20564 binop( Iop_Shl32
, mkexpr(fg_flag2
), mkU8( 2 ) ) ),
20565 binop( Iop_Shl32
, mkexpr(fe_flag2
), mkU8( 1 ) ) ) );
20568 binop( Iop_Or32
, mkU32( 8 ), // fl_flag
20569 binop( Iop_Shl32
, mkexpr(fg_flag3
), mkU8( 2 ) ) ),
20570 binop( Iop_Shl32
, mkexpr(fe_flag3
), mkU8( 1 ) ) ) );
20571 putGST_field( PPC_GST_CR
,
20578 mkexpr( flags3
) ) ) ),
20585 vex_printf( "dis_vxv_sp_arith(ppc)(opc2)\n" );
20592 * Vector Population Count/bit matrix transpose
20595 dis_av_count_bitTranspose ( UInt prefix
, UInt theInstr
, UInt opc2
)
20597 UChar vRB_addr
= ifieldRegB(theInstr
);
20598 UChar vRT_addr
= ifieldRegDS(theInstr
);
20599 UChar opc1
= ifieldOPC( theInstr
);
20600 IRTemp vB
= newTemp(Ity_V128
);
20602 /* There is no prefixed version of these instructions. */
20605 assign( vB
, getVReg(vRB_addr
));
20608 vex_printf( "dis_av_count_bitTranspose(ppc)(instr)\n" );
20613 case 0x702: // vclzb
20614 DIP("vclzb v%d,v%d\n", vRT_addr
, vRB_addr
);
20615 putVReg( vRT_addr
, unop(Iop_Clz8x16
, mkexpr( vB
) ) );
20618 case 0x742: // vclzh
20619 DIP("vclzh v%d,v%d\n", vRT_addr
, vRB_addr
);
20620 putVReg( vRT_addr
, unop(Iop_Clz16x8
, mkexpr( vB
) ) );
20623 case 0x782: // vclzw
20624 DIP("vclzw v%d,v%d\n", vRT_addr
, vRB_addr
);
20625 putVReg( vRT_addr
, unop(Iop_Clz32x4
, mkexpr( vB
) ) );
20628 case 0x7C2: // vclzd
20629 DIP("vclzd v%d,v%d\n", vRT_addr
, vRB_addr
);
20630 putVReg( vRT_addr
, unop(Iop_Clz64x2
, mkexpr( vB
) ) );
20633 case 0x703: // vpopcntb
20635 /* Break vector into 32-bit words and do the population count
20636 * on byte in the words
20638 IRType ty
= Ity_I32
;
20639 IRTemp bits0_31
, bits32_63
, bits64_95
, bits96_127
;
20640 bits0_31
= bits32_63
= bits64_95
= bits96_127
= IRTemp_INVALID
;
20641 IRTemp cnt_bits0_31
, cnt_bits32_63
, cnt_bits64_95
, cnt_bits96_127
;
20642 cnt_bits0_31
= cnt_bits32_63
= cnt_bits64_95
= cnt_bits96_127
= IRTemp_INVALID
;
20644 DIP("vpopcntb v%d,v%d\n", vRT_addr
, vRB_addr
);
20645 breakV128to4x32(mkexpr( vB
), &bits96_127
, &bits64_95
, &bits32_63
, &bits0_31
);
20646 cnt_bits0_31
= gen_POPCOUNT(ty
, bits0_31
, BYTE
);
20647 cnt_bits32_63
= gen_POPCOUNT(ty
, bits32_63
, BYTE
);
20648 cnt_bits64_95
= gen_POPCOUNT(ty
, bits64_95
, BYTE
);
20649 cnt_bits96_127
= gen_POPCOUNT(ty
, bits96_127
, BYTE
);
20651 putVReg( vRT_addr
, mkV128from32(cnt_bits96_127
, cnt_bits64_95
,
20652 cnt_bits32_63
, cnt_bits0_31
) );
20656 case 0x743: // vpopcnth
20658 /* Break vector into 32-bit words and do the population count
20659 * for each half word
20661 IRType ty
= Ity_I32
;
20662 IRTemp bits0_31
, bits32_63
, bits64_95
, bits96_127
;
20663 bits0_31
= bits32_63
= bits64_95
= bits96_127
= IRTemp_INVALID
;
20664 IRTemp cnt_bits0_31
, cnt_bits32_63
, cnt_bits64_95
, cnt_bits96_127
;
20665 cnt_bits0_31
= cnt_bits32_63
= cnt_bits64_95
= cnt_bits96_127
= IRTemp_INVALID
;
20667 DIP("vpopcnth v%d,v%d\n", vRT_addr
, vRB_addr
);
20668 breakV128to4x32(mkexpr( vB
), &bits96_127
, &bits64_95
, &bits32_63
, &bits0_31
);
20670 cnt_bits0_31
= gen_POPCOUNT(ty
, bits0_31
, HWORD
);
20671 cnt_bits32_63
= gen_POPCOUNT(ty
, bits32_63
, HWORD
);
20672 cnt_bits64_95
= gen_POPCOUNT(ty
, bits64_95
, HWORD
);
20673 cnt_bits96_127
= gen_POPCOUNT(ty
, bits96_127
, HWORD
);
20675 putVReg( vRT_addr
, mkV128from32(cnt_bits96_127
, cnt_bits64_95
,
20676 cnt_bits32_63
, cnt_bits0_31
) );
20680 case 0x783: // vpopcntw
20682 /* Break vector into 32-bit words and do the population count
20685 IRType ty
= Ity_I32
;
20686 IRTemp bits0_31
, bits32_63
, bits64_95
, bits96_127
;
20687 bits0_31
= bits32_63
= bits64_95
= bits96_127
= IRTemp_INVALID
;
20688 IRTemp cnt_bits0_31
, cnt_bits32_63
, cnt_bits64_95
, cnt_bits96_127
;
20689 cnt_bits0_31
= cnt_bits32_63
= cnt_bits64_95
= cnt_bits96_127
= IRTemp_INVALID
;
20691 DIP("vpopcntw v%d,v%d\n", vRT_addr
, vRB_addr
);
20692 breakV128to4x32(mkexpr( vB
), &bits96_127
, &bits64_95
, &bits32_63
, &bits0_31
);
20694 cnt_bits0_31
= gen_POPCOUNT(ty
, bits0_31
, WORD
);
20695 cnt_bits32_63
= gen_POPCOUNT(ty
, bits32_63
, WORD
);
20696 cnt_bits64_95
= gen_POPCOUNT(ty
, bits64_95
, WORD
);
20697 cnt_bits96_127
= gen_POPCOUNT(ty
, bits96_127
, WORD
);
20699 putVReg( vRT_addr
, mkV128from32(cnt_bits96_127
, cnt_bits64_95
,
20700 cnt_bits32_63
, cnt_bits0_31
) );
20704 case 0x7C3: // vpopcntd
20707 /* Break vector into 64-bit double words and do the population
20708 count on each double word.
20710 IRType ty
= Ity_I64
;
20711 IRTemp bits0_63
= newTemp(Ity_I64
);
20712 IRTemp bits64_127
= newTemp(Ity_I64
);
20713 IRTemp cnt_bits0_63
= newTemp(Ity_I64
);
20714 IRTemp cnt_bits64_127
= newTemp(Ity_I64
);
20716 DIP("vpopcntd v%d,v%d\n", vRT_addr
, vRB_addr
);
20718 assign(bits0_63
, unop( Iop_V128to64
, mkexpr( vB
) ) );
20719 assign(bits64_127
, unop( Iop_V128HIto64
, mkexpr( vB
) ) );
20720 cnt_bits0_63
= gen_POPCOUNT(ty
, bits0_63
, DWORD
);
20721 cnt_bits64_127
= gen_POPCOUNT(ty
, bits64_127
, DWORD
);
20723 putVReg( vRT_addr
, binop( Iop_64HLtoV128
,
20724 mkexpr( cnt_bits64_127
),
20725 mkexpr( cnt_bits0_63
) ) );
20727 /* Break vector into 32-bit words and do the population count
20728 on each 32-bit word.
20730 IRTemp bits0_31
, bits32_63
, bits64_95
, bits96_127
;
20731 bits0_31
= bits32_63
= bits64_95
= bits96_127
= IRTemp_INVALID
;
20732 IRTemp cnt_bits0_63
= newTemp(Ity_I64
);
20733 IRTemp cnt_bits64_127
= newTemp(Ity_I64
);
20735 DIP("vpopcntd v%d,v%d\n", vRT_addr
, vRB_addr
);
20736 breakV128to4x32(mkexpr( vB
), &bits96_127
, &bits64_95
,
20737 &bits32_63
, &bits0_31
);
20739 cnt_bits0_63
= gen_vpopcntd_mode32(bits0_31
, bits32_63
);
20740 cnt_bits64_127
= gen_vpopcntd_mode32(bits64_95
, bits96_127
);
20742 putVReg( vRT_addr
, binop( Iop_64HLtoV128
,
20743 mkexpr( cnt_bits64_127
),
20744 mkexpr( cnt_bits0_63
) ) );
20749 case 0x50C: // vgbbd Vector Gather Bits by Bytes by Doubleword
20750 DIP("vgbbd v%d,v%d\n", vRT_addr
, vRB_addr
);
20751 putVReg( vRT_addr
, unop( Iop_PwBitMtxXpose64x2
, mkexpr( vB
) ) );
20754 case 0x5CC: // vbpermd Vector Bit Permute Doubleword
20756 UChar vRA_addr
= ifieldRegA( theInstr
);
20757 IRTemp vA
= newTemp( Ity_V128
);
20759 IRTemp index_dword_hi
[8]; // index in double word
20760 IRTemp index_dword_lo
[8];
20761 IRTemp index_dword_hi_valid
[8];
20762 IRTemp index_dword_lo_valid
[8];
20763 IRTemp pb_dword_hi
[8]; // permute bit
20764 IRTemp pb_dword_lo
[8];
20768 DIP("vbpermd v%d,v%d,v%d\n", vRT_addr
, vRA_addr
, vRB_addr
);
20770 tmp_hi
[0] = newTemp( Ity_I64
);
20771 tmp_lo
[0] = newTemp( Ity_I64
);
20773 assign( vA
, getVReg(vRA_addr
) );
20774 assign( tmp_hi
[0], mkU64( 0 ) );
20775 assign( tmp_lo
[0], mkU64( 0 ) );
20777 for (j
=0; j
<8; j
++) {
20778 index_dword_hi
[j
] = newTemp( Ity_I64
);
20779 index_dword_lo
[j
] = newTemp( Ity_I64
);
20780 index_dword_hi_valid
[j
] = newTemp( Ity_I64
);
20781 index_dword_lo_valid
[j
] = newTemp( Ity_I64
);
20782 pb_dword_hi
[j
] = newTemp( Ity_I64
);
20783 pb_dword_lo
[j
] = newTemp( Ity_I64
);
20784 tmp_hi
[j
+1] = newTemp( Ity_I64
);
20785 tmp_lo
[j
+1] = newTemp( Ity_I64
);
20787 assign( index_dword_hi
[j
],
20790 unop( Iop_V128HIto64
,
20792 mkU8( ( 7 - j
) * 8 ) ),
20795 assign( index_dword_lo
[j
],
20798 unop( Iop_V128to64
,
20800 mkU8( ( 7 - j
) * 8 ) ),
20803 assign( index_dword_hi_valid
[j
],
20805 binop( Iop_CmpLT64U
,
20806 mkexpr( index_dword_hi
[j
] ),
20809 assign( index_dword_lo_valid
[j
],
20811 binop( Iop_CmpLT64U
,
20812 mkexpr( index_dword_lo
[j
] ),
20814 assign( pb_dword_hi
[j
],
20817 unop( Iop_V128HIto64
,
20822 mkexpr( index_dword_hi
[j
] )
20826 assign( pb_dword_lo
[j
],
20829 unop( Iop_V128to64
,
20834 mkexpr( index_dword_lo
[j
] )
20838 assign( tmp_hi
[j
+1],
20841 mkexpr( index_dword_hi_valid
[j
] ),
20843 mkexpr( pb_dword_hi
[j
] ),
20845 mkexpr( tmp_hi
[j
] ) ) );
20847 assign( tmp_lo
[j
+1],
20850 mkexpr( index_dword_lo_valid
[j
] ),
20852 mkexpr( pb_dword_lo
[j
] ),
20854 mkexpr( tmp_lo
[j
] ) ) );
20858 binop( Iop_64HLtoV128
,
20859 mkexpr( tmp_hi
[8] ),
20860 mkexpr( tmp_lo
[8] ) ) );
20865 vex_printf("dis_av_count_bitTranspose(ppc)(opc2)\n");
20873 * Scalar / Vector Population Count/bit matrix transpose
20875 static Bool
dis_logical_mask_bits ( UInt prefix
, UInt theInstr
,
20876 const VexAbiInfo
* vbi
)
20878 UChar opc1
= ifieldOPC(theInstr
);
20879 UInt opc2
= ifieldOPClo10(theInstr
);
20880 UChar rS_addr
= ifieldRegDS(theInstr
);
20881 UChar rA_addr
= ifieldRegA(theInstr
);
20882 UChar rB_addr
= ifieldRegB(theInstr
);
20884 IRTemp rS
= newTemp( Ity_I64
);
20885 IRTemp rA
= newTemp( Ity_I64
);
20886 IRTemp rB
= newTemp( Ity_I64
);
20888 /* There are no prefixed version of these instructions. */
20889 vassert( !prefix_instruction( prefix
) );
20891 assign( rS
, getIReg(rS_addr
) );
20892 assign( rB
, getIReg(rB_addr
) );
20894 if (opc1
!= 0x1F) {
20895 vex_printf( "dis_logical_mask_bits(ppc)(instr)\n" );
20901 /* X-form instructions */
20902 case 0x03B: // cntlzdm, Count Leading Zeros Doubleword Under bitmask
20903 case 0x0BC: // pextd, Parallel Bits Extract Doubleword
20904 case 0x0DC: // cfuged, Centrifuge Doubleword
20905 case 0x23B: // cnttzdm, Count Trailing Zeros Doubleword Under bit mask
20907 UInt max_bits
= mode64
? 64 : 32;
20908 IRTemp ones
= newTemp( Ity_I64
);
20909 IRTemp all_ones
= newTemp( Ity_I64
);
20911 /* Get the bits corresponding to 1's in the mask */
20912 assign( ones
, extract_bits_under_mask ( vbi
,
20917 if ( opc2
== 0x03b ) { // cntlzdm
20918 IRTemp cnt
= newTemp( Ity_I64
);
20920 DIP("cntlzdm r%u,r%u,r%u\n", rA_addr
, rS_addr
, rB_addr
);
20921 assign( cnt
, popcnt64( vbi
, mkexpr( rB
) ) );
20923 assign( all_ones
, binop( Iop_Shr64
,
20924 mkU64( 0xFFFFFFFFFFFFFFFF ),
20925 unop( Iop_64to8
, mkexpr( cnt
) ) ) );
20928 unop( Iop_ClzNat64
,
20935 mkexpr( cnt
) ) ) ),
20936 mkexpr( all_ones
) ) ) );
20938 } else if ( opc2
== 0x0BC ) { // pextd
20939 DIP("pextd r%u,r%u,r%u\n", rA_addr
, rS_addr
, rB_addr
);
20940 assign( rA
, mkexpr( ones
) );
20942 } else if ( opc2
== 0x0DC ) { // cfuged
20943 IRTemp zeros
= newTemp( Ity_I64
);
20944 IRTemp cnt
= newTemp( Ity_I64
);
20946 DIP("cfuged r%u,r%u,r%u\n", rA_addr
, rS_addr
, rB_addr
);
20947 assign( cnt
, popcnt64( vbi
, mkexpr( rB
) ) );
20949 /* Get the bits corresponding to 0's in the mask */
20950 assign( zeros
, extract_bits_under_mask ( vbi
,
20961 mkexpr( ones
) ) );
20963 } else if ( opc2
== 0x23B ) { //cnttzdm
20964 DIP("cnttzdm r%u,r%u,r%u\n", rA_addr
, rS_addr
, rB_addr
);
20965 assign( all_ones
, binop( Iop_Shl64
,
20966 mkU64( 0xFFFFFFFFFFFFFFFF ),
20969 mkexpr( rB
) ) ) ) );
20972 unop( Iop_CtzNat64
,
20974 mkexpr( all_ones
), mkexpr( ones
) ) ) );
20977 DIP("pexld r%u,r%u,r%u\n", rA_addr
, rS_addr
, rB_addr
);
20978 assign( rA
, mkexpr( ones
) );
20983 case 0x09C: // pdepd, Parallel Bits Deposit Doubleword X-form
20985 IRTemp ones
= newTemp( Ity_I64
);
20987 DIP("pdepd r%u,r%u,r%u\n", rA_addr
, rS_addr
, rB_addr
);
20988 assign( ones
, deposit_bits_under_mask ( vbi
, mkexpr( rS
),
20990 assign( rA
, mkexpr( ones
) );
20995 vex_printf("dis_logical_mask_bits)(ppc)\n");
20999 putIReg( rA_addr
, mkexpr( rA
) );
21004 dis_vector_logical_mask_bits ( UInt prefix
, UInt theInstr
, UInt opc2
,
21005 const VexAbiInfo
* vbi
)
21007 UChar vRA_addr
= ifieldRegA(theInstr
);
21008 UChar vRB_addr
= ifieldRegB(theInstr
);
21009 UChar vRT_addr
= ifieldRegDS(theInstr
);
21010 UChar opc1
= ifieldOPC( theInstr
);
21011 IRTemp vA
= newTemp(Ity_V128
);
21012 IRTemp vB
= newTemp(Ity_V128
);
21014 /* There are no prefixed version of these instructions. */
21015 vassert( !prefix_instruction( prefix
) );
21018 vex_printf( "dis_vector_logical_mask_bits(ppc)(instr)\n" );
21022 assign( vA
, getVReg(vRA_addr
));
21023 assign( vB
, getVReg(vRB_addr
));
21026 case 0x4CC: // vgnb, Vector Gather every Nth Bit VX-form
21028 IRTemp vB_hi
= newTemp( Ity_I64
);
21029 IRTemp vB_lo
= newTemp( Ity_I64
);
21030 IRTemp ones_hi
, ones_lo
;
21031 UChar N
= toUChar( IFIELD( theInstr
, 16, 3 ) );
21032 ULong extract_mask_hi
, extract_mask_lo
, byte_mask
;
21033 UInt i
, num_bits_hi
, num_bits_lo
;
21035 /* Note, the return register number is actually for a GPR not a
21036 vector register. */
21037 DIP("vgnb %u,v%u,%u\n", vRT_addr
, vRB_addr
, N
);
21039 if ((N
< 2) || (N
>7)) {
21040 /* The value of N can be any value between 2 and 7, inclusive. */
21041 vex_printf("\nERROR: vgnb RT,VRB,N; N is out of range.\n\n");
21045 /* Create 32-bit extract mask, starting with bit 0 (IBM numbering),
21046 every Nth bit going right will be a 1. */
21047 extract_mask_hi
= 0;
21048 extract_mask_lo
= 0;
21055 extract_mask_hi
= extract_mask_hi
| (byte_mask
<< (63 - i
));
21062 extract_mask_lo
= extract_mask_lo
| (byte_mask
<< (127 - i
));
21067 ones_hi
= newTemp( Ity_I64
);
21068 ones_lo
= newTemp( Ity_I64
);
21070 assign( vB_hi
, unop( Iop_V128HIto64
, mkexpr( vB
) ) );
21071 assign( vB_lo
, unop( Iop_V128to64
, mkexpr( vB
) ) );
21073 assign( ones_hi
, extract_bits_under_mask ( vbi
, mkexpr( vB_hi
),
21074 mkU64( extract_mask_hi
),
21076 assign( ones_lo
, extract_bits_under_mask ( vbi
, mkexpr( vB_lo
),
21077 mkU64( extract_mask_lo
),
21080 /* Concatenate the extracted bits from ones_hi and ones_lo and
21081 store in GPR. Make sure the hi and low bits are left aligned per
21083 putIReg( vRT_addr
, binop( Iop_Or64
,
21086 mkU8( 64 - num_bits_hi
) ),
21089 mkU8( 64 - num_bits_hi
21090 - num_bits_lo
) ) ) );
21094 case 0x54D: // vcfuged, Centrifuge Doubleword VX-form
21096 IRTemp vA_hi
= newTemp( Ity_I64
);
21097 IRTemp vA_lo
= newTemp( Ity_I64
);
21098 IRTemp vB_hi
= newTemp( Ity_I64
);
21099 IRTemp vB_lo
= newTemp( Ity_I64
);
21104 DIP("vcfuged v%u,v%u,v%u\n", vRT_addr
, vRA_addr
, vRB_addr
);
21106 zeros
[0] = newTemp( Ity_I64
);
21107 zeros
[1] = newTemp( Ity_I64
);
21108 ones
[0] = newTemp( Ity_I64
);
21109 ones
[1] = newTemp( Ity_I64
);
21110 count
[0] = newTemp( Ity_I64
);
21111 count
[1] = newTemp( Ity_I64
);
21113 assign( vA_hi
, unop( Iop_V128HIto64
, mkexpr( vA
) ) );
21114 assign( vB_hi
, unop( Iop_V128HIto64
, mkexpr( vB
) ) );
21115 assign( vA_lo
, unop( Iop_V128to64
, mkexpr( vA
) ) );
21116 assign( vB_lo
, unop( Iop_V128to64
, mkexpr( vB
) ) );
21118 assign( count
[0], popcnt64( vbi
, mkexpr( vB_hi
) ) );
21119 assign( count
[1], popcnt64( vbi
, mkexpr( vB_lo
) ) );
21121 assign( ones
[0], extract_bits_under_mask ( vbi
, mkexpr( vA_hi
),
21124 assign( ones
[1], extract_bits_under_mask ( vbi
, mkexpr( vA_lo
),
21127 assign( zeros
[0], extract_bits_under_mask ( vbi
, mkexpr( vA_hi
),
21130 assign( zeros
[1], extract_bits_under_mask ( vbi
, mkexpr( vA_lo
),
21134 /* Put the bits corresponding to zero mask bits to the left of the
21135 bits corresponding to one mask bits for the upper and lower 64-bit
21137 putVReg( vRT_addr
, binop( Iop_64HLtoV128
,
21140 mkexpr( zeros
[0] ),
21142 mkexpr( count
[0] ) ) ),
21143 mkexpr( ones
[0] ) ),
21146 mkexpr( zeros
[1] ),
21148 mkexpr( count
[1] ) ) ),
21149 mkexpr( ones
[1] ) ) ) );
21153 case 0x58D: // vpextd, Vector Parallel Bits Extract Doubleword VX-form
21155 IRTemp vA_hi
= newTemp( Ity_I64
);
21156 IRTemp vA_lo
= newTemp( Ity_I64
);
21157 IRTemp vB_hi
= newTemp( Ity_I64
);
21158 IRTemp vB_lo
= newTemp( Ity_I64
);
21161 DIP("vpextd v%u,v%u,v%u\n", vRT_addr
, vRA_addr
, vRB_addr
);
21163 ones
[0] = newTemp( Ity_I64
);
21164 ones
[1] = newTemp( Ity_I64
);
21166 assign( vA_hi
, unop( Iop_V128HIto64
, mkexpr( vA
) ) );
21167 assign( vB_hi
, unop( Iop_V128HIto64
, mkexpr( vB
) ) );
21168 assign( vA_lo
, unop( Iop_V128to64
, mkexpr( vA
) ) );
21169 assign( vB_lo
, unop( Iop_V128to64
, mkexpr( vB
) ) );
21171 assign( ones
[0], extract_bits_under_mask ( vbi
, mkexpr( vA_hi
),
21174 assign( ones
[1], extract_bits_under_mask ( vbi
, mkexpr( vA_lo
),
21177 putVReg( vRT_addr
, binop( Iop_64HLtoV128
,
21178 mkexpr( ones
[0] ), mkexpr( ones
[1] ) ) );
21182 case 0x5CD: // vpdepd, Vector Parallel Bits Deposit Doubleword VX-form
21184 IRTemp vA_hi
= newTemp( Ity_I64
);
21185 IRTemp vA_lo
= newTemp( Ity_I64
);
21186 IRTemp vB_hi
= newTemp( Ity_I64
);
21187 IRTemp vB_lo
= newTemp( Ity_I64
);
21190 DIP("vpdepd v%u,v%u,v%u\n", vRT_addr
, vRA_addr
, vRB_addr
);
21192 ones
[0] = newTemp( Ity_I64
);
21193 ones
[1] = newTemp( Ity_I64
);
21195 assign( vA_hi
, unop( Iop_V128HIto64
, mkexpr( vA
) ) );
21196 assign( vB_hi
, unop( Iop_V128HIto64
, mkexpr( vB
) ) );
21197 assign( vA_lo
, unop( Iop_V128to64
, mkexpr( vA
) ) );
21198 assign( vB_lo
, unop( Iop_V128to64
, mkexpr( vB
) ) );
21200 assign( ones
[0], deposit_bits_under_mask ( vbi
, mkexpr( vA_hi
),
21201 mkexpr( vB_hi
) ) );
21202 assign( ones
[1], deposit_bits_under_mask ( vbi
, mkexpr( vA_lo
),
21203 mkexpr( vB_lo
) ) );
21204 putVReg( vRT_addr
, binop( Iop_64HLtoV128
,
21205 mkexpr( ones
[0] ), mkexpr( ones
[1] ) ) );
21209 case 0x784: // vclzdm,
21211 /* Vector Count Leading Zeros Doubleword under bit mask */
21213 IRTemp extracted_bits
[2];
21216 IRTemp cnt_extract_bits
[2];
21217 UInt max_bits
= 64;
21218 IRTemp vA_hi
= newTemp( Ity_I64
);
21219 IRTemp vA_lo
= newTemp( Ity_I64
);
21220 IRTemp vB_hi
= newTemp( Ity_I64
);
21221 IRTemp vB_lo
= newTemp( Ity_I64
);
21223 DIP("vclzdm v%u,v%u,v%u\n", vRT_addr
, vRA_addr
, vRB_addr
);
21225 ones
[0] = newTemp( Ity_I64
);
21226 ones
[1] = newTemp( Ity_I64
);
21227 clz
[0] = newTemp( Ity_I64
);
21228 clz
[1] = newTemp( Ity_I64
);
21229 extracted_bits
[0] = newTemp( Ity_I64
);
21230 extracted_bits
[1] = newTemp( Ity_I64
);
21231 cnt_extract_bits
[0] = newTemp( Ity_I8
);
21232 cnt_extract_bits
[1] = newTemp( Ity_I8
);
21234 /* Gather bits in each vector element, then count leading zeros. */
21235 assign( vA_hi
, unop( Iop_V128HIto64
, mkexpr( vA
) ) );
21236 assign( vB_hi
, unop( Iop_V128HIto64
, mkexpr( vB
) ) );
21237 assign( vA_lo
, unop( Iop_V128to64
, mkexpr( vA
) ) );
21238 assign( vB_lo
, unop( Iop_V128to64
, mkexpr( vB
) ) );
21240 assign( ones
[0], extract_bits_under_mask ( vbi
,
21245 assign( ones
[1], extract_bits_under_mask ( vbi
,
21250 assign( cnt_extract_bits
[0],
21253 count_bits_under_mask ( vbi
,
21256 mkU64( 1 ) ) ) ) );
21258 assign( cnt_extract_bits
[1],
21261 count_bits_under_mask ( vbi
,
21264 mkU64( 1 ) ) ) ) );
21266 /* Shift extracted bits to High order bits, filling lower order bits
21267 with 1's so we only count zeros in extracted bits. */
21268 assign( extracted_bits
[0],
21271 mkU64( 0xFFFFFFFFFFFFFFFF ),
21272 mkexpr( cnt_extract_bits
[0] ) ),
21277 mkexpr( cnt_extract_bits
[0] )
21282 mkexpr( extracted_bits
[0] ) ) );
21284 assign( extracted_bits
[1],
21287 mkU64( 0xFFFFFFFFFFFFFFFF ),
21288 mkexpr( cnt_extract_bits
[1] ) ),
21293 mkexpr( cnt_extract_bits
[1] )
21297 mkexpr( extracted_bits
[1] ) ) );
21299 putVReg( vRT_addr
, binop( Iop_64HLtoV128
,
21300 mkexpr( clz
[0] ), mkexpr( clz
[1] ) ) );
21304 case 0x7C4: // vctzdm
21306 /* Vector Count Trailing Zeros Doubleword under bit mask */
21309 IRTemp all_ones_hi
= newTemp( Ity_I64
);
21310 IRTemp all_ones_lo
= newTemp( Ity_I64
);
21311 IRTemp vA_hi
= newTemp( Ity_I64
);
21312 IRTemp vA_lo
= newTemp( Ity_I64
);
21313 IRTemp vB_hi
= newTemp( Ity_I64
);
21314 IRTemp vB_lo
= newTemp( Ity_I64
);
21316 DIP("vctzdm v%u,v%u,v%u\n", vRT_addr
, vRA_addr
, vRB_addr
);
21318 ones
[0] = newTemp( Ity_I64
);
21319 ones
[1] = newTemp( Ity_I64
);
21320 ctz
[0] = newTemp( Ity_I64
);
21321 ctz
[1] = newTemp( Ity_I64
);
21323 /* Gather bits in each vector element, then count trailing zeros. */
21324 assign( vA_hi
, unop( Iop_V128HIto64
, mkexpr( vA
) ) );
21325 assign( vB_hi
, unop( Iop_V128HIto64
, mkexpr( vB
) ) );
21326 assign( vA_lo
, unop( Iop_V128to64
, mkexpr( vA
) ) );
21327 assign( vB_lo
, unop( Iop_V128to64
, mkexpr( vB
) ) );
21329 /* Shift all 1's value left by the count of the number of bits in the
21330 mask. OR this with the extracted bits so the trailing zero count
21331 will only count zeros in extracted field. */
21332 assign( all_ones_hi
,
21334 mkU64( 0xFFFFFFFFFFFFFFFF ),
21336 popcnt64( vbi
, mkexpr( vB_hi
) ) ) ) );
21337 assign( all_ones_lo
,
21339 mkU64( 0xFFFFFFFFFFFFFFFF ),
21341 popcnt64( vbi
, mkexpr( vB_lo
) ) ) ) );
21345 mkexpr( all_ones_hi
),
21346 extract_bits_under_mask ( vbi
,
21353 mkexpr( all_ones_lo
),
21354 extract_bits_under_mask ( vbi
,
21359 assign( ctz
[0], unop( Iop_CtzNat64
, mkexpr( ones
[0] ) ) );
21360 assign( ctz
[1], unop( Iop_CtzNat64
, mkexpr( ones
[1] ) ) );
21362 putVReg( vRT_addr
, binop( Iop_64HLtoV128
,
21363 mkexpr( ctz
[0] ), mkexpr( ctz
[1] ) ) );
21368 vex_printf("dis_vector_logical_mask_bits(ppc)(opc2)\n");
21383 This helper function takes as input the IRExpr returned
21384 from a binop( Iop_CmpF64, fpA, fpB), whose result is returned
21385 in IR form. This helper function converts it to PPC form.
21387 Map compare result from IR to PPC
21389 FP cmp result | PPC | IR
21390 --------------------------
21396 condcode = Shl(1, (~(ccIR>>5) & 2)
21397 | ((ccIR ^ (ccIR>>6)) & 1)
21400 get_fp_cmp_CR_val (IRExpr
* ccIR_expr
)
21402 IRTemp condcode
= newTemp( Ity_I32
);
21403 IRTemp ccIR
= newTemp( Ity_I32
);
21405 assign(ccIR
, ccIR_expr
);
21423 mkU32( 1 ) ) ) ) ) );
21428 * Helper function for get_max_min_fp for ascertaining the max or min between two doubles
21429 * following these special rules:
21430 * - The max/min of a QNaN and any value is that value
21431 * (When two QNaNs are being compared, the frA QNaN is the return value.)
21432 * - The max/min of any value and an SNaN is that SNaN converted to a QNaN
21433 * (When two SNaNs are being compared, the frA SNaN is converted to a QNaN.)
21435 static IRExpr
* _get_maxmin_fp_NaN(IRTemp frA_I64
, IRTemp frB_I64
)
21437 IRTemp frA_isNaN
= newTemp(Ity_I1
);
21438 IRTemp frB_isNaN
= newTemp(Ity_I1
);
21439 IRTemp frA_isSNaN
= newTemp(Ity_I1
);
21440 IRTemp frB_isSNaN
= newTemp(Ity_I1
);
21441 IRTemp frA_isQNaN
= newTemp(Ity_I1
);
21442 IRTemp frB_isQNaN
= newTemp(Ity_I1
);
21444 assign( frA_isNaN
, is_NaN( Ity_I64
, frA_I64
) );
21445 assign( frB_isNaN
, is_NaN( Ity_I64
, frB_I64
) );
21446 // If operand is a NAN and bit 12 is '0', then it's an SNaN
21447 assign( frA_isSNaN
,
21448 mkAND1( mkexpr(frA_isNaN
),
21449 binop( Iop_CmpEQ32
,
21451 unop( Iop_64HIto32
, mkexpr( frA_I64
) ),
21452 mkU32( 0x00080000 ) ),
21454 assign( frB_isSNaN
,
21455 mkAND1( mkexpr(frB_isNaN
),
21456 binop( Iop_CmpEQ32
,
21458 unop( Iop_64HIto32
, mkexpr( frB_I64
) ),
21459 mkU32( 0x00080000 ) ),
21461 assign( frA_isQNaN
,
21462 mkAND1( mkexpr( frA_isNaN
), unop( Iop_Not1
, mkexpr( frA_isSNaN
) ) ) );
21463 assign( frB_isQNaN
,
21464 mkAND1( mkexpr( frB_isNaN
), unop( Iop_Not1
, mkexpr( frB_isSNaN
) ) ) );
21466 /* Based on the rules specified in the function prologue, the algorithm is as follows:
21467 * <<<<<<<<<>>>>>>>>>>>>>>>>>>
21469 * result = frA converted to QNaN
21470 * else if frB is a SNaN
21474 * result = frB converted to QNaN
21475 * else if frB is a QNaN
21477 * // One of frA or frB was a NaN in order for this function to be called, so
21478 * // if we get to this point, we KNOW that frA must be a QNaN.
21479 * else // frA is a QNaN
21481 * <<<<<<<<<>>>>>>>>>>>>>>>>>>
21484 #define SNAN_MASK 0x0008000000000000ULL
21487 IRExpr_ITE(mkexpr(frA_isSNaN
),
21488 /* then: result = frA converted to QNaN */
21489 binop(Iop_Or64
, mkexpr(frA_I64
), mkU64(SNAN_MASK
)),
21490 /* else: if frB is a SNaN */
21491 IRExpr_ITE(mkexpr(frB_isSNaN
),
21492 IRExpr_ITE(mkexpr(frA_isQNaN
),
21493 /* then: result = frA */
21495 /* else: result = frB converted to QNaN */
21496 binop(Iop_Or64
, mkexpr(frB_I64
),
21497 mkU64(SNAN_MASK
))),
21498 /* else: if frB is a QNaN */
21499 IRExpr_ITE(mkexpr(frB_isQNaN
),
21500 /* then: result = frA */
21502 /* else: frA is a QNaN, so result = frB */
21503 mkexpr(frB_I64
))));
21507 * Helper function for get_max_min_fp.
21509 static IRExpr
* _get_maxmin_fp_cmp(IRTemp src1
, IRTemp src2
, Bool isMin
)
21511 IRTemp src1cmpsrc2
= get_fp_cmp_CR_val( binop( Iop_CmpF64
,
21512 unop( Iop_ReinterpI64asF64
,
21514 unop( Iop_ReinterpI64asF64
,
21515 mkexpr( src2
) ) ) );
21517 return IRExpr_ITE( binop( Iop_CmpEQ32
,
21518 mkexpr( src1cmpsrc2
),
21519 mkU32( isMin
? PPC_CMP_LT
: PPC_CMP_GT
) ),
21520 /* then: use src1 */
21522 /* else: use src2 */
21527 * Helper function for "Maximum/Minimum Double Precision" operations.
21528 * Arguments: frA and frb are Ity_I64
21529 * Returns Ity_I64 IRExpr that answers the "which is Maxiumum/Minimum" question
21531 static IRExpr
* get_max_min_fp(IRTemp frA_I64
, IRTemp frB_I64
, Bool isMin
)
21533 /* There are three special cases where get_fp_cmp_CR_val is not helpful
21534 * for ascertaining the maximum between two doubles:
21535 * 1. The max/min of +0 and -0 is +0.
21536 * 2. The max/min of a QNaN and any value is that value.
21537 * 3. The max/min of any value and an SNaN is that SNaN converted to a QNaN.
21538 * We perform the check for [+/-]0 here in this function and use the
21539 * _get_maxmin_fp_NaN helper for the two NaN cases; otherwise we call _get_maxmin_fp_cmp
21540 * to do the standard comparison function.
21542 IRTemp anyNaN
= newTemp(Ity_I1
);
21543 IRTemp frA_isZero
= newTemp(Ity_I1
);
21544 IRTemp frB_isZero
= newTemp(Ity_I1
);
21545 assign( frA_isZero
, is_Zero( Ity_I64
, frA_I64
) );
21546 assign( frB_isZero
, is_Zero( Ity_I64
, frB_I64
) );
21547 assign( anyNaN
, mkOR1( is_NaN( Ity_I64
, frA_I64
),
21548 is_NaN(Ity_I64
, frB_I64
) ) );
21549 #define MINUS_ZERO 0x8000000000000000ULL
21551 return IRExpr_ITE( /* If both arguments are zero . . . */
21552 mkAND1( mkexpr( frA_isZero
), mkexpr( frB_isZero
) ),
21553 /* then: if frA is -0 and isMin==True, return -0;
21554 * else if frA is +0 and isMin==False; return +0;
21555 * otherwise, simply return frB. */
21556 IRExpr_ITE( binop( Iop_CmpEQ32
,
21557 unop( Iop_64HIto32
,
21558 mkexpr( frA_I64
) ),
21559 mkU32( isMin
? 0x80000000 : 0 ) ),
21560 mkU64( isMin
? MINUS_ZERO
: 0ULL ),
21561 mkexpr( frB_I64
) ),
21562 /* else: check if either input is a NaN*/
21563 IRExpr_ITE( mkexpr( anyNaN
),
21564 /* then: use "NaN helper" */
21565 _get_maxmin_fp_NaN( frA_I64
, frB_I64
),
21566 /* else: use "comparison helper" */
21567 _get_maxmin_fp_cmp( frB_I64
, frA_I64
, isMin
) ));
21570 static const HChar
* _get_vsx_rdpi_suffix(UInt opc2
)
21572 switch (opc2
& 0x7F) {
21584 default: // Impossible to get here
21585 vex_printf("Unrecognized opcode %x\n", opc2
);
21586 vpanic("_get_vsx_rdpi_suffix(ppc)(opc2)");
21591 * Helper function for vector/scalar double precision fp round to integer instructions.
21593 static IRExpr
* _do_vsx_fp_roundToInt(IRTemp frB_I64
, UInt opc2
)
21596 /* The same rules apply for x{s|v}rdpi{m|p|c|z} as for floating point round operations (fri{m|n|p|z}). */
21597 IRTemp frB
= newTemp(Ity_F64
);
21598 IRTemp frD
= newTemp(Ity_F64
);
21599 IRTemp intermediateResult
= newTemp(Ity_I64
);
21600 IRTemp is_SNAN
= newTemp(Ity_I1
);
21603 switch (opc2
& 0x7F) {
21605 rxpi_rm
= mkU32(Irrm_NegINF
);
21608 rxpi_rm
= mkU32(Irrm_PosINF
);
21611 rxpi_rm
= get_IR_roundingmode();
21614 rxpi_rm
= mkU32(Irrm_ZERO
);
21617 rxpi_rm
= mkU32(Irrm_NEAREST
);
21620 default: // Impossible to get here
21621 vex_printf("Unrecognized opcode %x\n", opc2
);
21622 vpanic("_do_vsx_fp_roundToInt(ppc)(opc2)");
21624 assign(frB
, unop(Iop_ReinterpI64asF64
, mkexpr(frB_I64
)));
21625 assign( intermediateResult
,
21626 binop( Iop_F64toI64S
, rxpi_rm
,
21629 /* don't use the rounded integer if frB is outside -9e18..9e18 */
21630 /* F64 has only log10(2**52) significant digits anyway */
21631 /* need to preserve sign of zero */
21632 /* frD = (fabs(frB) > 9e18) ? frB :
21633 (sign(frB)) ? -fabs((double)intermediateResult) : (double)intermediateResult */
21639 IRExpr_Const( IRConst_F64( 9e18
) ),
21640 unop( Iop_AbsF64
, mkexpr( frB
) ) ) ),
21644 binop( Iop_CmpNE32
,
21646 unop( Iop_64HIto32
,
21647 mkexpr( frB_I64
) ),
21652 binop( Iop_I64StoF64
,
21654 mkexpr( intermediateResult
) ) ) ),
21655 binop( Iop_I64StoF64
,
21657 mkexpr( intermediateResult
) )
21662 /* See Appendix "Floating-Point Round to Integer Model" in ISA doc.
21663 * If frB is a SNAN, then frD <- frB, with bit 12 set to '1'.
21665 #define SNAN_MASK 0x0008000000000000ULL
21666 hi32
= unop( Iop_64HIto32
, mkexpr(frB_I64
) );
21668 mkAND1( is_NaN( Ity_I64
, frB_I64
),
21669 binop( Iop_CmpEQ32
,
21670 binop( Iop_And32
, hi32
, mkU32( 0x00080000 ) ),
21673 return IRExpr_ITE( mkexpr( is_SNAN
),
21674 unop( Iop_ReinterpI64asF64
,
21676 mkU64( SNAN_MASK
),
21677 mkexpr( frB_I64
) ) ),
21682 * Miscellaneous VSX vector instructions
21685 dis_vxv_misc ( UInt prefix
, UInt theInstr
, UInt opc2
)
21688 UChar opc1
= ifieldOPC( theInstr
);
21689 UChar XT
= ifieldRegXT( theInstr
);
21690 UChar XB
= ifieldRegXB( theInstr
);
21692 /* There is no prefixed version of these instructions. */
21695 if (opc1
!= 0x3C) {
21696 vex_printf( "dis_vxv_misc(ppc)(instr)\n" );
21701 case 0x1B4: // xvredp (VSX Vector Reciprocal Estimate Double-Precision)
21702 case 0x194: // xvrsqrtedp (VSX Vector Reciprocal Square Root Estimate
21703 // Double-Precision)
21705 IRExpr
* ieee_one
= IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL
));
21706 IRExpr
* rm
= get_IR_roundingmode();
21707 IRTemp frB
= newTemp(Ity_I64
);
21708 IRTemp frB2
= newTemp(Ity_I64
);
21709 Bool redp
= opc2
== 0x1B4;
21710 IRTemp sqrtHi
= newTemp(Ity_F64
);
21711 IRTemp sqrtLo
= newTemp(Ity_F64
);
21712 assign(frB
, unop(Iop_V128HIto64
, getVSReg( XB
)));
21713 assign(frB2
, unop(Iop_V128to64
, getVSReg( XB
)));
21715 DIP("%s v%d,v%d\n", redp
? "xvredp" : "xvrsqrtedp", XT
, XB
);
21719 binop( Iop_SqrtF64
,
21721 unop( Iop_ReinterpI64asF64
, mkexpr( frB
) ) ) );
21723 binop( Iop_SqrtF64
,
21725 unop( Iop_ReinterpI64asF64
, mkexpr( frB2
) ) ) );
21728 binop( Iop_64HLtoV128
,
21729 unop( Iop_ReinterpF64asI64
,
21733 redp
? unop( Iop_ReinterpI64asF64
,
21735 : mkexpr( sqrtHi
) ) ),
21736 unop( Iop_ReinterpF64asI64
,
21740 redp
? unop( Iop_ReinterpI64asF64
,
21742 : mkexpr( sqrtLo
) ) ) ) );
21746 case 0x134: // xvresp (VSX Vector Reciprocal Estimate Single-Precision)
21747 case 0x114: // xvrsqrtesp (VSX Vector Reciprocal Square Root Estimate Single-Precision)
21749 IRTemp b3
, b2
, b1
, b0
;
21750 IRTemp res0
= newTemp(Ity_I32
);
21751 IRTemp res1
= newTemp(Ity_I32
);
21752 IRTemp res2
= newTemp(Ity_I32
);
21753 IRTemp res3
= newTemp(Ity_I32
);
21754 IRTemp sqrt3
= newTemp(Ity_F64
);
21755 IRTemp sqrt2
= newTemp(Ity_F64
);
21756 IRTemp sqrt1
= newTemp(Ity_F64
);
21757 IRTemp sqrt0
= newTemp(Ity_F64
);
21758 IRExpr
* rm
= get_IR_roundingmode();
21759 Bool resp
= opc2
== 0x134;
21761 IRExpr
* ieee_one
= IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL
));
21763 b3
= b2
= b1
= b0
= IRTemp_INVALID
;
21764 DIP("%s v%d,v%d\n", resp
? "xvresp" : "xvrsqrtesp", XT
, XB
);
21765 breakV128to4xF64( getVSReg( XB
), &b3
, &b2
, &b1
, &b0
);
21768 assign( sqrt3
, binop( Iop_SqrtF64
, rm
, mkexpr( b3
) ) );
21769 assign( sqrt2
, binop( Iop_SqrtF64
, rm
, mkexpr( b2
) ) );
21770 assign( sqrt1
, binop( Iop_SqrtF64
, rm
, mkexpr( b1
) ) );
21771 assign( sqrt0
, binop( Iop_SqrtF64
, rm
, mkexpr( b0
) ) );
21775 unop( Iop_ReinterpF32asI32
,
21776 unop( Iop_TruncF64asF32
,
21777 triop( Iop_DivF64r32
,
21780 resp
? mkexpr( b0
) : mkexpr( sqrt0
) ) ) ) );
21782 unop( Iop_ReinterpF32asI32
,
21783 unop( Iop_TruncF64asF32
,
21784 triop( Iop_DivF64r32
,
21787 resp
? mkexpr( b1
) : mkexpr( sqrt1
) ) ) ) );
21789 unop( Iop_ReinterpF32asI32
,
21790 unop( Iop_TruncF64asF32
,
21791 triop( Iop_DivF64r32
,
21794 resp
? mkexpr( b2
) : mkexpr( sqrt2
) ) ) ) );
21796 unop( Iop_ReinterpF32asI32
,
21797 unop( Iop_TruncF64asF32
,
21798 triop( Iop_DivF64r32
,
21801 resp
? mkexpr( b3
) : mkexpr( sqrt3
) ) ) ) );
21803 binop( Iop_64HLtoV128
,
21804 binop( Iop_32HLto64
, mkexpr( res3
), mkexpr( res2
) ),
21805 binop( Iop_32HLto64
, mkexpr( res1
), mkexpr( res0
) ) ) );
21808 case 0x300: // xvmaxsp (VSX Vector Maximum Single-Precision)
21809 case 0x320: // xvminsp (VSX Vector Minimum Single-Precision)
21811 UChar XA
= ifieldRegXA( theInstr
);
21812 IRTemp a3
, a2
, a1
, a0
;
21813 IRTemp b3
, b2
, b1
, b0
;
21814 IRTemp res0
= newTemp( Ity_I32
);
21815 IRTemp res1
= newTemp( Ity_I32
);
21816 IRTemp res2
= newTemp( Ity_I32
);
21817 IRTemp res3
= newTemp( Ity_I32
);
21818 IRTemp a0_I64
= newTemp( Ity_I64
);
21819 IRTemp a1_I64
= newTemp( Ity_I64
);
21820 IRTemp a2_I64
= newTemp( Ity_I64
);
21821 IRTemp a3_I64
= newTemp( Ity_I64
);
21822 IRTemp b0_I64
= newTemp( Ity_I64
);
21823 IRTemp b1_I64
= newTemp( Ity_I64
);
21824 IRTemp b2_I64
= newTemp( Ity_I64
);
21825 IRTemp b3_I64
= newTemp( Ity_I64
);
21827 Bool isMin
= opc2
== 0x320 ? True
: False
;
21829 a3
= a2
= a1
= a0
= IRTemp_INVALID
;
21830 b3
= b2
= b1
= b0
= IRTemp_INVALID
;
21831 DIP("%s v%d,v%d v%d\n", isMin
? "xvminsp" : "xvmaxsp", XT
, XA
, XB
);
21832 breakV128to4xF64( getVSReg( XA
), &a3
, &a2
, &a1
, &a0
);
21833 breakV128to4xF64( getVSReg( XB
), &b3
, &b2
, &b1
, &b0
);
21834 assign( a0_I64
, unop( Iop_ReinterpF64asI64
, mkexpr( a0
) ) );
21835 assign( b0_I64
, unop( Iop_ReinterpF64asI64
, mkexpr( b0
) ) );
21836 assign( a1_I64
, unop( Iop_ReinterpF64asI64
, mkexpr( a1
) ) );
21837 assign( b1_I64
, unop( Iop_ReinterpF64asI64
, mkexpr( b1
) ) );
21838 assign( a2_I64
, unop( Iop_ReinterpF64asI64
, mkexpr( a2
) ) );
21839 assign( b2_I64
, unop( Iop_ReinterpF64asI64
, mkexpr( b2
) ) );
21840 assign( a3_I64
, unop( Iop_ReinterpF64asI64
, mkexpr( a3
) ) );
21841 assign( b3_I64
, unop( Iop_ReinterpF64asI64
, mkexpr( b3
) ) );
21843 unop( Iop_ReinterpF32asI32
,
21844 unop( Iop_TruncF64asF32
,
21845 unop( Iop_ReinterpI64asF64
,
21846 get_max_min_fp( a0_I64
, b0_I64
, isMin
) ) ) ) );
21848 unop( Iop_ReinterpF32asI32
,
21849 unop( Iop_TruncF64asF32
,
21850 unop( Iop_ReinterpI64asF64
,
21851 get_max_min_fp( a1_I64
, b1_I64
, isMin
) ) ) ) );
21853 unop( Iop_ReinterpF32asI32
,
21854 unop( Iop_TruncF64asF32
,
21855 unop( Iop_ReinterpI64asF64
,
21856 get_max_min_fp( a2_I64
, b2_I64
, isMin
) ) ) ) );
21858 unop( Iop_ReinterpF32asI32
,
21859 unop( Iop_TruncF64asF32
,
21860 unop( Iop_ReinterpI64asF64
,
21861 get_max_min_fp( a3_I64
, b3_I64
, isMin
) ) ) ) );
21863 binop( Iop_64HLtoV128
,
21864 binop( Iop_32HLto64
, mkexpr( res3
), mkexpr( res2
) ),
21865 binop( Iop_32HLto64
, mkexpr( res1
), mkexpr( res0
) ) ) );
21868 case 0x380: // xvmaxdp (VSX Vector Maximum Double-Precision)
21869 case 0x3A0: // xvmindp (VSX Vector Minimum Double-Precision)
21871 UChar XA
= ifieldRegXA( theInstr
);
21872 IRTemp frA
= newTemp(Ity_I64
);
21873 IRTemp frB
= newTemp(Ity_I64
);
21874 IRTemp frA2
= newTemp(Ity_I64
);
21875 IRTemp frB2
= newTemp(Ity_I64
);
21876 Bool isMin
= opc2
== 0x3A0 ? True
: False
;
21878 assign(frA
, unop(Iop_V128HIto64
, getVSReg( XA
)));
21879 assign(frB
, unop(Iop_V128HIto64
, getVSReg( XB
)));
21880 assign(frA2
, unop(Iop_V128to64
, getVSReg( XA
)));
21881 assign(frB2
, unop(Iop_V128to64
, getVSReg( XB
)));
21882 DIP("%s v%d,v%d v%d\n", isMin
? "xvmindp" : "xvmaxdp", XT
, XA
, XB
);
21883 putVSReg( XT
, binop( Iop_64HLtoV128
, get_max_min_fp(frA
, frB
, isMin
), get_max_min_fp(frA2
, frB2
, isMin
) ) );
21887 case 0x3c0: // xvcpsgndp (VSX Vector Copy Sign Double-Precision)
21889 UChar XA
= ifieldRegXA( theInstr
);
21890 IRTemp frA
= newTemp(Ity_I64
);
21891 IRTemp frB
= newTemp(Ity_I64
);
21892 IRTemp frA2
= newTemp(Ity_I64
);
21893 IRTemp frB2
= newTemp(Ity_I64
);
21894 assign(frA
, unop(Iop_V128HIto64
, getVSReg( XA
)));
21895 assign(frB
, unop(Iop_V128HIto64
, getVSReg( XB
)));
21896 assign(frA2
, unop(Iop_V128to64
, getVSReg( XA
)));
21897 assign(frB2
, unop(Iop_V128to64
, getVSReg( XB
)));
21899 DIP("xvcpsgndp v%d,v%d,v%d\n", XT
, XA
, XB
);
21901 binop( Iop_64HLtoV128
,
21905 mkU64( SIGN_BIT
) ),
21908 mkU64( SIGN_MASK
) ) ),
21912 mkU64( SIGN_BIT
) ),
21915 mkU64( SIGN_MASK
) ) ) ) );
21918 case 0x340: // xvcpsgnsp
21920 UChar XA
= ifieldRegXA( theInstr
);
21921 IRTemp a3_I64
, a2_I64
, a1_I64
, a0_I64
;
21922 IRTemp b3_I64
, b2_I64
, b1_I64
, b0_I64
;
21923 IRTemp resHi
= newTemp(Ity_I64
);
21924 IRTemp resLo
= newTemp(Ity_I64
);
21926 a3_I64
= a2_I64
= a1_I64
= a0_I64
= IRTemp_INVALID
;
21927 b3_I64
= b2_I64
= b1_I64
= b0_I64
= IRTemp_INVALID
;
21928 DIP("xvcpsgnsp v%d,v%d v%d\n",XT
, XA
, XB
);
21929 breakV128to4x64U( getVSReg( XA
), &a3_I64
, &a2_I64
, &a1_I64
, &a0_I64
);
21930 breakV128to4x64U( getVSReg( XB
), &b3_I64
, &b2_I64
, &b1_I64
, &b0_I64
);
21933 binop( Iop_32HLto64
,
21936 unop(Iop_64to32
, mkexpr( a3_I64
) ),
21937 mkU32( SIGN_BIT32
) ),
21939 unop(Iop_64to32
, mkexpr( b3_I64
) ),
21940 mkU32( SIGN_MASK32
) ) ),
21944 unop(Iop_64to32
, mkexpr( a2_I64
) ),
21945 mkU32( SIGN_BIT32
) ),
21947 unop(Iop_64to32
, mkexpr( b2_I64
) ),
21948 mkU32( SIGN_MASK32
) ) ) ) );
21950 binop( Iop_32HLto64
,
21953 unop(Iop_64to32
, mkexpr( a1_I64
) ),
21954 mkU32( SIGN_BIT32
) ),
21956 unop(Iop_64to32
, mkexpr( b1_I64
) ),
21957 mkU32( SIGN_MASK32
) ) ),
21961 unop(Iop_64to32
, mkexpr( a0_I64
) ),
21962 mkU32( SIGN_BIT32
) ),
21964 unop(Iop_64to32
, mkexpr( b0_I64
) ),
21965 mkU32( SIGN_MASK32
) ) ) ) );
21966 putVSReg( XT
, binop( Iop_64HLtoV128
, mkexpr( resHi
), mkexpr( resLo
) ) );
21969 case 0x3B2: // xvabsdp (VSX Vector Absolute Value Double-Precision)
21970 case 0x3D2: // xvnabsdp VSX Vector Negative Absolute Value Double-Precision)
21972 IRTemp frB
= newTemp(Ity_F64
);
21973 IRTemp frB2
= newTemp(Ity_F64
);
21974 IRTemp abs_resultHi
= newTemp(Ity_F64
);
21975 IRTemp abs_resultLo
= newTemp(Ity_F64
);
21976 Bool make_negative
= (opc2
== 0x3D2) ? True
: False
;
21977 assign(frB
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128HIto64
, getVSReg( XB
))));
21978 assign(frB2
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128to64
, getVSReg(XB
))));
21980 DIP("xv%sabsdp v%d,v%d\n", make_negative
? "n" : "", XT
, XB
);
21981 if (make_negative
) {
21982 assign(abs_resultHi
, unop( Iop_NegF64
, unop( Iop_AbsF64
, mkexpr( frB
) ) ) );
21983 assign(abs_resultLo
, unop( Iop_NegF64
, unop( Iop_AbsF64
, mkexpr( frB2
) ) ) );
21986 assign(abs_resultHi
, unop( Iop_AbsF64
, mkexpr( frB
) ) );
21987 assign(abs_resultLo
, unop( Iop_AbsF64
, mkexpr( frB2
) ) );
21989 putVSReg( XT
, binop( Iop_64HLtoV128
,
21990 unop( Iop_ReinterpF64asI64
, mkexpr( abs_resultHi
) ),
21991 unop( Iop_ReinterpF64asI64
, mkexpr( abs_resultLo
) ) ) );
21994 case 0x332: // xvabssp (VSX Vector Absolute Value Single-Precision)
21995 case 0x352: // xvnabssp (VSX Vector Negative Absolute Value Single-Precision)
21998 * The Iop_AbsF32 IRop is not implemented for ppc64 since, up until introduction
21999 * of xvabssp, there has not been an abs(sp) type of instruction. But since emulation
22000 * of this function is so easy using shifts, I choose to emulate this instruction that
22001 * way versus a native instruction method of implementation.
22003 Bool make_negative
= (opc2
== 0x352) ? True
: False
;
22004 IRTemp shiftVector
= newTemp(Ity_V128
);
22005 IRTemp absVal_vector
= newTemp(Ity_V128
);
22006 assign( shiftVector
,
22007 binop( Iop_64HLtoV128
,
22008 binop( Iop_32HLto64
, mkU32( 1 ), mkU32( 1 ) ),
22009 binop( Iop_32HLto64
, mkU32( 1 ), mkU32( 1 ) ) ) );
22010 assign( absVal_vector
,
22011 binop( Iop_Shr32x4
,
22012 binop( Iop_Shl32x4
,
22014 mkexpr( shiftVector
) ),
22015 mkexpr( shiftVector
) ) );
22016 if (make_negative
) {
22017 IRTemp signBit_vector
= newTemp(Ity_V128
);
22018 assign( signBit_vector
,
22019 binop( Iop_64HLtoV128
,
22020 binop( Iop_32HLto64
,
22021 mkU32( 0x80000000 ),
22022 mkU32( 0x80000000 ) ),
22023 binop( Iop_32HLto64
,
22024 mkU32( 0x80000000 ),
22025 mkU32( 0x80000000 ) ) ) );
22028 mkexpr( absVal_vector
),
22029 mkexpr( signBit_vector
) ) );
22031 putVSReg( XT
, mkexpr( absVal_vector
) );
22035 case 0x372: // xvnegsp (VSX Vector Negate Single-Precision)
22037 IRTemp B0
= newTemp(Ity_I32
);
22038 IRTemp B1
= newTemp(Ity_I32
);
22039 IRTemp B2
= newTemp(Ity_I32
);
22040 IRTemp B3
= newTemp(Ity_I32
);
22042 DIP("xvnegsp v%d,v%d\n", XT
, XB
);
22044 /* Don't support NegF32, so just XOR the sign bit in the int value */
22045 assign(B0
, unop( Iop_64HIto32
,
22046 unop( Iop_V128HIto64
, getVSReg( XB
) ) ) );
22047 assign(B1
, unop( Iop_64to32
,
22048 unop( Iop_V128HIto64
, getVSReg( XB
) ) ) );
22049 assign(B2
, unop( Iop_64HIto32
,
22050 unop( Iop_V128to64
, getVSReg( XB
) ) ) );
22051 assign(B3
, unop( Iop_64to32
,
22052 unop( Iop_V128to64
, getVSReg( XB
) ) ) );
22055 binop( Iop_64HLtoV128
,
22056 binop( Iop_32HLto64
,
22057 binop( Iop_Xor32
, mkexpr( B0
), mkU32( 0x80000000 ) ),
22058 binop( Iop_Xor32
, mkexpr( B1
), mkU32( 0x80000000 ) ) ),
22059 binop( Iop_32HLto64
,
22060 binop( Iop_Xor32
, mkexpr( B2
), mkU32( 0x80000000 ) ),
22061 binop( Iop_Xor32
, mkexpr( B3
), mkU32( 0x80000000 ) ) ) ) );
22064 case 0x3F2: // xvnegdp (VSX Vector Negate Double-Precision)
22066 IRTemp frB
= newTemp(Ity_F64
);
22067 IRTemp frB2
= newTemp(Ity_F64
);
22068 assign(frB
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128HIto64
, getVSReg( XB
))));
22069 assign(frB2
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128to64
, getVSReg(XB
))));
22070 DIP("xvnegdp v%d,v%d\n", XT
, XB
);
22072 binop( Iop_64HLtoV128
,
22073 unop( Iop_ReinterpF64asI64
,
22074 unop( Iop_NegF64
, mkexpr( frB
) ) ),
22075 unop( Iop_ReinterpF64asI64
,
22076 unop( Iop_NegF64
, mkexpr( frB2
) ) ) ) );
22079 case 0x192: // xvrdpi (VSX Vector Round to Double-Precision Integer using round toward Nearest Away)
22080 case 0x1D6: // xvrdpic (VSX Vector Round to Double-Precision Integer using Current rounding mode)
22081 case 0x1F2: // xvrdpim (VSX Vector Round to Double-Precision Integer using round toward -Infinity)
22082 case 0x1D2: // xvrdpip (VSX Vector Round to Double-Precision Integer using round toward +Infinity)
22083 case 0x1B2: // xvrdpiz (VSX Vector Round to Double-Precision Integer using round toward Zero)
22085 IRTemp frBHi_I64
= newTemp(Ity_I64
);
22086 IRTemp frBLo_I64
= newTemp(Ity_I64
);
22087 IRExpr
* frD_fp_roundHi
= NULL
;
22088 IRExpr
* frD_fp_roundLo
= NULL
;
22090 assign( frBHi_I64
, unop( Iop_V128HIto64
, getVSReg( XB
) ) );
22091 frD_fp_roundHi
= _do_vsx_fp_roundToInt(frBHi_I64
, opc2
);
22092 assign( frBLo_I64
, unop( Iop_V128to64
, getVSReg( XB
) ) );
22093 frD_fp_roundLo
= _do_vsx_fp_roundToInt(frBLo_I64
, opc2
);
22095 DIP("xvrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2
), XT
, XB
);
22097 binop( Iop_64HLtoV128
,
22098 unop( Iop_ReinterpF64asI64
, frD_fp_roundHi
),
22099 unop( Iop_ReinterpF64asI64
, frD_fp_roundLo
) ) );
22102 case 0x112: // xvrspi (VSX Vector Round to Single-Precision Integer using round toward Nearest Away)
22103 case 0x156: // xvrspic (VSX Vector Round to SinglePrecision Integer using Current rounding mode)
22104 case 0x172: // xvrspim (VSX Vector Round to SinglePrecision Integer using round toward -Infinity)
22105 case 0x152: // xvrspip (VSX Vector Round to SinglePrecision Integer using round toward +Infinity)
22106 case 0x132: // xvrspiz (VSX Vector Round to SinglePrecision Integer using round toward Zero)
22108 const HChar
* insn_suffix
= NULL
;
22110 if (opc2
!= 0x156) {
22111 // Use pre-defined IRop's for vrfi{m|n|p|z}
22115 op
= Iop_RoundF32x4_RN
;
22119 op
= Iop_RoundF32x4_RM
;
22123 op
= Iop_RoundF32x4_RP
;
22127 op
= Iop_RoundF32x4_RZ
;
22131 vex_printf("Unrecognized opcode %x\n", opc2
);
22132 vpanic("dis_vxv_misc(ppc)(vrspi<x>)(opc2)\n");
22134 DIP("xvrspi%s v%d,v%d\n", insn_suffix
, XT
, XB
);
22135 putVSReg( XT
, unop( op
, getVSReg(XB
) ) );
22137 // Handle xvrspic. Unfortunately there is no corresponding "vfric" instruction.
22138 IRExpr
* frD_fp_roundb3
, * frD_fp_roundb2
, * frD_fp_roundb1
, * frD_fp_roundb0
;
22139 IRTemp b3_F64
, b2_F64
, b1_F64
, b0_F64
;
22140 IRTemp b3_I64
= newTemp(Ity_I64
);
22141 IRTemp b2_I64
= newTemp(Ity_I64
);
22142 IRTemp b1_I64
= newTemp(Ity_I64
);
22143 IRTemp b0_I64
= newTemp(Ity_I64
);
22145 b3_F64
= b2_F64
= b1_F64
= b0_F64
= IRTemp_INVALID
;
22146 frD_fp_roundb3
= frD_fp_roundb2
= frD_fp_roundb1
= frD_fp_roundb0
= NULL
;
22147 breakV128to4xF64( getVSReg(XB
), &b3_F64
, &b2_F64
, &b1_F64
, &b0_F64
);
22148 assign(b3_I64
, unop(Iop_ReinterpF64asI64
, mkexpr(b3_F64
)));
22149 assign(b2_I64
, unop(Iop_ReinterpF64asI64
, mkexpr(b2_F64
)));
22150 assign(b1_I64
, unop(Iop_ReinterpF64asI64
, mkexpr(b1_F64
)));
22151 assign(b0_I64
, unop(Iop_ReinterpF64asI64
, mkexpr(b0_F64
)));
22152 frD_fp_roundb3
= unop(Iop_TruncF64asF32
,
22153 _do_vsx_fp_roundToInt(b3_I64
, opc2
));
22154 frD_fp_roundb2
= unop(Iop_TruncF64asF32
,
22155 _do_vsx_fp_roundToInt(b2_I64
, opc2
));
22156 frD_fp_roundb1
= unop(Iop_TruncF64asF32
,
22157 _do_vsx_fp_roundToInt(b1_I64
, opc2
));
22158 frD_fp_roundb0
= unop(Iop_TruncF64asF32
,
22159 _do_vsx_fp_roundToInt(b0_I64
, opc2
));
22160 DIP("xvrspic v%d,v%d\n", XT
, XB
);
22162 binop( Iop_64HLtoV128
,
22163 binop( Iop_32HLto64
,
22164 unop( Iop_ReinterpF32asI32
, frD_fp_roundb3
),
22165 unop( Iop_ReinterpF32asI32
, frD_fp_roundb2
) ),
22166 binop( Iop_32HLto64
,
22167 unop( Iop_ReinterpF32asI32
, frD_fp_roundb1
),
22168 unop( Iop_ReinterpF32asI32
, frD_fp_roundb0
) ) ) );
22174 vex_printf( "dis_vxv_misc(ppc)(opc2)\n" );
22182 * VSX Scalar Floating Point Arithmetic Instructions
22185 dis_vxs_arith ( UInt prefix
, UInt theInstr
, UInt opc2
)
22188 UChar opc1
= ifieldOPC( theInstr
);
22189 UChar XT
= ifieldRegXT( theInstr
);
22190 UChar XA
= ifieldRegXA( theInstr
);
22191 UChar XB
= ifieldRegXB( theInstr
);
22192 IRExpr
* rm
= get_IR_roundingmode();
22193 IRTemp frA
= newTemp(Ity_F64
);
22194 IRTemp frB
= newTemp(Ity_F64
);
22196 /* There is no prefixed version of these instructions. */
22199 if (opc1
!= 0x3C) {
22200 vex_printf( "dis_vxs_arith(ppc)(instr)\n" );
22204 assign(frA
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128HIto64
, getVSReg( XA
))));
22205 assign(frB
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128HIto64
, getVSReg( XB
))));
22207 /* For all the VSX sclar arithmetic instructions, the contents of doubleword element 1
22208 * of VSX[XT] are undefined after the operation; therefore, we can simply set
22209 * element to zero where it makes sense to do so.
22212 case 0x000: // xsaddsp (VSX Scalar Add Single-Precision)
22213 DIP("xsaddsp v%d,v%d,v%d\n", XT
, XA
, XB
);
22214 putVSReg( XT
, binop( Iop_64HLtoV128
,
22215 unop( Iop_ReinterpF64asI64
,
22216 binop( Iop_RoundF64toF32
, rm
,
22217 triop( Iop_AddF64
, rm
,
22219 mkexpr( frB
) ) ) ),
22222 case 0x020: // xssubsp (VSX Scalar Subtract Single-Precision)
22223 DIP("xssubsp v%d,v%d,v%d\n", XT
, XA
, XB
);
22224 putVSReg( XT
, binop( Iop_64HLtoV128
,
22225 unop( Iop_ReinterpF64asI64
,
22226 binop( Iop_RoundF64toF32
, rm
,
22227 triop( Iop_SubF64
, rm
,
22229 mkexpr( frB
) ) ) ),
22232 case 0x080: // xsadddp (VSX scalar add double-precision)
22233 DIP("xsadddp v%d,v%d,v%d\n", XT
, XA
, XB
);
22234 putVSReg( XT
, binop( Iop_64HLtoV128
, unop( Iop_ReinterpF64asI64
,
22235 triop( Iop_AddF64
, rm
,
22240 case 0x060: // xsdivsp (VSX scalar divide single-precision)
22241 DIP("xsdivsp v%d,v%d,v%d\n", XT
, XA
, XB
);
22242 putVSReg( XT
, binop( Iop_64HLtoV128
,
22243 unop( Iop_ReinterpF64asI64
,
22244 binop( Iop_RoundF64toF32
, rm
,
22245 triop( Iop_DivF64
, rm
,
22247 mkexpr( frB
) ) ) ),
22250 case 0x0E0: // xsdivdp (VSX scalar divide double-precision)
22251 DIP("xsdivdp v%d,v%d,v%d\n", XT
, XA
, XB
);
22252 putVSReg( XT
, binop( Iop_64HLtoV128
, unop( Iop_ReinterpF64asI64
,
22253 triop( Iop_DivF64
, rm
,
22258 case 0x004: case 0x024: /* xsmaddasp, xsmaddmsp (VSX scalar multiply-add
22259 * single-precision)
22262 IRTemp frT
= newTemp(Ity_F64
);
22263 Bool mdp
= opc2
== 0x024;
22264 DIP("xsmadd%ssp v%d,v%d,v%d\n", mdp
? "m" : "a", XT
, XA
, XB
);
22265 assign( frT
, unop( Iop_ReinterpI64asF64
, unop( Iop_V128HIto64
,
22266 getVSReg( XT
) ) ) );
22268 binop( Iop_64HLtoV128
,
22269 unop( Iop_ReinterpF64asI64
,
22270 binop( Iop_RoundF64toF32
, rm
,
22271 qop( Iop_MAddF64
, rm
,
22273 mkexpr( mdp
? frT
: frB
),
22274 mkexpr( mdp
? frB
: frT
) ) ) ),
22278 case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp (VSX scalar multiply-add double-precision)
22280 IRTemp frT
= newTemp(Ity_F64
);
22281 Bool mdp
= opc2
== 0x0A4;
22282 DIP("xsmadd%sdp v%d,v%d,v%d\n", mdp
? "m" : "a", XT
, XA
, XB
);
22283 assign( frT
, unop( Iop_ReinterpI64asF64
, unop( Iop_V128HIto64
,
22284 getVSReg( XT
) ) ) );
22285 putVSReg( XT
, binop( Iop_64HLtoV128
, unop( Iop_ReinterpF64asI64
,
22286 qop( Iop_MAddF64
, rm
,
22288 mkexpr( mdp
? frT
: frB
),
22289 mkexpr( mdp
? frB
: frT
) ) ),
22293 case 0x044: case 0x064: /* xsmsubasp, xsmsubmsp (VSX scalar
22294 * multiply-subtract single-precision)
22297 IRTemp frT
= newTemp(Ity_F64
);
22298 Bool mdp
= opc2
== 0x064;
22299 DIP("xsmsub%ssp v%d,v%d,v%d\n", mdp
? "m" : "a", XT
, XA
, XB
);
22300 assign( frT
, unop( Iop_ReinterpI64asF64
, unop( Iop_V128HIto64
,
22301 getVSReg( XT
) ) ) );
22303 binop( Iop_64HLtoV128
,
22304 unop( Iop_ReinterpF64asI64
,
22305 binop( Iop_RoundF64toF32
, rm
,
22306 qop( Iop_MSubF64
, rm
,
22308 mkexpr( mdp
? frT
: frB
),
22309 mkexpr( mdp
? frB
: frT
) ) ) ),
22313 case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp (VSX scalar multiply-subtract double-precision)
22315 IRTemp frT
= newTemp(Ity_F64
);
22316 Bool mdp
= opc2
== 0x0E4;
22317 DIP("xsmsub%sdp v%d,v%d,v%d\n", mdp
? "m" : "a", XT
, XA
, XB
);
22318 assign( frT
, unop( Iop_ReinterpI64asF64
, unop( Iop_V128HIto64
,
22319 getVSReg( XT
) ) ) );
22320 putVSReg( XT
, binop( Iop_64HLtoV128
, unop( Iop_ReinterpF64asI64
,
22321 qop( Iop_MSubF64
, rm
,
22323 mkexpr( mdp
? frT
: frB
),
22324 mkexpr( mdp
? frB
: frT
) ) ),
22328 case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp (VSX scalar multiply-add double-precision)
22330 /* TODO: mpj -- Naturally, I expected to be able to leverage the implementation
22331 * of fnmadd and use pretty much the same code. However, that code has a bug in the
22332 * way it blindly negates the signbit, even if the floating point result is a NaN.
22333 * So, the TODO is to fix fnmadd (which I'll do in a different patch).
22334 * FIXED 7/1/2012: carll fnmadd and fnmsubs fixed to not negate sign
22335 * bit for NaN result.
22337 Bool mdp
= opc2
== 0x2A4;
22338 IRTemp frT
= newTemp(Ity_F64
);
22339 IRTemp maddResult
= newTemp(Ity_I64
);
22341 DIP("xsnmadd%sdp v%d,v%d,v%d\n", mdp
? "m" : "a", XT
, XA
, XB
);
22342 assign( frT
, unop( Iop_ReinterpI64asF64
, unop( Iop_V128HIto64
,
22343 getVSReg( XT
) ) ) );
22344 assign( maddResult
, unop( Iop_ReinterpF64asI64
, qop( Iop_MAddF64
, rm
,
22346 mkexpr( mdp
? frT
: frB
),
22347 mkexpr( mdp
? frB
: frT
) ) ) );
22349 putVSReg( XT
, binop( Iop_64HLtoV128
, mkexpr( getNegatedResult(maddResult
) ),
22353 case 0x204: case 0x224: /* xsnmaddasp, xsnmaddmsp (VSX scalar
22354 * multiply-add single-precision)
22357 Bool mdp
= opc2
== 0x224;
22358 IRTemp frT
= newTemp(Ity_F64
);
22359 IRTemp maddResult
= newTemp(Ity_I64
);
22361 DIP("xsnmadd%ssp v%d,v%d,v%d\n", mdp
? "m" : "a", XT
, XA
, XB
);
22362 assign( frT
, unop( Iop_ReinterpI64asF64
, unop( Iop_V128HIto64
,
22363 getVSReg( XT
) ) ) );
22364 assign( maddResult
,
22365 unop( Iop_ReinterpF64asI64
,
22366 binop( Iop_RoundF64toF32
, rm
,
22367 qop( Iop_MAddF64
, rm
,
22369 mkexpr( mdp
? frT
: frB
),
22370 mkexpr( mdp
? frB
: frT
) ) ) ) );
22372 putVSReg( XT
, binop( Iop_64HLtoV128
,
22373 mkexpr( getNegatedResult(maddResult
) ),
22377 case 0x244: case 0x264: /* xsnmsubasp, xsnmsubmsp (VSX Scalar Negative
22378 * Multiply-Subtract Single-Precision)
22381 IRTemp frT
= newTemp(Ity_F64
);
22382 Bool mdp
= opc2
== 0x264;
22383 IRTemp msubResult
= newTemp(Ity_I64
);
22385 DIP("xsnmsub%ssp v%d,v%d,v%d\n", mdp
? "m" : "a", XT
, XA
, XB
);
22386 assign( frT
, unop( Iop_ReinterpI64asF64
, unop( Iop_V128HIto64
,
22387 getVSReg( XT
) ) ) );
22388 assign( msubResult
,
22389 unop( Iop_ReinterpF64asI64
,
22390 binop( Iop_RoundF64toF32
, rm
,
22391 qop( Iop_MSubF64
, rm
,
22393 mkexpr( mdp
? frT
: frB
),
22394 mkexpr( mdp
? frB
: frT
) ) ) ) );
22396 putVSReg( XT
, binop( Iop_64HLtoV128
,
22397 mkexpr( getNegatedResult(msubResult
) ),
22403 case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp (VSX Scalar Negative Multiply-Subtract Double-Precision)
22405 IRTemp frT
= newTemp(Ity_F64
);
22406 Bool mdp
= opc2
== 0x2E4;
22407 IRTemp msubResult
= newTemp(Ity_I64
);
22409 DIP("xsnmsub%sdp v%d,v%d,v%d\n", mdp
? "m" : "a", XT
, XA
, XB
);
22410 assign( frT
, unop( Iop_ReinterpI64asF64
, unop( Iop_V128HIto64
,
22411 getVSReg( XT
) ) ) );
22412 assign(msubResult
, unop( Iop_ReinterpF64asI64
,
22416 mkexpr( mdp
? frT
: frB
),
22417 mkexpr( mdp
? frB
: frT
) ) ));
22419 putVSReg( XT
, binop( Iop_64HLtoV128
, mkexpr( getNegatedResult(msubResult
) ), mkU64( 0 ) ) );
22424 case 0x040: // xsmulsp (VSX Scalar Multiply Single-Precision)
22425 DIP("xsmulsp v%d,v%d,v%d\n", XT
, XA
, XB
);
22426 putVSReg( XT
, binop( Iop_64HLtoV128
,
22427 unop( Iop_ReinterpF64asI64
,
22428 binop( Iop_RoundF64toF32
, rm
,
22429 triop( Iop_MulF64
, rm
,
22431 mkexpr( frB
) ) ) ),
22435 case 0x0C0: // xsmuldp (VSX Scalar Multiply Double-Precision)
22436 DIP("xsmuldp v%d,v%d,v%d\n", XT
, XA
, XB
);
22437 putVSReg( XT
, binop( Iop_64HLtoV128
, unop( Iop_ReinterpF64asI64
,
22438 triop( Iop_MulF64
, rm
,
22443 case 0x0A0: // xssubdp (VSX Scalar Subtract Double-Precision)
22444 DIP("xssubdp v%d,v%d,v%d\n", XT
, XA
, XB
);
22445 putVSReg( XT
, binop( Iop_64HLtoV128
, unop( Iop_ReinterpF64asI64
,
22446 triop( Iop_SubF64
, rm
,
22452 case 0x016: // xssqrtsp (VSX Scalar Square Root Single-Precision)
22453 DIP("xssqrtsp v%d,v%d\n", XT
, XB
);
22455 binop( Iop_64HLtoV128
,
22456 unop( Iop_ReinterpF64asI64
,
22457 binop( Iop_RoundF64toF32
, rm
,
22458 binop( Iop_SqrtF64
, rm
,
22459 mkexpr( frB
) ) ) ),
22463 case 0x096: // xssqrtdp (VSX Scalar Square Root Double-Precision)
22464 DIP("xssqrtdp v%d,v%d\n", XT
, XB
);
22465 putVSReg( XT
, binop( Iop_64HLtoV128
, unop( Iop_ReinterpF64asI64
,
22466 binop( Iop_SqrtF64
, rm
,
22471 case 0x0F4: // xstdivdp (VSX Scalar Test for software Divide Double-Precision)
22473 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) );
22474 IRTemp frA_I64
= newTemp(Ity_I64
);
22475 IRTemp frB_I64
= newTemp(Ity_I64
);
22476 DIP("xstdivdp crf%d,v%d,v%d\n", crfD
, XA
, XB
);
22477 assign( frA_I64
, unop( Iop_ReinterpF64asI64
, mkexpr( frA
) ) );
22478 assign( frB_I64
, unop( Iop_ReinterpF64asI64
, mkexpr( frB
) ) );
22479 putGST_field( PPC_GST_CR
, do_fp_tdiv(frA_I64
, frB_I64
), crfD
);
22482 case 0x0D4: // xstsqrtdp (VSX Vector Test for software Square Root Double-Precision)
22484 IRTemp frB_I64
= newTemp(Ity_I64
);
22485 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) );
22486 IRTemp flags
= newTemp(Ity_I32
);
22487 IRTemp fe_flag
, fg_flag
;
22488 fe_flag
= fg_flag
= IRTemp_INVALID
;
22489 DIP("xstsqrtdp v%d,v%d\n", XT
, XB
);
22490 assign( frB_I64
, unop(Iop_V128HIto64
, getVSReg( XB
)) );
22491 do_fp_tsqrt(frB_I64
, False
/*not single precision*/, &fe_flag
, &fg_flag
);
22492 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
22493 * where fl_flag == 1 on ppc64.
22497 binop( Iop_Or32
, mkU32( 8 ), // fl_flag
22498 binop( Iop_Shl32
, mkexpr(fg_flag
), mkU8( 2 ) ) ),
22499 binop( Iop_Shl32
, mkexpr(fe_flag
), mkU8( 1 ) ) ) );
22500 putGST_field( PPC_GST_CR
, mkexpr(flags
), crfD
);
22505 vex_printf( "dis_vxs_arith(ppc)(opc2)\n" );
22514 * VSX Floating Point Compare Instructions
22517 dis_vx_cmp( UInt prefix
, UInt theInstr
, UInt opc2
)
22519 /* XX3-Form and XX2-Form */
22520 UChar opc1
= ifieldOPC( theInstr
);
22521 UChar crfD
= toUChar( IFIELD( theInstr
, 23, 3 ) );
22523 UChar XA
= ifieldRegXA ( theInstr
);
22524 UChar XB
= ifieldRegXB ( theInstr
);
22525 IRTemp frA
= newTemp(Ity_F64
);
22526 IRTemp frB
= newTemp(Ity_F64
);
22528 /* There is no prefixed version of these instructions. */
22531 if (opc1
!= 0x3C) {
22532 vex_printf( "dis_vx_cmp(ppc)(instr)\n" );
22536 assign(frA
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128HIto64
, getVSReg( XA
))));
22537 assign(frB
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128HIto64
, getVSReg( XB
))));
22539 case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
22540 /* Note: Differences between xscmpudp and xscmpodp are only in
22541 * exception flag settings, which aren't supported anyway. */
22542 DIP("xscmp%sdp crf%d,fr%u,fr%u\n", opc2
== 0x08c ? "u" : "o",
22544 ccPPC32
= get_fp_cmp_CR_val( binop(Iop_CmpF64
, mkexpr(frA
), mkexpr(frB
)));
22545 putGST_field( PPC_GST_CR
, mkexpr(ccPPC32
), crfD
);
22546 putFPCC( mkexpr( ccPPC32
) );
22550 vex_printf( "dis_vx_cmp(ppc)(opc2)\n" );
22557 do_vvec_fp_cmp ( IRTemp vA
, IRTemp vB
, UChar XT
, UChar flag_rC
,
22558 ppc_cmp_t cmp_type
)
22560 IRTemp frA_hi
= newTemp(Ity_F64
);
22561 IRTemp frB_hi
= newTemp(Ity_F64
);
22562 IRTemp frA_lo
= newTemp(Ity_F64
);
22563 IRTemp frB_lo
= newTemp(Ity_F64
);
22564 IRTemp ccPPC32
= newTemp(Ity_I32
);
22568 IRTemp hiResult
= newTemp(Ity_I64
);
22569 IRTemp loResult
= newTemp(Ity_I64
);
22570 IRTemp hiEQlo
= newTemp(Ity_I1
);
22571 IRTemp all_elem_true
= newTemp(Ity_I32
);
22572 IRTemp all_elem_false
= newTemp(Ity_I32
);
22574 assign(frA_hi
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128HIto64
, mkexpr( vA
))));
22575 assign(frB_hi
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128HIto64
, mkexpr( vB
))));
22576 assign(frA_lo
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128to64
, mkexpr( vA
))));
22577 assign(frB_lo
, unop(Iop_ReinterpI64asF64
, unop(Iop_V128to64
, mkexpr( vB
))));
22579 ccIR_hi
= get_fp_cmp_CR_val( binop( Iop_CmpF64
,
22581 mkexpr( frB_hi
) ) );
22582 ccIR_lo
= get_fp_cmp_CR_val( binop( Iop_CmpF64
,
22584 mkexpr( frB_lo
) ) );
22586 if (cmp_type
!= PPC_CMP_GE
) {
22589 binop( Iop_CmpEQ32
, mkexpr( ccIR_hi
), mkU32( cmp_type
) ) ) );
22592 binop( Iop_CmpEQ32
, mkexpr( ccIR_lo
), mkU32( cmp_type
) ) ) );
22594 // For PPC_CMP_GE, one element compare may return "4" (for "greater than") and
22595 // the other element compare may return "2" (for "equal to").
22596 IRTemp lo_GE
= newTemp(Ity_I1
);
22597 IRTemp hi_GE
= newTemp(Ity_I1
);
22599 assign(hi_GE
, mkOR1( binop( Iop_CmpEQ32
, mkexpr( ccIR_hi
), mkU32( 2 ) ),
22600 binop( Iop_CmpEQ32
, mkexpr( ccIR_hi
), mkU32( 4 ) ) ) );
22601 assign( hiResult
,unop( Iop_1Sto64
, mkexpr( hi_GE
) ) );
22603 assign(lo_GE
, mkOR1( binop( Iop_CmpEQ32
, mkexpr( ccIR_lo
), mkU32( 2 ) ),
22604 binop( Iop_CmpEQ32
, mkexpr( ccIR_lo
), mkU32( 4 ) ) ) );
22605 assign( loResult
, unop( Iop_1Sto64
, mkexpr( lo_GE
) ) );
22608 // The [hi/lo]Result will be all 1's or all 0's. We just look at the lower word.
22610 binop( Iop_CmpEQ32
,
22611 unop( Iop_64to32
, mkexpr( hiResult
) ),
22612 unop( Iop_64to32
, mkexpr( loResult
) ) ) );
22614 binop( Iop_64HLtoV128
, mkexpr( hiResult
), mkexpr( loResult
) ) );
22616 assign( all_elem_true
,
22618 mkAND1( mkexpr( hiEQlo
),
22619 binop( Iop_CmpEQ32
,
22620 mkU32( 0xffffffff ),
22622 mkexpr( hiResult
) ) ) ) ) );
22624 assign( all_elem_false
,
22626 mkAND1( mkexpr( hiEQlo
),
22627 binop( Iop_CmpEQ32
,
22630 mkexpr( hiResult
) ) ) ) ) );
22633 binop( Iop_Shl32
, mkexpr( all_elem_false
), mkU8( 1 ) ),
22634 binop( Iop_Shl32
, mkexpr( all_elem_true
), mkU8( 3 ) ) ) );
22637 putGST_field( PPC_GST_CR
, mkexpr(ccPPC32
), 6 );
22642 * VSX Vector Compare Instructions
22645 dis_vvec_cmp( UInt prefix
, UInt theInstr
, UInt opc2
)
22648 UChar opc1
= ifieldOPC( theInstr
);
22649 UChar XT
= ifieldRegXT ( theInstr
);
22650 UChar XA
= ifieldRegXA ( theInstr
);
22651 UChar XB
= ifieldRegXB ( theInstr
);
22652 UChar flag_rC
= ifieldBIT10(theInstr
);
22653 IRTemp vA
= newTemp( Ity_V128
);
22654 IRTemp vB
= newTemp( Ity_V128
);
22656 /* There is no prefixed version of these instructions. */
22659 if (opc1
!= 0x3C) {
22660 vex_printf( "dis_vvec_cmp(ppc)(instr)\n" );
22664 assign( vA
, getVSReg( XA
) );
22665 assign( vB
, getVSReg( XB
) );
22668 case 0x18C: // xvcmpeqdp[.] (VSX Vector Compare Equal To Double-Precision [ & Record ])
22670 DIP("xvcmpeqdp%s crf%d,fr%u,fr%u\n", (flag_rC
? ".":""),
22672 do_vvec_fp_cmp(vA
, vB
, XT
, flag_rC
, PPC_CMP_EQ
);
22676 case 0x1CC: // xvcmpgedp[.] (VSX Vector Compare Greater Than or Equal To Double-Precision [ & Record ])
22678 DIP("xvcmpgedp%s crf%d,fr%u,fr%u\n", (flag_rC
? ".":""),
22680 do_vvec_fp_cmp(vA
, vB
, XT
, flag_rC
, PPC_CMP_GE
);
22684 case 0x1AC: // xvcmpgtdp[.] (VSX Vector Compare Greater Than Double-Precision [ & Record ])
22686 DIP("xvcmpgtdp%s crf%d,fr%u,fr%u\n", (flag_rC
? ".":""),
22688 do_vvec_fp_cmp(vA
, vB
, XT
, flag_rC
, PPC_CMP_GT
);
22692 case 0x10C: // xvcmpeqsp[.] (VSX Vector Compare Equal To Single-Precision [ & Record ])
22694 IRTemp vD
= newTemp(Ity_V128
);
22696 DIP("xvcmpeqsp%s crf%d,fr%u,fr%u\n", (flag_rC
? ".":""),
22698 assign( vD
, binop(Iop_CmpEQ32Fx4
, mkexpr(vA
), mkexpr(vB
)) );
22699 putVSReg( XT
, mkexpr(vD
) );
22701 set_AV_CR6( mkexpr(vD
), True
);
22706 case 0x14C: // xvcmpgesp[.] (VSX Vector Compare Greater Than or Equal To Single-Precision [ & Record ])
22708 IRTemp vD
= newTemp(Ity_V128
);
22710 DIP("xvcmpgesp%s crf%d,fr%u,fr%u\n", (flag_rC
? ".":""),
22712 assign( vD
, binop(Iop_CmpGE32Fx4
, mkexpr(vA
), mkexpr(vB
)) );
22713 putVSReg( XT
, mkexpr(vD
) );
22715 set_AV_CR6( mkexpr(vD
), True
);
22720 case 0x12C: //xvcmpgtsp[.] (VSX Vector Compare Greater Than Single-Precision [ & Record ])
22722 IRTemp vD
= newTemp(Ity_V128
);
22724 DIP("xvcmpgtsp%s crf%d,fr%u,fr%u\n", (flag_rC
? ".":""),
22726 assign( vD
, binop(Iop_CmpGT32Fx4
, mkexpr(vA
), mkexpr(vB
)) );
22727 putVSReg( XT
, mkexpr(vD
) );
22729 set_AV_CR6( mkexpr(vD
), True
);
22735 vex_printf( "dis_vvec_cmp(ppc)(opc2)\n" );
22741 * Miscellaneous VSX Scalar Instructions
22744 dis_load_vector_special( UInt prefix
, UInt theInstr
,
22745 const VexAbiInfo
* vbi
, UInt opc2
, int allow_isa_3_0
)
22747 UChar opc1
= ifieldOPC( theInstr
);
22748 UChar XT
= ifieldRegXT ( theInstr
);
22749 UInt uim
= IFIELD( theInstr
, 11, 5 ); // inst[16:20]
22751 if (opc1
!= 0x3C) {
22752 vex_printf( "dis_load_special(ppc)(instr)\n" );
22756 DIP("lxvkq v%u,%u\n", (UInt
)XT
, uim
);
22759 case 0b00001: putVSReg( XT
, binop( Iop_64HLtoV128
,
22760 mkU64( 0x3FFF000000000000 ),
22761 mkU64( 0x0000000000000000 ) ) );
22763 case 0b00010: putVSReg( XT
, binop( Iop_64HLtoV128
,
22764 mkU64( 0x4000000000000000 ),
22765 mkU64( 0x0000000000000000 ) ) );
22767 case 0b00011: putVSReg( XT
, binop( Iop_64HLtoV128
,
22768 mkU64( 0x4000800000000000 ),
22769 mkU64( 0x0000000000000000 ) ) );
22771 case 0b00100: putVSReg( XT
, binop( Iop_64HLtoV128
,
22772 mkU64( 0x4001000000000000 ),
22773 mkU64( 0x0000000000000000 ) ) );
22775 case 0b00101: putVSReg( XT
, binop( Iop_64HLtoV128
,
22776 mkU64( 0x4001400000000000 ),
22777 mkU64( 0x0000000000000000 ) ) );
22779 case 0b00110: putVSReg( XT
, binop( Iop_64HLtoV128
,
22780 mkU64( 0x4001800000000000 ),
22781 mkU64( 0x0000000000000000 ) ) );
22783 case 0b00111: putVSReg( XT
, binop( Iop_64HLtoV128
,
22784 mkU64( 0x4001C00000000000 ),
22785 mkU64( 0x0000000000000000 ) ) );
22787 case 0b01000: putVSReg( XT
, binop( Iop_64HLtoV128
,
22788 mkU64( 0x7FFF000000000000 ),
22789 mkU64( 0x0000000000000000 ) ) );
22791 case 0b01001: putVSReg( XT
, binop( Iop_64HLtoV128
,
22792 mkU64( 0x7FFF800000000000 ),
22793 mkU64( 0x0000000000000000 ) ) );
22795 case 0b10000: putVSReg( XT
, binop( Iop_64HLtoV128
,
22796 mkU64( 0x8000000000000000 ),
22797 mkU64( 0x0000000000000000 ) ) );
22799 case 0b10001: putVSReg( XT
, binop( Iop_64HLtoV128
,
22800 mkU64( 0xBFFF000000000000 ),
22801 mkU64( 0x0000000000000000 ) ) );
22803 case 0b10010: putVSReg( XT
, binop( Iop_64HLtoV128
,
22804 mkU64( 0xC000000000000000 ),
22805 mkU64( 0x0000000000000000 ) ) );
22807 case 0b10011: putVSReg( XT
, binop( Iop_64HLtoV128
,
22808 mkU64( 0xC000800000000000 ),
22809 mkU64( 0x0000000000000000 ) ) );
22811 case 0b10100: putVSReg( XT
, binop( Iop_64HLtoV128
,
22812 mkU64( 0xC001000000000000 ),
22813 mkU64( 0x0000000000000000 ) ) );
22815 case 0b10101: putVSReg( XT
, binop( Iop_64HLtoV128
,
22816 mkU64( 0xC001400000000000 ),
22817 mkU64( 0x0000000000000000 ) ) );
22819 case 0b10110: putVSReg( XT
, binop( Iop_64HLtoV128
,
22820 mkU64( 0xC001800000000000 ),
22821 mkU64( 0x0000000000000000 ) ) );
22823 case 0b10111: putVSReg( XT
, binop( Iop_64HLtoV128
,
22824 mkU64( 0xC001C00000000000 ),
22825 mkU64( 0x0000000000000000 ) ) );
22827 case 0b11000: putVSReg( XT
, binop( Iop_64HLtoV128
,
22828 mkU64( 0xFFFF000000000000 ),
22829 mkU64( 0x0000000000000000 ) ) );
22831 default: vex_printf( "dis_load_special(ppc)(lxvkq XT, UIM not valid)\n" );
22832 putVSReg( XT
, binop( Iop_64HLtoV128
,
22833 mkU64( 0x0000000000000000 ),
22834 mkU64( 0x0000000000000000 ) ) );
22835 return True
; /* print message, continue */
22841 dis_vxs_misc( UInt prefix
, UInt theInstr
, const VexAbiInfo
* vbi
, UInt opc2
,
22842 int allow_isa_3_0
)
22844 #define VG_PPC_SIGN_MASK 0x7fffffffffffffffULL
22845 /* XX3-Form and XX2-Form */
22846 UChar opc1
= ifieldOPC( theInstr
);
22847 UChar XT
= ifieldRegXT ( theInstr
);
22848 UChar XA
= ifieldRegXA ( theInstr
);
22849 UChar XB
= ifieldRegXB ( theInstr
);
22850 IRTemp vA
= newTemp( Ity_V128
);
22851 IRTemp vB
= newTemp( Ity_V128
);
22853 /* There is no prefixed version of these instructions. */
22856 if (opc1
!= 0x3C) {
22857 vex_printf( "dis_vxs_misc(ppc)(instr)\n" );
22861 assign( vA
, getVSReg( XA
) );
22862 assign( vB
, getVSReg( XB
) );
22864 /* For all the VSX move instructions, the contents of doubleword element 1
22865 * of VSX[XT] are undefined after the operation; therefore, we can simply
22866 * move the entire array element where it makes sense to do so.
22868 if (( opc2
== 0x168 ) && ( IFIELD( theInstr
, 19, 2 ) == 0 ) )
22870 /* Special case of XX1-Form with immediate value
22871 * xxspltib (VSX Vector Splat Immediate Byte)
22873 UInt uim
= IFIELD( theInstr
, 11, 8 );
22874 UInt word_value
= ( uim
<< 24 ) | ( uim
<< 16 ) | ( uim
<< 8 ) | uim
;
22876 DIP("xxspltib v%u,%u\n", (UInt
)XT
, uim
);
22877 putVSReg(XT
, binop( Iop_64HLtoV128
,
22878 binop( Iop_32HLto64
,
22879 mkU32( word_value
),
22880 mkU32( word_value
) ),
22881 binop( Iop_32HLto64
,
22882 mkU32( word_value
),
22883 mkU32( word_value
) ) ) );
22888 case 0x0ec: // xscmpexpdp (VSX Scalar Compare Exponents Double-Precision)
22890 /* Compare 64-bit data, 128-bit layout:
22891 src1[0:63] is double word, src1[64:127] is unused
22892 src2[0:63] is double word, src2[64:127] is unused
22894 IRExpr
*bit4
, *bit5
, *bit6
, *bit7
;
22895 UInt BF
= IFIELD( theInstr
, 23, 3 );
22896 IRTemp eq_lt_gt
= newTemp( Ity_I32
);
22897 IRTemp CC
= newTemp( Ity_I32
);
22898 IRTemp vA_hi
= newTemp( Ity_I64
);
22899 IRTemp vB_hi
= newTemp( Ity_I64
);
22900 IRExpr
*mask
= mkU64( 0x7FF0000000000000 );
22902 DIP("xscmpexpdp %u,v%u,v%u\n", BF
, XA
, XB
);
22904 assign( vA_hi
, unop( Iop_V128HIto64
, mkexpr( vA
) ) );
22905 assign( vB_hi
, unop( Iop_V128HIto64
, mkexpr( vB
) ) );
22907 /* A exp < B exp */
22908 bit4
= binop( Iop_CmpLT64U
,
22915 /* A exp > B exp */
22916 bit5
= binop( Iop_CmpLT64U
,
22924 bit6
= binop( Iop_CmpEQ64
,
22932 /* exp A or exp B is NaN */
22933 bit7
= mkOR1( is_NaN( Ity_I64
, vA_hi
),
22934 is_NaN( Ity_I64
, vB_hi
) );
22936 assign( eq_lt_gt
, binop( Iop_Or32
,
22938 unop( Iop_1Uto32
, bit4
),
22942 unop( Iop_1Uto32
, bit5
),
22945 unop( Iop_1Uto32
, bit6
),
22947 assign(CC
, binop( Iop_Or32
,
22949 mkexpr( eq_lt_gt
) ,
22950 unop( Iop_Not32
, unop( Iop_1Sto32
, bit7
) ) ),
22951 unop( Iop_1Uto32
, bit7
) ) );
22953 putGST_field( PPC_GST_CR
, mkexpr( CC
), BF
);
22954 putFPCC( mkexpr( CC
) );
22959 case 0x14A: // xxextractuw (VSX Vector Extract Unsigned Word)
22961 UInt uim
= IFIELD( theInstr
, 16, 4 );
22963 DIP("xxextractuw v%u,v%u,%u\n", (UInt
)XT
, (UInt
)XB
, uim
);
22966 binop( Iop_ShlV128
,
22967 binop( Iop_AndV128
,
22968 binop( Iop_ShrV128
,
22970 mkU8( ( 12 - uim
) * 8 ) ),
22971 binop(Iop_64HLtoV128
,
22973 mkU64( 0xFFFFFFFF ) ) ),
22974 mkU8( ( 32*2 ) ) ) );
22977 case 0x16A: // xxinsertw (VSX Vector insert Word)
22979 UInt uim
= IFIELD( theInstr
, 16, 4 );
22980 IRTemp vT
= newTemp( Ity_V128
);
22981 IRTemp tmp
= newTemp( Ity_V128
);
22983 DIP("xxinsertw v%u,v%u,%u\n", (UInt
)XT
, (UInt
)XB
, uim
);
22985 assign( vT
, getVSReg( XT
) );
22986 assign( tmp
, binop( Iop_AndV128
,
22989 binop( Iop_ShlV128
,
22990 binop( Iop_64HLtoV128
,
22992 mkU64( 0xFFFFFFFF) ),
22993 mkU8( ( 12 - uim
) * 8 ) ) ) ) );
22997 binop( Iop_ShlV128
,
22998 binop( Iop_AndV128
,
22999 binop( Iop_ShrV128
,
23002 binop( Iop_64HLtoV128
,
23004 mkU64( 0xFFFFFFFF ) ) ),
23005 mkU8( ( 12 - uim
) * 8 ) ),
23010 case 0x2B2: // xsabsdp (VSX scalar absolute value double-precision
23012 /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */
23013 IRTemp absVal
= newTemp(Ity_V128
);
23014 if (host_endness
== VexEndnessLE
) {
23015 IRTemp hi64
= newTemp(Ity_I64
);
23016 IRTemp lo64
= newTemp(Ity_I64
);
23017 assign( hi64
, unop( Iop_V128HIto64
, mkexpr(vB
) ) );
23018 assign( lo64
, unop( Iop_V128to64
, mkexpr(vB
) ) );
23019 assign( absVal
, binop( Iop_64HLtoV128
,
23020 binop( Iop_And64
, mkexpr(hi64
),
23021 mkU64(VG_PPC_SIGN_MASK
) ),
23024 assign(absVal
, binop(Iop_ShrV128
,
23025 binop(Iop_ShlV128
, mkexpr(vB
),
23026 mkU8(1)), mkU8(1)));
23028 DIP("xsabsdp v%u,v%u\n", XT
, XB
);
23029 putVSReg(XT
, mkexpr(absVal
));
23033 case 0x2b6: // xsxexpdp (VSX Scalar Extract Exponent Double-Precision)
23034 // xsxsigdp (VSX Scalar Extract Significand Doulbe-Precision)
23035 // xsvhpdp (VSX Scalar Convert Half-Precision format
23036 // to Double-Precision format)
23037 // xscvdphp (VSX Scalar round & convert Double-precision
23038 // format to Half-precision format)
23040 IRTemp rT
= newTemp( Ity_I64
);
23041 UInt inst_select
= IFIELD( theInstr
, 16, 5);
23043 if (inst_select
== 0) {
23044 DIP("xsxexpd %u,v%u\n", (UInt
)XT
, (UInt
)XB
);
23046 assign( rT
, binop( Iop_Shr64
,
23048 unop( Iop_V128HIto64
, mkexpr( vB
) ),
23049 mkU64( 0x7FF0000000000000 ) ),
23051 } else if (inst_select
== 1) {
23053 IRTemp tmp
= newTemp(Ity_I64
);
23055 DIP("xsxsigdp v%u,v%u\n", (UInt
)XT
, (UInt
)XB
);
23057 assign( tmp
, unop( Iop_V128HIto64
, mkexpr( vB
) ) );
23059 /* Value is normal if it isn't infinite, zero or denormalized */
23060 normal
= mkNOT1( mkOR1(
23061 mkOR1( is_NaN( Ity_I64
, tmp
),
23062 is_Inf( Ity_I64
, tmp
) ),
23063 mkOR1( is_Zero( Ity_I64
, tmp
),
23064 is_Denorm( Ity_I64
, tmp
) ) ) );
23066 assign( rT
, binop( Iop_Or64
,
23069 mkU64( 0xFFFFFFFFFFFFF ) ),
23071 unop( Iop_1Uto64
, normal
),
23073 putIReg( XT
, mkexpr( rT
) );
23075 } else if (inst_select
== 16) {
23076 IRTemp result
= newTemp( Ity_V128
);
23077 IRTemp value
= newTemp( Ity_I64
);
23078 /* Note: PPC only coverts the 16-bit value in the upper 64-bits
23079 * of the source V128 to a 64-bit value stored in the upper
23080 * 64-bits of the V128 result. The contents of the lower 64-bits
23084 DIP("xscvhpdp v%u, v%u\n", (UInt
)XT
, (UInt
)XB
);
23085 assign( result
, unop( Iop_F16toF64x2
, mkexpr( vB
) ) );
23087 putVSReg( XT
, mkexpr( result
) );
23089 assign( value
, unop( Iop_V128HIto64
, mkexpr( result
) ) );
23090 generate_store_FPRF( Ity_I64
, value
, vbi
);
23093 } else if (inst_select
== 17) { // xscvdphp
23094 IRTemp value
= newTemp( Ity_I32
);
23095 IRTemp result
= newTemp( Ity_V128
);
23096 /* Note: PPC only coverts the 64-bit value in the upper 64-bits of
23097 * the V128 and stores the 16-bit result in the upper word of the
23098 * V128 result. The contents of the lower 64-bits is undefined.
23100 DIP("xscvdphp v%u, v%u\n", (UInt
)XT
, (UInt
)XB
);
23101 assign( result
, unop( Iop_F64toF16x2_DEP
, mkexpr( vB
) ) );
23102 assign( value
, unop( Iop_64to32
, unop( Iop_V128HIto64
,
23103 mkexpr( result
) ) ) );
23104 putVSReg( XT
, mkexpr( result
) );
23105 generate_store_FPRF( Ity_I16
, value
, vbi
);
23109 vex_printf( "dis_vxv_scalar_extract_exp_sig invalid inst_select (ppc)(opc2)\n" );
23110 vex_printf("inst_select = %u\n", inst_select
);
23116 case 0x254: // xststdcsp (VSX Scalar Test Data Class Single-Precision)
23117 case 0x2D4: // xststdcdp (VSX Scalar Test Data Class Double-Precision)
23119 /* These instructions only differ in that the single precision
23120 instruction, xststdcsp, has the additional constraint on the
23121 denormal test that the exponent be greater then zero and
23122 less then 0x381. */
23123 IRTemp vB_hi
= newTemp( Ity_I64
);
23124 UInt BF
= IFIELD( theInstr
, 23, 3 );
23125 UInt DCMX_mask
= IFIELD( theInstr
, 16, 7 );
23126 IRTemp NaN
= newTemp( Ity_I64
);
23127 IRTemp inf
= newTemp( Ity_I64
);
23128 IRTemp zero
= newTemp( Ity_I64
);
23129 IRTemp dnorm
= newTemp( Ity_I64
);
23130 IRTemp pos
= newTemp( Ity_I64
);
23131 IRTemp not_sp
= newTemp( Ity_I64
);
23132 IRTemp DCM
= newTemp( Ity_I64
);
23133 IRTemp CC
= newTemp( Ity_I64
);
23134 IRTemp exponent
= newTemp( Ity_I64
);
23135 IRTemp tmp
= newTemp( Ity_I64
);
23137 assign( vB_hi
, unop( Iop_V128HIto64
, mkexpr( vB
) ) );
23139 assign( pos
, unop( Iop_1Uto64
,
23140 binop( Iop_CmpEQ64
,
23146 assign( NaN
, unop( Iop_1Uto64
, is_NaN( Ity_I64
, vB_hi
) ) );
23147 assign( inf
, unop( Iop_1Uto64
, is_Inf( Ity_I64
, vB_hi
) ) );
23148 assign( zero
, unop( Iop_1Uto64
, is_Zero( Ity_I64
, vB_hi
) ) );
23150 if (opc2
== 0x254) {
23151 DIP("xststdcsp %u,v%u,%u\n", BF
, (UInt
)XB
, DCMX_mask
);
23153 /* The least significant bit of the CC is set to 1 if the double
23154 precision value is not representable as a single precision
23155 value. The spec says the bit is set if:
23156 src != convert_SPtoDP(convert_DPtoSP(src))
23159 unop( Iop_ReinterpF64asI64
,
23160 unop( Iop_F32toF64
,
23161 unop( Iop_TruncF64asF32
,
23162 unop( Iop_ReinterpI64asF64
,
23163 mkexpr( vB_hi
) ) ) ) ) );
23164 assign( not_sp
, unop( Iop_1Uto64
,
23165 mkNOT1( binop( Iop_CmpEQ64
,
23167 mkexpr( tmp
) ) ) ) );
23172 mkU64( 0x7ff0000000000000 ) ),
23174 assign( dnorm
, unop( Iop_1Uto64
,
23175 mkOR1( is_Denorm( Ity_I64
, vB_hi
),
23176 mkAND1( binop( Iop_CmpLT64U
,
23177 mkexpr( exponent
),
23179 binop( Iop_CmpNE64
,
23180 mkexpr( exponent
),
23181 mkU64( 0x0 ) ) ) ) ) );
23184 DIP("xststdcdp %u,v%u,%u\n", BF
, (UInt
)XB
, DCMX_mask
);
23185 assign( not_sp
, mkU64( 0 ) );
23186 assign( dnorm
, unop( Iop_1Uto64
, is_Denorm( Ity_I64
, vB_hi
) ) );
23189 assign( DCM
, create_DCM( Ity_I64
, NaN
, inf
, zero
, dnorm
, pos
) );
23192 binop( Iop_And64
, /* vB sign bit */
23200 binop( Iop_CmpNE64
,
23203 mkU64( DCMX_mask
) ),
23206 mkexpr( not_sp
) ) ) );
23207 putGST_field( PPC_GST_CR
, unop( Iop_64to32
, mkexpr( CC
) ), BF
);
23208 putFPCC( unop( Iop_64to32
, mkexpr( CC
) ) );
23212 case 0x2C0: // xscpsgndp
23214 /* Scalar copy sign double-precision */
23215 IRTemp vecA_signed
= newTemp(Ity_I64
);
23216 IRTemp vecB_unsigned
= newTemp(Ity_I64
);
23217 IRTemp vec_result
= newTemp(Ity_V128
);
23218 DIP("xscpsgndp v%d,v%d v%d\n", XT
, XA
, XB
);
23219 assign( vecA_signed
, binop( Iop_And64
,
23220 unop( Iop_V128HIto64
,
23222 mkU64(~VG_PPC_SIGN_MASK
) ) );
23223 assign( vecB_unsigned
, binop( Iop_And64
,
23224 unop( Iop_V128HIto64
,
23226 mkU64(VG_PPC_SIGN_MASK
) ) );
23227 assign( vec_result
, binop( Iop_64HLtoV128
,
23229 mkexpr(vecA_signed
),
23230 mkexpr(vecB_unsigned
) ),
23232 putVSReg(XT
, mkexpr(vec_result
));
23235 case 0x2D2: // xsnabsdp
23237 /* Scalar negative absolute value double-precision */
23238 IRTemp BHi_signed
= newTemp(Ity_I64
);
23239 DIP("xsnabsdp v%d,v%d\n", XT
, XB
);
23240 assign( BHi_signed
, binop( Iop_Or64
,
23241 unop( Iop_V128HIto64
,
23243 mkU64(~VG_PPC_SIGN_MASK
) ) );
23244 putVSReg(XT
, binop( Iop_64HLtoV128
,
23245 mkexpr(BHi_signed
), mkU64(0x0ULL
) ) );
23248 case 0x2F2: // xsnegdp
23250 /* Scalar negate double-precision */
23251 IRTemp BHi_signed
= newTemp(Ity_I64
);
23252 IRTemp BHi_unsigned
= newTemp(Ity_I64
);
23253 IRTemp BHi_negated
= newTemp(Ity_I64
);
23254 IRTemp BHi_negated_signbit
= newTemp(Ity_I1
);
23255 IRTemp vec_result
= newTemp(Ity_V128
);
23256 DIP("xsnabsdp v%d,v%d\n", XT
, XB
);
23257 assign( BHi_signed
, unop( Iop_V128HIto64
, mkexpr(vB
) ) );
23258 assign( BHi_unsigned
, binop( Iop_And64
, mkexpr(BHi_signed
),
23259 mkU64(VG_PPC_SIGN_MASK
) ) );
23260 assign( BHi_negated_signbit
,
23264 unop( Iop_64HIto32
,
23266 mkexpr(BHi_signed
),
23267 mkU64(~VG_PPC_SIGN_MASK
) )
23270 assign( BHi_negated
,
23272 binop( Iop_32HLto64
,
23275 mkexpr(BHi_negated_signbit
) ),
23278 mkexpr(BHi_unsigned
) ) );
23279 assign( vec_result
, binop( Iop_64HLtoV128
, mkexpr(BHi_negated
),
23281 putVSReg( XT
, mkexpr(vec_result
));
23284 case 0x280: // xsmaxdp (VSX Scalar Maximum Double-Precision)
23285 case 0x2A0: // xsmindp (VSX Scalar Minimum Double-Precision)
23287 IRTemp frA
= newTemp(Ity_I64
);
23288 IRTemp frB
= newTemp(Ity_I64
);
23289 Bool isMin
= opc2
== 0x2A0 ? True
: False
;
23290 DIP("%s v%d,v%d v%d\n", isMin
? "xsmaxdp" : "xsmindp", XT
, XA
, XB
);
23292 assign(frA
, unop(Iop_V128HIto64
, mkexpr( vA
)));
23293 assign(frB
, unop(Iop_V128HIto64
, mkexpr( vB
)));
23294 putVSReg( XT
, binop( Iop_64HLtoV128
, get_max_min_fp(frA
, frB
, isMin
), mkU64( 0 ) ) );
23298 case 0x0F2: // xsrdpim (VSX Scalar Round to Double-Precision Integer using round toward -Infinity)
23299 case 0x0D2: // xsrdpip (VSX Scalar Round to Double-Precision Integer using round toward +Infinity)
23300 case 0x0D6: // xsrdpic (VSX Scalar Round to Double-Precision Integer using Current rounding mode)
23301 case 0x0B2: // xsrdpiz (VSX Scalar Round to Double-Precision Integer using round toward Zero)
23302 case 0x092: // xsrdpi (VSX Scalar Round to Double-Precision Integer using round toward Nearest Away)
23304 IRTemp frB_I64
= newTemp(Ity_I64
);
23305 IRExpr
* frD_fp_round
= NULL
;
23307 assign(frB_I64
, unop(Iop_V128HIto64
, mkexpr( vB
)));
23308 frD_fp_round
= _do_vsx_fp_roundToInt(frB_I64
, opc2
);
23310 DIP("xsrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2
), XT
, XB
);
23312 binop( Iop_64HLtoV128
,
23313 unop( Iop_ReinterpF64asI64
, frD_fp_round
),
23317 case 0x034: // xsresp (VSX Scalar Reciprocal Estimate single-Precision)
23318 case 0x014: /* xsrsqrtesp (VSX Scalar Reciprocal Square Root Estimate
23319 * single-Precision)
23322 IRTemp frB
= newTemp(Ity_F64
);
23323 IRTemp sqrt
= newTemp(Ity_F64
);
23324 IRExpr
* ieee_one
= IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL
));
23325 IRExpr
* rm
= get_IR_roundingmode();
23326 Bool redp
= opc2
== 0x034;
23327 DIP("%s v%d,v%d\n", redp
? "xsresp" : "xsrsqrtesp", XT
,
23331 unop( Iop_ReinterpI64asF64
,
23332 unop( Iop_V128HIto64
, mkexpr( vB
) ) ) );
23336 binop( Iop_SqrtF64
,
23340 binop( Iop_64HLtoV128
,
23341 unop( Iop_ReinterpF64asI64
,
23342 binop( Iop_RoundF64toF32
, rm
,
23346 redp
? mkexpr( frB
) :
23347 mkexpr( sqrt
) ) ) ),
23352 case 0x0B4: // xsredp (VSX Scalar Reciprocal Estimate Double-Precision)
23353 case 0x094: // xsrsqrtedp (VSX Scalar Reciprocal Square Root Estimate Double-Precision)
23356 IRTemp frB
= newTemp(Ity_F64
);
23357 IRTemp sqrt
= newTemp(Ity_F64
);
23358 IRExpr
* ieee_one
= IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL
));
23359 IRExpr
* rm
= get_IR_roundingmode();
23360 Bool redp
= opc2
== 0x0B4;
23361 DIP("%s v%d,v%d\n", redp
? "xsredp" : "xsrsqrtedp", XT
, XB
);
23363 unop( Iop_ReinterpI64asF64
,
23364 unop( Iop_V128HIto64
, mkexpr( vB
) ) ) );
23368 binop( Iop_SqrtF64
,
23372 binop( Iop_64HLtoV128
,
23373 unop( Iop_ReinterpF64asI64
,
23377 redp
? mkexpr( frB
) : mkexpr( sqrt
) ) ),
23382 case 0x232: // xsrsp (VSX Scalar Round to Single-Precision)
23384 IRTemp frB
= newTemp(Ity_F64
);
23385 IRExpr
* rm
= get_IR_roundingmode();
23386 DIP("xsrsp v%d, v%d\n", XT
, XB
);
23388 unop( Iop_ReinterpI64asF64
,
23389 unop( Iop_V128HIto64
, mkexpr( vB
) ) ) );
23391 putVSReg( XT
, binop( Iop_64HLtoV128
,
23392 unop( Iop_ReinterpF64asI64
,
23393 binop( Iop_RoundF64toF32
,
23400 case 0x354: // xvtstdcsp (VSX Test Data Class Single-Precision)
23402 UInt DX_mask
= IFIELD( theInstr
, 16, 5 );
23403 UInt DC_mask
= IFIELD( theInstr
, 6, 1 );
23404 UInt DM_mask
= IFIELD( theInstr
, 2, 1 );
23405 UInt DCMX_mask
= (DC_mask
<< 6) | (DM_mask
<< 5) | DX_mask
;
23407 IRTemp match_value
[4];
23417 DIP("xvtstdcsp v%u,v%u,%u\n", (UInt
)XT
, (UInt
)XB
, DCMX_mask
);
23419 for (i
= 0; i
< 4; i
++) {
23420 NaN
[i
] = newTemp(Ity_I32
);
23421 inf
[i
] = newTemp(Ity_I32
);
23422 pos
[i
] = newTemp(Ity_I32
);
23423 DCM
[i
] = newTemp(Ity_I32
);
23424 zero
[i
] = newTemp(Ity_I32
);
23425 dnorm
[i
] = newTemp(Ity_I32
);
23427 value
[i
] = newTemp(Ity_I32
);
23428 match_value
[i
] = newTemp(Ity_I32
);
23432 unop( Iop_V128to64
,
23433 binop( Iop_AndV128
,
23434 binop( Iop_ShrV128
,
23436 mkU8( (3-i
)*32 ) ),
23437 binop( Iop_64HLtoV128
,
23439 mkU64( 0xFFFFFFFF ) ) ) ) ) );
23441 assign( pos
[i
], unop( Iop_1Uto32
,
23442 binop( Iop_CmpEQ32
,
23444 mkexpr( value
[i
] ),
23448 assign( NaN
[i
], unop( Iop_1Uto32
, is_NaN( Ity_I32
, value
[i
] ) ));
23449 assign( inf
[i
], unop( Iop_1Uto32
, is_Inf( Ity_I32
, value
[i
] ) ) );
23450 assign( zero
[i
], unop( Iop_1Uto32
, is_Zero( Ity_I32
, value
[i
] ) ) );
23452 assign( dnorm
[i
], unop( Iop_1Uto32
, is_Denorm( Ity_I32
,
23454 assign( DCM
[i
], create_DCM( Ity_I32
, NaN
[i
], inf
[i
], zero
[i
],
23455 dnorm
[i
], pos
[i
] ) );
23457 assign( match_value
[i
],
23459 binop( Iop_CmpNE32
,
23461 mkU32( DCMX_mask
),
23462 mkexpr( DCM
[i
] ) ),
23466 putVSReg( XT
, binop( Iop_64HLtoV128
,
23467 binop( Iop_32HLto64
,
23468 mkexpr( match_value
[0] ),
23469 mkexpr( match_value
[1] ) ),
23470 binop( Iop_32HLto64
,
23471 mkexpr( match_value
[2] ),
23472 mkexpr( match_value
[3] ) ) ) );
23476 case 0x360: // xviexpsp (VSX Vector Insert Exponent Single-Precision)
23482 IRExpr
*sign
[4], *expr
[4], *fract
[4];
23484 DIP("xviexpsp v%d,v%d\n", XT
, XB
);
23485 new_XT
[0] = newTemp(Ity_V128
);
23486 assign( new_XT
[0], binop( Iop_64HLtoV128
,
23490 for (i
= 0; i
< 4; i
++) {
23491 A_value
[i
] = newTemp(Ity_I32
);
23492 B_value
[i
] = newTemp(Ity_I32
);
23494 assign( A_value
[i
],
23496 unop( Iop_V128to64
,
23497 binop( Iop_AndV128
,
23498 binop( Iop_ShrV128
,
23500 mkU8( (3-i
)*32 ) ),
23501 binop( Iop_64HLtoV128
,
23503 mkU64( 0xFFFFFFFF ) ) ) ) ) );
23504 assign( B_value
[i
],
23506 unop( Iop_V128to64
,
23507 binop( Iop_AndV128
,
23508 binop( Iop_ShrV128
,
23510 mkU8( (3-i
)*32 ) ),
23511 binop( Iop_64HLtoV128
,
23513 mkU64( 0xFFFFFFFF ) ) ) ) ) );
23515 sign
[i
] = binop( Iop_And32
, mkexpr( A_value
[i
] ),
23516 mkU32( 0x80000000 ) );
23517 expr
[i
] = binop( Iop_Shl32
,
23518 binop( Iop_And32
, mkexpr( B_value
[i
] ),
23521 fract
[i
] = binop( Iop_And32
, mkexpr( A_value
[i
] ),
23522 mkU32( 0x007FFFFF ) );
23524 new_XT
[i
+1] = newTemp(Ity_V128
);
23525 assign( new_XT
[i
+1],
23527 binop( Iop_ShlV128
,
23528 binop( Iop_64HLtoV128
,
23530 binop( Iop_32HLto64
,
23537 mkU8( (3-i
)*32 ) ),
23538 mkexpr( new_XT
[i
] ) ) );
23540 putVSReg( XT
, mkexpr( new_XT
[4] ) );
23544 case 0x396: // xsiexpdp (VSX Scalar Insert Exponent Double-Precision)
23546 IRExpr
*sign
, *expr
, *fract
;
23547 UChar rA_addr
= ifieldRegA(theInstr
);
23548 UChar rB_addr
= ifieldRegB(theInstr
);
23549 IRTemp rA
= newTemp( Ity_I64
);
23550 IRTemp rB
= newTemp( Ity_I64
);
23552 DIP("xsiexpdp v%u,%u,%u\n", (UInt
)XT
, (UInt
)rA_addr
, (UInt
)rB_addr
);
23553 assign( rA
, getIReg(rA_addr
));
23554 assign( rB
, getIReg(rB_addr
));
23556 sign
= binop( Iop_And64
, mkexpr( rA
), mkU64( 0x8000000000000000 ) );
23557 expr
= binop( Iop_Shl64
,
23558 binop( Iop_And64
, mkexpr( rB
), mkU64( 0x7FF ) ),
23560 fract
= binop( Iop_And64
, mkexpr( rA
), mkU64( 0x000FFFFFFFFFFFFF ) );
23562 putVSReg( XT
, binop( Iop_64HLtoV128
,
23564 binop( Iop_Or64
, sign
, expr
),
23570 case 0x3B6: // xvxexpdp (VSX Vector Extract Exponent Double-Precision)
23571 // xvxsigdp (VSX Vector Extract Significand Double-Precision)
23573 // xvxexpsp (VSX Vector Extract Exponent Single-Precision)
23574 // xvxsigsp (VSX Vector Extract Significand Single-Precision)
23578 // xvcvbf16spn (VSX Convert 16-bit bfloat to 32-bit float)
23579 // xvcvspbf16 (VSX Convert 32-bit float to 16-bit bfloat)
23580 // xvcvhpsp (VSX Vector Convert Half-Precision format to Single-Precision format)
23581 // xvcvsphp (VSX Vector round and convert Single-Precision format to Half-Precision format)
23583 UInt inst_select
= IFIELD( theInstr
, 16, 5);
23585 if (inst_select
== 0) {
23586 DIP("xvxexpdp v%d,v%d\n", XT
, XB
);
23588 putVSReg( XT
, binop( Iop_ShrV128
,
23589 binop( Iop_AndV128
,
23591 binop( Iop_64HLtoV128
,
23592 mkU64( 0x7FF0000000000000 ),
23593 mkU64( 0x7FF0000000000000 ) ) ),
23596 } else if (inst_select
== 1) {
23602 DIP("xvxsigdp v%d,v%d\n", XT
, XB
);
23603 new_XT
[0] = newTemp(Ity_V128
);
23604 assign( new_XT
[0], binop( Iop_64HLtoV128
,
23608 for (i
= 0; i
< 2; i
++) {
23609 value
[i
] = newTemp(Ity_I64
);
23611 unop( Iop_V128to64
,
23612 binop( Iop_AndV128
,
23613 binop( Iop_ShrV128
,
23615 mkU8( (1-i
)*64 ) ),
23616 binop( Iop_64HLtoV128
,
23618 mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ) );
23620 /* Value is normal if it isn't infinite, zero or denormalized */
23621 normal
[i
] = mkNOT1( mkOR1(
23622 mkOR1( is_NaN( Ity_I64
, value
[i
] ),
23623 is_Inf( Ity_I64
, value
[i
] ) ),
23624 mkOR1( is_Zero( Ity_I64
, value
[i
] ),
23625 is_Denorm( Ity_I64
,
23627 new_XT
[i
+1] = newTemp(Ity_V128
);
23629 assign( new_XT
[i
+1],
23631 binop( Iop_ShlV128
,
23632 binop( Iop_64HLtoV128
,
23636 mkexpr( value
[i
] ),
23637 mkU64( 0xFFFFFFFFFFFFF ) ),
23642 mkU8( (1-i
)*64 ) ),
23643 mkexpr( new_XT
[i
] ) ) );
23645 putVSReg( XT
, mkexpr( new_XT
[2] ) );
23647 } else if (inst_select
== 7) {
23648 IRTemp sub_element0
= newTemp( Ity_V128
);
23649 IRTemp sub_element1
= newTemp( Ity_V128
);
23651 DIP("xxbrh v%u, v%u\n", (UInt
)XT
, (UInt
)XB
);
23653 assign( sub_element0
,
23654 binop( Iop_ShrV128
,
23655 binop( Iop_AndV128
,
23656 binop(Iop_64HLtoV128
,
23657 mkU64( 0xFF00FF00FF00FF00 ),
23658 mkU64( 0xFF00FF00FF00FF00 ) ),
23661 assign( sub_element1
,
23662 binop( Iop_ShlV128
,
23663 binop( Iop_AndV128
,
23664 binop(Iop_64HLtoV128
,
23665 mkU64( 0x00FF00FF00FF00FF ),
23666 mkU64( 0x00FF00FF00FF00FF ) ),
23670 putVSReg(XT
, binop( Iop_OrV128
,
23671 mkexpr( sub_element1
),
23672 mkexpr( sub_element0
) ) );
23674 } else if (inst_select
== 8) {
23675 DIP("xvxexpsp v%d,v%d\n", XT
, XB
);
23677 putVSReg( XT
, binop( Iop_ShrV128
,
23678 binop( Iop_AndV128
,
23680 binop( Iop_64HLtoV128
,
23681 mkU64( 0x7F8000007F800000 ),
23682 mkU64( 0x7F8000007F800000 ) ) ),
23684 } else if (inst_select
== 9) {
23688 IRTemp new_value
[4];
23691 DIP("xvxsigsp v%d,v%d\n", XT
, XB
);
23692 new_XT
[0] = newTemp(Ity_V128
);
23693 assign( new_XT
[0], binop( Iop_64HLtoV128
,
23697 for (i
= 0; i
< 4; i
++) {
23698 value
[i
] = newTemp(Ity_I32
);
23701 unop( Iop_V128to64
,
23702 binop( Iop_AndV128
,
23703 binop( Iop_ShrV128
,
23705 mkU8( (3-i
)*32 ) ),
23706 binop( Iop_64HLtoV128
,
23708 mkU64( 0xFFFFFFFF ) ) ) ) ) );
23710 new_XT
[i
+1] = newTemp(Ity_V128
);
23712 /* Value is normal if it isn't infinite, zero or denormalized */
23713 normal
[i
] = mkNOT1( mkOR1(
23714 mkOR1( is_NaN( Ity_I32
, value
[i
] ),
23715 is_Inf( Ity_I32
, value
[i
] ) ),
23716 mkOR1( is_Zero( Ity_I32
, value
[i
] ),
23717 is_Denorm( Ity_I32
,
23719 new_value
[i
] = newTemp(Ity_I32
);
23720 assign( new_value
[i
],
23723 mkexpr( value
[i
] ),
23724 mkU32( 0x7FFFFF ) ),
23730 assign( new_XT
[i
+1],
23732 binop( Iop_ShlV128
,
23733 binop( Iop_64HLtoV128
,
23735 binop( Iop_32HLto64
,
23737 mkexpr( new_value
[i
] ) ) ),
23738 mkU8( (3-i
)*32 ) ),
23739 mkexpr( new_XT
[i
] ) ) );
23741 putVSReg( XT
, mkexpr( new_XT
[4] ) );
23743 } else if (inst_select
== 15) {
23744 IRTemp sub_element0
= newTemp( Ity_V128
);
23745 IRTemp sub_element1
= newTemp( Ity_V128
);
23746 IRTemp sub_element2
= newTemp( Ity_V128
);
23747 IRTemp sub_element3
= newTemp( Ity_V128
);
23749 DIP("xxbrw v%u, v%u\n", (UInt
)XT
, (UInt
)XB
);
23751 assign( sub_element0
,
23752 binop( Iop_ShrV128
,
23753 binop( Iop_AndV128
,
23754 binop(Iop_64HLtoV128
,
23755 mkU64( 0xFF000000FF000000 ),
23756 mkU64( 0xFF000000FF000000 ) ),
23759 assign( sub_element1
,
23760 binop( Iop_ShrV128
,
23761 binop( Iop_AndV128
,
23762 binop(Iop_64HLtoV128
,
23763 mkU64( 0x00FF000000FF0000 ),
23764 mkU64( 0x00FF000000FF0000 ) ),
23767 assign( sub_element2
,
23768 binop( Iop_ShlV128
,
23769 binop( Iop_AndV128
,
23770 binop(Iop_64HLtoV128
,
23771 mkU64( 0x0000FF000000FF00 ),
23772 mkU64( 0x0000FF000000FF00 ) ),
23775 assign( sub_element3
,
23776 binop( Iop_ShlV128
,
23777 binop( Iop_AndV128
,
23778 binop(Iop_64HLtoV128
,
23779 mkU64( 0x00000000FF000000FF ),
23780 mkU64( 0x00000000FF000000FF ) ),
23787 mkexpr( sub_element3
),
23788 mkexpr( sub_element2
) ),
23790 mkexpr( sub_element1
),
23791 mkexpr( sub_element0
) ) ) );
23793 } else if ((inst_select
== 16) && !prefix
) {
23794 IRTemp result
= newTemp(Ity_V128
);
23795 UChar xT_addr
= ifieldRegXT ( theInstr
);
23796 UChar xB_addr
= ifieldRegXB ( theInstr
);
23797 /* Convert 16-bit bfloat to 32-bit float, not a prefix inst */
23798 DIP("xvcvbf16spn v%u,v%u\n", xT_addr
, xB_addr
);
23799 assign( result
, vector_convert_bf16tofloat( vbi
, mkexpr( vB
) ) );
23800 putVSReg( XT
, mkexpr( result
) );
23802 } else if ((inst_select
== 17) && !prefix
) {
23803 IRTemp result
= newTemp(Ity_V128
);
23804 UChar xT_addr
= ifieldRegXT ( theInstr
);
23805 UChar xB_addr
= ifieldRegXB ( theInstr
);
23806 /* Convert 32-bit float to 16-bit bfloat, not a prefix inst */
23807 DIP("xvcvspbf16 v%u,v%u\n", xT_addr
, xB_addr
);
23808 assign( result
, vector_convert_floattobf16( vbi
, mkexpr( vB
) ) );
23809 putVSReg( XT
, mkexpr( result
) );
23811 } else if (inst_select
== 23) {
23812 DIP("xxbrd v%u, v%u\n", (UInt
)XT
, (UInt
)XB
);
23816 IRTemp sub_element
[16];
23819 new_xT
[0] = newTemp( Ity_V128
);
23820 assign( new_xT
[0], binop( Iop_64HLtoV128
,
23824 for ( i
= 0; i
< 4; i
++ ) {
23825 new_xT
[i
+1] = newTemp( Ity_V128
);
23826 sub_element
[i
] = newTemp( Ity_V128
);
23827 sub_element
[i
+4] = newTemp( Ity_V128
);
23829 assign( sub_element
[i
],
23830 binop( Iop_ShrV128
,
23831 binop( Iop_AndV128
,
23832 binop( Iop_64HLtoV128
,
23833 mkU64( (0xFFULL
<< (7 - i
) * 8) ),
23834 mkU64( (0xFFULL
<< (7 - i
) * 8) ) ),
23838 assign( sub_element
[i
+4],
23839 binop( Iop_ShlV128
,
23840 binop( Iop_AndV128
,
23841 binop( Iop_64HLtoV128
,
23842 mkU64( (0xFFULL
<< i
*8) ),
23843 mkU64( (0xFFULL
<< i
*8) ) ),
23846 shift
= shift
- 16;
23848 assign( new_xT
[i
+1],
23850 mkexpr( new_xT
[i
] ),
23852 mkexpr ( sub_element
[i
] ),
23853 mkexpr ( sub_element
[i
+4] ) ) ) );
23856 putVSReg( XT
, mkexpr( new_xT
[4] ) );
23858 } else if (inst_select
== 24) {
23859 // xvcvhpsp, (VSX Vector Convert half-precision format to
23860 // Single-precision format)
23861 /* only supported on ISA 3.0 and newer */
23862 IRTemp result
= newTemp( Ity_V128
);
23863 IRTemp src
= newTemp( Ity_I64
);
23865 if (!allow_isa_3_0
) return False
;
23867 DIP("xvcvhpsp v%d,v%d\n", XT
,XB
);
23868 /* The instruction does not set the C or FPCC fields. The
23869 * instruction takes four 16-bit values stored in a 128-bit value
23870 * as follows: x V | x V | x V | x V where V is a 16-bit
23871 * value and x is an unused 16-bit value. To use Iop_F16toF32x4
23872 * the four 16-bit values will be gathered into a single 64 bit
23873 * value. The backend will scatter the four 16-bit values back
23874 * into a 128-bit operand before issuing the instruction.
23876 /* Gather 16-bit float values from V128 source into new 64-bit
23877 * source value for the Iop.
23880 unop( Iop_V128to64
,
23881 binop( Iop_Perm8x16
,
23883 binop ( Iop_64HLtoV128
,
23885 mkU64( 0x020306070A0B0E0F) ) ) ) );
23887 assign( result
, unop( Iop_F16toF32x4
, mkexpr( src
) ) );
23889 putVSReg( XT
, mkexpr( result
) );
23891 } else if (inst_select
== 25) {
23892 // xvcvsphp, (VSX Vector round and Convert single-precision
23893 // format to half-precision format)
23894 /* only supported on ISA 3.0 and newer */
23895 IRTemp result
= newTemp( Ity_V128
);
23896 IRTemp tmp64
= newTemp( Ity_I64
);
23898 if (!allow_isa_3_0
) return False
;
23899 DIP("xvcvsphp v%d,v%d\n", XT
,XB
);
23901 /* Iop_F32toF16x4 is V128 -> I64, scatter the 16-bit floats in the
23902 * I64 result to the V128 register to store.
23904 assign( tmp64
, unop( Iop_F32toF16x4_DEP
, mkexpr( vB
) ) );
23906 /* Scatter 16-bit float values from returned 64-bit value
23909 if (host_endness
== VexEndnessLE
)
23910 /* Note location 0 may have a valid number in it. Location
23911 * 15 should always be zero. Use 0xF to put zeros in the
23915 binop( Iop_Perm8x16
,
23916 binop( Iop_64HLtoV128
,
23919 binop ( Iop_64HLtoV128
,
23920 mkU64( 0x0F0F00010F0F0203 ),
23921 mkU64( 0x0F0F04050F0F0607 ) ) ) );
23924 binop( Iop_Perm8x16
,
23925 binop( Iop_64HLtoV128
,
23928 binop ( Iop_64HLtoV128
,
23929 mkU64( 0x0F0F06070F0F0405 ),
23930 mkU64( 0x0F0F02030F0F0001 ) ) ) );
23931 putVSReg( XT
, mkexpr( result
) );
23933 } else if ( inst_select
== 31 ) {
23935 int shift_left
= 8;
23936 int shift_right
= 120;
23937 IRTemp sub_element
[16];
23940 DIP("xxbrq v%u, v%u\n", (UInt
) XT
, (UInt
) XB
);
23942 new_xT
[0] = newTemp( Ity_V128
);
23943 assign( new_xT
[0], binop( Iop_64HLtoV128
,
23947 for ( i
= 0; i
< 8; i
++ ) {
23948 new_xT
[i
+1] = newTemp( Ity_V128
);
23949 sub_element
[i
] = newTemp( Ity_V128
);
23950 sub_element
[i
+8] = newTemp( Ity_V128
);
23952 assign( sub_element
[i
],
23953 binop( Iop_ShrV128
,
23954 binop( Iop_AndV128
,
23955 binop( Iop_64HLtoV128
,
23956 mkU64( ( 0xFFULL
<< (7 - i
) * 8 ) ),
23959 mkU8( shift_right
) ) );
23960 shift_right
= shift_right
- 16;
23962 assign( sub_element
[i
+8],
23963 binop( Iop_ShlV128
,
23964 binop( Iop_AndV128
,
23965 binop( Iop_64HLtoV128
,
23967 mkU64( ( 0xFFULL
<< (7 - i
) * 8 ) ) ),
23969 mkU8( shift_left
) ) );
23970 shift_left
= shift_left
+ 16;
23972 assign( new_xT
[i
+1],
23974 mkexpr( new_xT
[i
] ),
23976 mkexpr ( sub_element
[i
] ),
23977 mkexpr ( sub_element
[i
+8] ) ) ) );
23980 putVSReg( XT
, mkexpr( new_xT
[8] ) );
23983 vex_printf("dis_vxs_misc(ppc) Invalid instruction selection\n");
23989 case 0x3D4: // xvtstdcdp (VSX Test Data Class Double-Precision)
23991 UInt DX_mask
= IFIELD( theInstr
, 16, 5 );
23992 UInt DC_mask
= IFIELD( theInstr
, 6, 1 );
23993 UInt DM_mask
= IFIELD( theInstr
, 2, 1 );
23994 UInt DCMX_mask
= (DC_mask
<< 6) | (DM_mask
<< 5) | DX_mask
;
23996 IRTemp NaN
[2], inf
[2], zero
[2], dnorm
[2], pos
[2], DCM
[2];
23997 IRTemp match_value
[2];
24001 DIP("xvtstdcdp v%u,v%u,%u\n", (UInt
)XT
, (UInt
)XB
, DCMX_mask
);
24003 for (i
= 0; i
< 2; i
++) {
24004 NaN
[i
] = newTemp(Ity_I64
);
24005 inf
[i
] = newTemp(Ity_I64
);
24006 pos
[i
] = newTemp(Ity_I64
);
24007 DCM
[i
] = newTemp(Ity_I64
);
24008 zero
[i
] = newTemp(Ity_I64
);
24009 dnorm
[i
] = newTemp(Ity_I64
);
24011 value
[i
] = newTemp(Ity_I64
);
24012 match_value
[i
] = newTemp(Ity_I64
);
24015 unop( Iop_V128to64
,
24016 binop( Iop_AndV128
,
24017 binop( Iop_ShrV128
,
24019 mkU8( (1-i
)*64 ) ),
24020 binop( Iop_64HLtoV128
,
24022 mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ) );
24024 assign( pos
[i
], unop( Iop_1Uto64
,
24025 binop( Iop_CmpEQ64
,
24027 mkexpr( value
[i
] ),
24031 assign( NaN
[i
], unop( Iop_1Uto64
, is_NaN( Ity_I64
, value
[i
] ) ) );
24032 assign( inf
[i
], unop( Iop_1Uto64
, is_Inf( Ity_I64
, value
[i
] ) ) );
24033 assign( zero
[i
], unop( Iop_1Uto64
, is_Zero( Ity_I64
, value
[i
] ) ) );
24034 assign( dnorm
[i
], unop( Iop_1Uto64
, is_Denorm( Ity_I64
,
24037 assign( DCM
[i
], create_DCM( Ity_I64
, NaN
[i
], inf
[i
], zero
[i
],
24038 dnorm
[i
], pos
[i
] ) );
24040 assign( match_value
[i
],
24042 binop( Iop_CmpNE64
,
24044 mkU64( DCMX_mask
),
24045 mkexpr( DCM
[i
] ) ),
24048 putVSReg( XT
, binop( Iop_64HLtoV128
,
24049 mkexpr( match_value
[0] ),
24050 mkexpr( match_value
[1] ) ) );
24054 case 0x3E0: // xviexpdp (VSX Vector Insert Exponent Double-Precision)
24060 IRExpr
*sign
[2], *expr
[2], *fract
[2];
24062 DIP("xviexpdp v%d,v%d\n", XT
, XB
);
24063 new_XT
[0] = newTemp(Ity_V128
);
24064 assign( new_XT
[0], binop( Iop_64HLtoV128
,
24068 for (i
= 0; i
< 2; i
++) {
24069 A_value
[i
] = newTemp(Ity_I64
);
24070 B_value
[i
] = newTemp(Ity_I64
);
24072 assign( A_value
[i
],
24073 unop( Iop_V128to64
,
24074 binop( Iop_AndV128
,
24075 binop( Iop_ShrV128
,
24077 mkU8( (1-i
)*64 ) ),
24078 binop( Iop_64HLtoV128
,
24080 mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ) );
24081 assign( B_value
[i
],
24082 unop( Iop_V128to64
,
24083 binop( Iop_AndV128
,
24084 binop( Iop_ShrV128
,
24086 mkU8( (1-i
)*64 ) ),
24087 binop( Iop_64HLtoV128
,
24089 mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ) );
24091 sign
[i
] = binop( Iop_And64
, mkexpr( A_value
[i
] ),
24092 mkU64( 0x8000000000000000 ) );
24093 expr
[i
] = binop( Iop_Shl64
,
24094 binop( Iop_And64
, mkexpr( B_value
[i
] ),
24097 fract
[i
] = binop( Iop_And64
, mkexpr( A_value
[i
] ),
24098 mkU64( 0x000FFFFFFFFFFFFF ) );
24100 new_XT
[i
+1] = newTemp(Ity_V128
);
24101 assign( new_XT
[i
+1],
24103 binop( Iop_ShlV128
,
24104 binop( Iop_64HLtoV128
,
24111 mkU8( (1-i
)*64 ) ),
24112 mkexpr( new_XT
[i
] ) ) );
24114 putVSReg( XT
, mkexpr( new_XT
[2] ) );
24119 vex_printf( "dis_vxs_misc(ppc)(opc2)\n" );
24126 * VSX vector miscellaneous instructions
24130 dis_vx_misc ( UInt prefix
, UInt theInstr
, UInt opc2
)
24133 UChar XT
= ifieldRegXT ( theInstr
);
24134 UChar XA
= ifieldRegXA ( theInstr
);
24135 UChar XB
= ifieldRegXB ( theInstr
);
24136 IRTemp vA
= newTemp( Ity_V128
);
24137 IRTemp vB
= newTemp( Ity_V128
);
24138 IRTemp src1
= newTemp(Ity_I64
);
24139 IRTemp src2
= newTemp(Ity_I64
);
24140 IRTemp result_mask
= newTemp(Ity_I64
);
24141 IRTemp cmp_mask
= newTemp(Ity_I64
);
24142 IRTemp nan_mask
= newTemp(Ity_I64
);
24143 IRTemp snan_mask
= newTemp(Ity_I64
);
24144 IRTemp word_result
= newTemp(Ity_I64
);
24145 IRTemp check_result
= newTemp(Ity_I64
);
24146 IRTemp xT
= newTemp( Ity_V128
);
24147 IRTemp nan_cmp_value
= newTemp(Ity_I64
);
24148 UInt trap_enabled
= 0; /* 0 - trap enabled is False */
24150 /* There is no prefixed version of these instructions. */
24153 assign( vA
, getVSReg( XA
) );
24154 assign( vB
, getVSReg( XB
) );
24155 assign( xT
, getVSReg( XT
) );
24157 assign(src1
, unop( Iop_V128HIto64
, mkexpr( vA
) ) );
24158 assign(src2
, unop( Iop_V128HIto64
, mkexpr( vB
) ) );
24162 unop( Iop_1Sto64
, is_NaN( Ity_I64
, src1
) ),
24163 unop( Iop_1Sto64
, is_NaN( Ity_I64
, src2
) ) ) );
24165 if ( trap_enabled
== 0 )
24166 /* Traps on invalid operation are assumed not enabled, assign
24167 result of comparison to xT.
24169 assign( snan_mask
, mkU64( 0 ) );
24174 unop( Iop_1Sto64
, is_sNaN( Ity_I64
, src1
) ),
24175 unop( Iop_1Sto64
, is_sNaN( Ity_I64
, src2
) ) ) );
24177 assign (result_mask
, binop( Iop_Or64
,
24178 mkexpr( snan_mask
),
24179 mkexpr( nan_mask
) ) );
24182 case 0xC: //xscmpeqdp
24184 DIP("xscmpeqdp v%d,v%d,v%d\n", XT
, XA
, XB
);
24185 /* extract double-precision floating point source values from
24188 /* result of Iop_CmpF64 is 0x40 if operands are equal,
24189 mask is all 1's if equal. */
24196 unop( Iop_ReinterpI64asF64
,
24198 unop( Iop_ReinterpI64asF64
,
24199 mkexpr( src2
) ) ),
24202 assign( word_result
,
24204 binop( Iop_And64
, mkexpr( cmp_mask
),
24205 mkU64( 0xFFFFFFFFFFFFFFFF ) ),
24207 unop( Iop_Not64
, mkexpr( cmp_mask
) ),
24208 mkU64( 0x0 ) ) ) );
24209 assign( nan_cmp_value
, mkU64( 0 ) );
24213 case 0x2C: //xscmpgtdp
24215 DIP("xscmpgtdp v%d,v%d,v%d\n", XT
, XA
, XB
);
24216 /* Test for src1 > src2 */
24218 /* Result of Iop_CmpF64 is 0x1 if op1 < op2, set mask to all 1's. */
24223 unop( Iop_ReinterpI64asF64
,
24225 unop( Iop_ReinterpI64asF64
,
24226 mkexpr( src1
) ) ) ) ) );
24227 assign( word_result
,
24229 binop( Iop_And64
, mkexpr( cmp_mask
),
24230 mkU64( 0xFFFFFFFFFFFFFFFF ) ),
24232 unop( Iop_Not64
, mkexpr( cmp_mask
) ),
24233 mkU64( 0x0 ) ) ) );
24234 assign( nan_cmp_value
, mkU64( 0 ) );
24238 case 0x4C: //xscmpgedp
24240 DIP("xscmpgedp v%u,v%u,v%u\n", XT
, XA
, XB
);
24241 /* compare src 1 >= src 2 */
24242 /* result of Iop_CmpF64 is 0x40 if operands are equal,
24243 mask is all 1's if equal. */
24249 binop(Iop_CmpF64
, /* EQ test */
24250 unop( Iop_ReinterpI64asF64
,
24252 unop( Iop_ReinterpI64asF64
,
24253 mkexpr( src2
) ) ),
24255 binop(Iop_CmpF64
, /* src2 < src 1 test */
24256 unop( Iop_ReinterpI64asF64
,
24258 unop( Iop_ReinterpI64asF64
,
24259 mkexpr( src1
) ) ) ) ) ) );
24260 assign( word_result
,
24262 binop( Iop_And64
, mkexpr( cmp_mask
),
24263 mkU64( 0xFFFFFFFFFFFFFFFF ) ),
24265 unop( Iop_Not64
, mkexpr( cmp_mask
) ),
24266 mkU64( 0x0 ) ) ) );
24267 assign( nan_cmp_value
, mkU64( 0 ) );
24271 case 0x200: //xsmaxcdp
24273 DIP("xsmaxcdp v%d,v%d,v%d\n", XT
, XA
, XB
);
24274 /* extract double-precision floating point source values from
24277 /* result of Iop_CmpF64 is 0x1 if arg1 LT then arg2, */
24282 unop( Iop_ReinterpI64asF64
,
24284 unop( Iop_ReinterpI64asF64
,
24285 mkexpr( src1
) ) ) ) ) );
24286 assign( word_result
,
24288 binop( Iop_And64
, mkexpr( cmp_mask
), mkexpr( src1
) ),
24290 unop( Iop_Not64
, mkexpr( cmp_mask
) ),
24291 mkexpr( src2
) ) ) );
24292 assign( nan_cmp_value
, mkexpr( src2
) );
24296 case 0x220: //xsmincdp
24298 DIP("xsmincdp v%d,v%d,v%d\n", XT
, XA
, XB
);
24299 /* extract double-precision floating point source values from
24302 /* result of Iop_CmpF64 is 0x1 if arg1 less then arg2, */
24307 unop( Iop_ReinterpI64asF64
,
24309 unop( Iop_ReinterpI64asF64
,
24310 mkexpr( src2
) ) ) ) ) );
24311 assign( word_result
,
24313 binop( Iop_And64
, mkexpr( cmp_mask
), mkexpr( src1
) ),
24315 unop( Iop_Not64
, mkexpr( cmp_mask
) ),
24316 mkexpr( src2
) ) ) );
24317 assign( nan_cmp_value
, mkexpr( src2
) );
24322 vex_printf( "dis_vx_misc(ppc)(opc2)\n" );
24326 /* If either argument is NaN, result is src2. If either argument is
24327 SNaN, we are supposed to generate invalid operation exception.
24328 Currently don't support generating exceptions. In case of an
24329 trap enabled invalid operation (SNaN) XT is not changed. The
24330 snan_mask is setup appropriately for trap enabled or not.
24332 assign( check_result
,
24334 binop( Iop_And64
, mkexpr( snan_mask
),
24335 unop( Iop_V128HIto64
, mkexpr( xT
) ) ),
24336 binop( Iop_And64
, unop( Iop_Not64
,
24337 mkexpr( snan_mask
) ),
24339 binop( Iop_And64
, mkexpr( nan_mask
),
24340 mkexpr( nan_cmp_value
) ),
24343 mkexpr( nan_mask
) ),
24344 mkU64( 0 ) ) ) ) ) );
24346 /* If SNaN is true, then the result is unchanged if a trap-enabled
24347 Invalid Operation occurs. Result mask already setup for trap-enabled
24351 binop( Iop_64HLtoV128
,
24354 unop( Iop_Not64
, mkexpr( result_mask
) ),
24355 mkexpr( word_result
) ),
24357 mkexpr( result_mask
),
24358 mkexpr( check_result
) ) ),
24364 * VSX Logical Instructions
24367 dis_vx_logic ( UInt prefix
, UInt theInstr
, UInt opc2
)
24370 UChar opc1
= ifieldOPC( theInstr
);
24371 UChar XT
= ifieldRegXT ( theInstr
);
24372 UChar XA
= ifieldRegXA ( theInstr
);
24373 UChar XB
= ifieldRegXB ( theInstr
);
24374 IRTemp vA
= newTemp( Ity_V128
);
24375 IRTemp vB
= newTemp( Ity_V128
);
24377 /* There is no prefixed version of these instructions. */
24380 if (opc1
!= 0x3C) {
24381 vex_printf( "dis_vx_logic(ppc)(instr)\n" );
24385 assign( vA
, getVSReg( XA
) );
24386 assign( vB
, getVSReg( XB
) );
24389 case 0x268: // xxlxor
24390 DIP("xxlxor v%d,v%d,v%d\n", XT
, XA
, XB
);
24391 putVSReg( XT
, binop( Iop_XorV128
, mkexpr( vA
), mkexpr( vB
) ) );
24393 case 0x248: // xxlor
24394 DIP("xxlor v%d,v%d,v%d\n", XT
, XA
, XB
);
24395 putVSReg( XT
, binop( Iop_OrV128
, mkexpr( vA
), mkexpr( vB
) ) );
24397 case 0x288: // xxlnor
24398 DIP("xxlnor v%d,v%d,v%d\n", XT
, XA
, XB
);
24399 putVSReg( XT
, unop( Iop_NotV128
, binop( Iop_OrV128
, mkexpr( vA
),
24400 mkexpr( vB
) ) ) );
24402 case 0x208: // xxland
24403 DIP("xxland v%d,v%d,v%d\n", XT
, XA
, XB
);
24404 putVSReg( XT
, binop( Iop_AndV128
, mkexpr( vA
), mkexpr( vB
) ) );
24406 case 0x228: //xxlandc
24407 DIP("xxlandc v%d,v%d,v%d\n", XT
, XA
, XB
);
24408 putVSReg( XT
, binop( Iop_AndV128
, mkexpr( vA
), unop( Iop_NotV128
,
24409 mkexpr( vB
) ) ) );
24411 case 0x2A8: // xxlorc (VSX Logical OR with complement)
24412 DIP("xxlorc v%d,v%d,v%d\n", XT
, XA
, XB
);
24413 putVSReg( XT
, binop( Iop_OrV128
,
24415 unop( Iop_NotV128
, mkexpr( vB
) ) ) );
24417 case 0x2C8: // xxlnand (VSX Logical NAND)
24418 DIP("xxlnand v%d,v%d,v%d\n", XT
, XA
, XB
);
24419 putVSReg( XT
, unop( Iop_NotV128
,
24420 binop( Iop_AndV128
, mkexpr( vA
),
24421 mkexpr( vB
) ) ) );
24423 case 0x2E8: // xxleqv (VSX Logical Equivalence)
24424 DIP("xxleqv v%d,v%d,v%d\n", XT
, XA
, XB
);
24425 putVSReg( XT
, unop( Iop_NotV128
,
24426 binop( Iop_XorV128
,
24427 mkexpr( vA
), mkexpr( vB
) ) ) );
24430 vex_printf( "dis_vx_logic(ppc)(opc2)\n" );
24437 * VSX Load Instructions
24438 * NOTE: VSX supports word-aligned storage access.
24441 dis_vx_load ( UInt prefix
, UInt theInstr
)
24444 UChar opc1
= ifieldOPC( theInstr
);
24445 UChar XT
= ifieldRegXT ( theInstr
);
24446 UChar rA_addr
= ifieldRegA( theInstr
);
24447 UChar rB_addr
= ifieldRegB( theInstr
);
24448 UInt opc2
= ifieldOPClo10( theInstr
);
24450 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
24451 IRTemp EA
= newTemp( ty
);
24453 /* There is no prefixed version of these instructions. */
24456 if (opc1
!= 0x1F) {
24457 vex_printf( "dis_vx_load(ppc)(instr)\n" );
24461 assign( EA
, ea_rAor0_idxd( rA_addr
, rB_addr
) );
24464 case 0x00C: // lxsiwzx (Load VSX Scalar as Integer Word and Zero Indexed)
24467 DIP("lxsiwzx %d,r%u,r%u\n", XT
, rA_addr
, rB_addr
);
24469 if (host_endness
== VexEndnessLE
)
24470 exp
= unop( Iop_64to32
, load( Ity_I64
, mkexpr( EA
) ) );
24472 exp
= unop( Iop_64HIto32
, load( Ity_I64
, mkexpr( EA
) ) );
24474 putVSReg( XT
, binop( Iop_64HLtoV128
,
24475 unop( Iop_32Uto64
, exp
),
24480 case 0x00D: // lxvrbx
24483 DIP("lxvrbx v%u,r%u,r%u\n", XT
, rA_addr
, rB_addr
);
24484 exp
= load( Ity_I64
, mkexpr( EA
) );
24486 if (host_endness
== VexEndnessLE
)
24487 putVSReg( XT
, binop( Iop_64HLtoV128
,
24489 binop( Iop_And64
, mkU64( 0xFF ), exp
) ) );
24492 binop( Iop_ShrV128
,
24493 binop( Iop_64HLtoV128
,
24495 binop( Iop_And64
, mkU64( 0xFF ), exp
) ),
24496 mkU8( 15*8 ) ) ); // data is left most byte
24500 case 0x02D: // lxvrhx
24504 DIP("lxvrhx v%u,r%u,r%u\n", XT
, rA_addr
, rB_addr
);
24506 exp
= load( Ity_I64
, mkexpr( EA
) );
24508 if (host_endness
== VexEndnessLE
)
24509 putVSReg( XT
, binop( Iop_64HLtoV128
,
24511 binop( Iop_And64
, mkU64( 0xFFFF ), exp
) ) );
24514 binop( Iop_ShrV128
,
24515 binop( Iop_64HLtoV128
,
24517 binop( Iop_And64
, mkU64( 0xFFFF ), exp
) ),
24518 mkU8( 7*16 ) ) ); // data is left most half-word
24522 case 0x04D: // lxvrwx
24526 DIP("lxvrwx v%u,r%u,r%u\n", XT
, rA_addr
, rB_addr
);
24528 exp
= load( Ity_I64
, mkexpr( EA
) );
24530 if (host_endness
== VexEndnessLE
)
24531 putVSReg( XT
, binop( Iop_64HLtoV128
,
24533 binop( Iop_And64
, mkU64( 0xFFFFFFFF ), exp
) ) );
24536 binop( Iop_ShrV128
,
24537 binop( Iop_64HLtoV128
,
24540 mkU64( 0xFFFFFFFF ), exp
) ),
24541 mkU8( 3*32 ) ) ); // data is left most word
24545 case 0x06D: // lxvrdx
24549 DIP("lxvrdx v%u,r%u,r%u\n", XT
, rA_addr
, rB_addr
);
24551 exp
= load( Ity_I64
, mkexpr( EA
) );
24553 if (host_endness
== VexEndnessLE
)
24554 putVSReg( XT
, binop( Iop_64HLtoV128
,
24557 mkU64( 0xFFFFFFFFFFFFFFFFULL
), exp
) ) );
24560 binop( Iop_ShrV128
,
24561 binop( Iop_64HLtoV128
,
24564 mkU64( 0xFFFFFFFFFFFFFFFFULL
), exp
) ),
24565 mkU8( 1*64 ) ) ); // data is left most double word
24569 case 0x08D: // stxvrbx
24571 IRExpr
* fetched_exp
;
24572 IRExpr
* store_exp
;
24573 IRTemp vS
= newTemp( Ity_V128
);
24575 DIP("stxvrbx v%u,r%u,r%u\n", XT
, rA_addr
, rB_addr
);
24577 fetched_exp
= load( Ity_I64
, mkexpr( EA
) );
24578 assign( vS
, getVSReg( XT
) );
24580 /* Fetch 64 bits, merge byte element 15 into the fetched value and
24582 if (host_endness
== VexEndnessLE
) {
24583 store_exp
= binop( Iop_Or64
,
24585 mkU64( 0x00000000000000FF ),
24586 unop( Iop_V128to64
, mkexpr( vS
) ) ),
24588 mkU64( 0xFFFFFFFFFFFFFF00 ),
24590 store( mkexpr( EA
), store_exp
);
24592 store_exp
= binop( Iop_Or64
,
24594 mkU64( 0xFF00000000000000 ),
24595 unop( Iop_V128HIto64
, mkexpr( vS
) ) ),
24597 mkU64( 0x00FFFFFFFFFFFFFF ),
24599 store( mkexpr( EA
), store_exp
);
24604 case 0x0AD: // stxvrhx
24606 IRExpr
* fetched_exp
;
24607 IRExpr
* store_exp
;
24608 IRTemp vS
= newTemp( Ity_V128
);
24610 DIP("stxvrhx v%u,r%u,r%u\n", XT
, rA_addr
, rB_addr
);
24612 fetched_exp
= load( Ity_I64
, mkexpr( EA
) );
24613 assign( vS
, getVSReg( XT
) );
24615 /* Fetch 64 bits, merge half-word element 7 into the fetched value and
24617 if (host_endness
== VexEndnessLE
) {
24618 store_exp
= binop( Iop_Or64
,
24620 mkU64( 0x000000000000FFFF ),
24621 unop( Iop_V128to64
, mkexpr( vS
) ) ),
24623 mkU64( 0xFFFFFFFFFFFF0000 ),
24625 store( mkexpr( EA
), store_exp
);
24627 store_exp
= binop( Iop_Or64
,
24629 mkU64( 0xFFFF000000000000 ),
24630 unop( Iop_V128HIto64
, mkexpr( vS
) ) ),
24632 mkU64( 0x0000FFFFFFFFFFFF ),
24634 store( mkexpr( EA
), store_exp
);
24639 case 0x0CD: // stxvrwx
24641 IRExpr
* fetched_exp
;
24642 IRExpr
* store_exp
;
24643 IRTemp vS
= newTemp( Ity_V128
);
24645 DIP("stxvrwx v%u,r%u,r%u\n", XT
, rA_addr
, rB_addr
);
24647 fetched_exp
= load( Ity_I64
, mkexpr( EA
) );
24648 assign( vS
, getVSReg( XT
) );
24650 /* Fetch 64 bits, merge word element 3 into the fetched value and
24652 if (host_endness
== VexEndnessLE
) {
24653 store_exp
= binop( Iop_Or64
,
24655 mkU64( 0x00000000FFFFFFFF ),
24656 unop( Iop_V128to64
, mkexpr( vS
) ) ),
24658 mkU64( 0xFFFFFFFF00000000 ),
24660 store( mkexpr( EA
), store_exp
);
24662 store_exp
= binop( Iop_Or64
,
24664 mkU64( 0xFFFFFFFF00000000 ),
24665 unop( Iop_V128HIto64
, mkexpr( vS
) ) ),
24667 mkU64( 0x00000000FFFFFFFF ),
24669 store( mkexpr( EA
), store_exp
);
24674 case 0x0ED: // stxvrdx
24676 IRExpr
* store_exp
;
24677 IRTemp vS
= newTemp( Ity_V128
);
24679 DIP("stxvrdx v%u,r%u,r%u\n", XT
, rA_addr
, rB_addr
);
24681 assign( vS
, getVSReg( XT
) );
24683 /* Fetch 64 bits, merge double word element 1 into the fetched value and
24684 * store. Well, this is just store vS bits[63:0] at EA. */
24685 if (host_endness
== VexEndnessLE
) {
24686 store_exp
= binop( Iop_And64
,
24687 mkU64( 0xFFFFFFFFFFFFFFFF ),
24688 unop( Iop_V128to64
, mkexpr( vS
) ) );
24689 store( mkexpr( EA
), store_exp
);
24691 store_exp
= binop( Iop_And64
,
24692 mkU64( 0xFFFFFFFFFFFFFFFF ),
24693 unop( Iop_V128HIto64
, mkexpr( vS
) ) );
24694 store( mkexpr( EA
), store_exp
);
24699 case 0x04C: // lxsiwax (Load VSX Scalar as Integer Word Algebraic Indexed)
24702 DIP("lxsiwax %d,r%u,r%u\n", XT
, rA_addr
, rB_addr
);
24704 if (host_endness
== VexEndnessLE
)
24705 exp
= unop( Iop_64to32
, load( Ity_I64
, mkexpr( EA
) ) );
24707 exp
= unop( Iop_64HIto32
, load( Ity_I64
, mkexpr( EA
) ) );
24709 putVSReg( XT
, binop( Iop_64HLtoV128
,
24710 unop( Iop_32Sto64
, exp
),
24714 case 0x10C: // lxvx
24721 DIP("lxvx %u,r%u,r%u\n", (UInt
)XT
, rA_addr
, rB_addr
);
24723 if ( host_endness
== VexEndnessBE
) {
24724 for ( i
= 3; i
>= 0; i
-- ) {
24725 word
[i
] = newTemp( Ity_I64
);
24728 binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
24729 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
24731 assign( word
[i
], unop( Iop_32Uto64
,
24732 load( Ity_I32
, irx_addr
) ) );
24736 putVSReg( XT
, binop( Iop_64HLtoV128
,
24746 mkU8( 32 ) ) ) ) );
24748 for ( i
= 0; i
< 4; i
++ ) {
24749 word
[i
] = newTemp( Ity_I64
);
24752 binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
24753 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
24755 assign( word
[i
], unop( Iop_32Uto64
,
24756 load( Ity_I32
, irx_addr
) ) );
24760 putVSReg( XT
, binop( Iop_64HLtoV128
,
24770 mkU8( 32 ) ) ) ) );
24775 case 0x10D: // lxvl
24777 DIP("lxvl %u,r%u,r%u\n", (UInt
)XT
, rA_addr
, rB_addr
);
24785 IRTemp shift
= newTemp( Ity_I8
);
24786 IRTemp nb_gt16
= newTemp( Ity_I8
);
24787 IRTemp ld_result
= newTemp( Ity_V128
);
24788 IRTemp nb_not_zero
= newTemp( Ity_I64
);
24790 IRTemp base_addr
= newTemp( ty
);
24792 tmp_low
[0] = newTemp( Ity_I64
);
24793 tmp_hi
[0] = newTemp( Ity_I64
);
24795 assign( base_addr
, ea_rAor0( rA_addr
) );
24796 assign( tmp_low
[0], mkU64( 0 ) );
24797 assign( tmp_hi
[0], mkU64( 0 ) );
24799 /* shift is 15 - nb, where nb = rB[0:7], used to zero out upper bytes */
24800 assign( nb_not_zero
, unop( Iop_1Sto64
,
24801 binop( Iop_CmpNE64
,
24804 getIReg( rB_addr
),
24805 mkU8( 56 ) ) ) ) );
24807 assign( nb_gt16
, unop( Iop_1Sto8
,
24808 binop( Iop_CmpLT64U
,
24810 getIReg( rB_addr
),
24814 /* Set the shift to 0, by ANDing with nb_gt16. nb_gt16 will be all
24815 * zeros if nb > 16. This will result in quad word load being stored.
24824 getIReg( rB_addr
),
24827 mkexpr( nb_gt16
) ) );
24829 /* fetch all 16 bytes, we will remove what we don't want later */
24830 if ( host_endness
== VexEndnessBE
) {
24831 for ( i
= 0; i
< 8; i
++ ) {
24832 byte
[i
] = newTemp( Ity_I64
);
24833 tmp_hi
[i
+1] = newTemp( Ity_I64
);
24836 binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
24837 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
24840 assign( byte
[i
], binop( Iop_Shl64
,
24842 load( Ity_I8
, irx_addr
) ),
24843 mkU8( 8 * ( 7 - i
) ) ) );
24845 assign( tmp_hi
[i
+1], binop( Iop_Or64
,
24847 mkexpr( tmp_hi
[i
] ) ) );
24850 for ( i
= 0; i
< 8; i
++ ) {
24851 byte
[i
+8] = newTemp( Ity_I64
);
24852 tmp_low
[i
+1] = newTemp( Ity_I64
);
24855 binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
24856 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
24859 assign( byte
[i
+8], binop( Iop_Shl64
,
24861 load( Ity_I8
, irx_addr
) ),
24862 mkU8( 8 * ( 7 - i
) ) ) );
24864 assign( tmp_low
[i
+1], binop( Iop_Or64
,
24865 mkexpr( byte
[i
+8] ),
24866 mkexpr( tmp_low
[i
] ) ) );
24868 assign( ld_result
, binop( Iop_ShlV128
,
24869 binop( Iop_ShrV128
,
24870 binop( Iop_64HLtoV128
,
24871 mkexpr( tmp_hi
[8] ),
24872 mkexpr( tmp_low
[8] ) ),
24874 mkexpr( shift
) ) );
24876 for ( i
= 0; i
< 8; i
++ ) {
24877 byte
[i
] = newTemp( Ity_I64
);
24878 tmp_low
[i
+1] = newTemp( Ity_I64
);
24881 binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
24882 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
24885 assign( byte
[i
], binop( Iop_Shl64
,
24887 load( Ity_I8
, irx_addr
) ),
24890 assign( tmp_low
[i
+1],
24892 mkexpr( byte
[i
] ), mkexpr( tmp_low
[i
] ) ) );
24895 for ( i
= 0; i
< 8; i
++ ) {
24896 byte
[i
+ 8] = newTemp( Ity_I64
);
24897 tmp_hi
[i
+1] = newTemp( Ity_I64
);
24900 binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
24901 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
24904 assign( byte
[i
+8], binop( Iop_Shl64
,
24906 load( Ity_I8
, irx_addr
) ),
24909 assign( tmp_hi
[i
+1], binop( Iop_Or64
,
24910 mkexpr( byte
[i
+8] ),
24911 mkexpr( tmp_hi
[i
] ) ) );
24913 assign( ld_result
, binop( Iop_ShrV128
,
24914 binop( Iop_ShlV128
,
24915 binop( Iop_64HLtoV128
,
24916 mkexpr( tmp_hi
[8] ),
24917 mkexpr( tmp_low
[8] ) ),
24919 mkexpr( shift
) ) );
24923 /* If nb = 0, mask out the calculated load result so the stored
24927 putVSReg( XT
, binop( Iop_AndV128
,
24928 mkexpr( ld_result
),
24929 binop( Iop_64HLtoV128
,
24930 mkexpr( nb_not_zero
),
24931 mkexpr( nb_not_zero
) ) ) );
24935 case 0x12D: // lxvll (Load VSX Vector Left-Justified with Length XX1 form)
24940 IRTemp mask
= newTemp(Ity_V128
);
24941 IRTemp rB
= newTemp( Ity_I64
);
24942 IRTemp nb
= newTemp( Ity_I64
);
24943 IRTemp nb_zero
= newTemp(Ity_V128
);
24944 IRTemp mask_shift
= newTemp(Ity_I64
);
24948 IRTemp base_addr
= newTemp( ty
);
24949 IRTemp nb_compare_zero
= newTemp( Ity_I64
);
24951 DIP("lxvll %u,r%u,r%u\n", (UInt
)XT
, rA_addr
, rB_addr
);
24953 tmp_low
[0] = newTemp(Ity_I64
);
24954 tmp_hi
[0] = newTemp(Ity_I64
);
24956 assign( rB
, getIReg(rB_addr
));
24957 assign( base_addr
, ea_rAor0( rA_addr
) );
24958 assign( tmp_low
[0], mkU64( 0 ) );
24959 assign( tmp_hi
[0], mkU64( 0 ) );
24961 /* mask_shift is number of 16 bytes minus (nb times 8-bits per byte) */
24962 assign( nb
, binop( Iop_Shr64
, mkexpr( rB
), mkU8( 56 ) ) );
24964 assign( nb_compare_zero
, unop( Iop_1Sto64
,
24965 binop( Iop_CmpEQ64
,
24969 /* nb_zero is 0xFF..FF if the nb_field = 0 */
24970 assign( nb_zero
, binop( Iop_64HLtoV128
,
24971 mkexpr( nb_compare_zero
),
24972 mkexpr( nb_compare_zero
) ) );
24974 assign( mask_shift
, binop( Iop_Sub64
,
24980 /* fetch all 16 bytes, we will remove what we don't want later */
24981 for (i
= 0; i
< 8; i
++) {
24982 byte
[i
] = newTemp(Ity_I64
);
24983 tmp_hi
[i
+1] = newTemp(Ity_I64
);
24985 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
24986 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
24989 /* Instruction always loads in Big Endian format */
24990 assign( byte
[i
], binop( Iop_Shl64
,
24992 load( Ity_I8
, irx_addr
) ),
24993 mkU8( 8 * (7 - i
) ) ) );
24994 assign( tmp_hi
[i
+1],
24996 mkexpr( byte
[i
] ), mkexpr( tmp_hi
[i
] ) ) );
24999 for (i
= 0; i
< 8; i
++) {
25000 byte
[i
+ 8] = newTemp(Ity_I64
);
25001 tmp_low
[i
+1] = newTemp(Ity_I64
);
25003 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
25004 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
25007 /* Instruction always loads in Big Endian format */
25008 assign( byte
[i
+8], binop( Iop_Shl64
,
25010 load( Ity_I8
, irx_addr
) ),
25011 mkU8( 8 * (7 - i
) ) ) );
25012 assign( tmp_low
[i
+1], binop( Iop_Or64
,
25013 mkexpr( byte
[i
+8] ),
25014 mkexpr( tmp_low
[i
] ) ) );
25017 /* Create mask to clear the right most 16 - nb bytes, set to zero
25020 assign( mask
, binop( Iop_AndV128
,
25021 binop( Iop_ShlV128
,
25022 binop( Iop_ShrV128
,
25024 unop( Iop_64to8
, mkexpr( mask_shift
) ) ),
25025 unop( Iop_64to8
, mkexpr( mask_shift
) ) ),
25026 unop( Iop_NotV128
, mkexpr( nb_zero
) ) ) );
25028 putVSReg( XT
, binop( Iop_AndV128
,
25030 binop( Iop_64HLtoV128
,
25031 mkexpr( tmp_hi
[8] ),
25032 mkexpr( tmp_low
[8] ) ) ) );
25036 case 0x16C: // lxvwsx
25038 IRTemp data
= newTemp( Ity_I64
);
25040 DIP("lxvwsx %u,r%u,r%u\n", (UInt
)XT
, rA_addr
, rB_addr
);
25042 /* The load is a 64-bit fetch that is Endian aware, just want
25043 * the lower 32 bits. */
25044 if ( host_endness
== VexEndnessBE
) {
25049 binop( mkSzOp( ty
, Iop_Sub8
), mkexpr( EA
),
25050 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
25052 assign( data
, binop( Iop_And64
,
25053 load( Ity_I64
, irx_addr
),
25054 mkU64( 0xFFFFFFFF ) ) );
25057 assign( data
, binop( Iop_And64
,
25058 load( Ity_I64
, mkexpr( EA
) ),
25059 mkU64( 0xFFFFFFFF ) ) );
25062 /* Take lower 32-bits and spat across the four word positions */
25064 binop( Iop_64HLtoV128
,
25074 mkU8( 32 ) ) ) ) );
25078 case 0x20C: // lxsspx (Load VSX Scalar Single-Precision Indexed)
25081 DIP("lxsspx %d,r%u,r%u\n", XT
, rA_addr
, rB_addr
);
25082 /* Take 32-bit floating point value in the upper half of the fetched
25083 * 64-bit value, convert to 64-bit floating point value and load into
25084 * top word of V128.
25086 exp
= unop( Iop_ReinterpF64asI64
,
25087 unop( Iop_F32toF64
,
25088 unop( Iop_ReinterpI32asF32
,
25089 load( Ity_I32
, mkexpr( EA
) ) ) ) );
25091 putVSReg( XT
, binop( Iop_64HLtoV128
, exp
, mkU64( 0 ) ) );
25094 case 0x24C: // lxsdx
25097 DIP("lxsdx %d,r%u,r%u\n", XT
, rA_addr
, rB_addr
);
25098 exp
= load( Ity_I64
, mkexpr( EA
) );
25099 // We need to pass an expression of type Ity_V128 with putVSReg, but the load
25100 // we just performed is only a DW. But since the contents of VSR[XT] element 1
25101 // are undefined after this operation, we can just do a splat op.
25102 putVSReg( XT
, binop( Iop_64HLtoV128
, exp
, exp
) );
25106 case 0x30D: // lxsibzx
25111 DIP("lxsibzx %u,r%u,r%u\n", (UInt
)XT
, rA_addr
, rB_addr
);
25113 if ( host_endness
== VexEndnessBE
)
25114 irx_addr
= binop( Iop_Sub64
, mkexpr( EA
), mkU64( 7 ) );
25117 irx_addr
= mkexpr( EA
);
25119 byte
= load( Ity_I8
, irx_addr
);
25120 putVSReg( XT
, binop( Iop_64HLtoV128
,
25121 unop( Iop_8Uto64
, byte
),
25126 case 0x32D: // lxsihzx
25131 DIP("lxsihzx %u,r%u,r%u\n", (UInt
)XT
, rA_addr
, rB_addr
);
25133 if ( host_endness
== VexEndnessBE
)
25134 irx_addr
= binop( Iop_Sub64
, mkexpr( EA
), mkU64( 6 ) );
25137 irx_addr
= mkexpr( EA
);
25139 hword
= load( Ity_I16
, irx_addr
);
25140 putVSReg( XT
, binop( Iop_64HLtoV128
,
25146 case 0x34C: // lxvd2x
25149 DIP("lxvd2x %d,r%u,r%u\n", XT
, rA_addr
, rB_addr
);
25150 t128
= load( Ity_V128
, mkexpr( EA
) );
25152 /* The data in the vec register should be in big endian order.
25153 So if we just did a little endian load then swap around the
25154 high and low double words. */
25155 if (host_endness
== VexEndnessLE
) {
25156 IRTemp high
= newTemp(Ity_I64
);
25157 IRTemp low
= newTemp(Ity_I64
);
25158 assign( high
, unop(Iop_V128HIto64
, t128
) );
25159 assign( low
, unop(Iop_V128to64
, t128
) );
25160 t128
= binop( Iop_64HLtoV128
, mkexpr (low
), mkexpr (high
) );
25163 putVSReg( XT
, t128
);
25166 case 0x14C: // lxvdsx
25168 IRTemp data
= newTemp(Ity_I64
);
25169 DIP("lxvdsx %d,r%u,r%u\n", XT
, rA_addr
, rB_addr
);
25170 assign( data
, load( Ity_I64
, mkexpr( EA
) ) );
25171 putVSReg( XT
, binop( Iop_64HLtoV128
, mkexpr( data
), mkexpr( data
) ) );
25178 DIP("lxvw4x %u,r%u,r%u\n", XT
, rA_addr
, rB_addr
);
25180 /* The load will result in the data being in BE order. */
25181 if (host_endness
== VexEndnessLE
) {
25183 IRTemp perm_LE
= newTemp(Ity_V128
);
25185 t0_BE
= load( Ity_V128
, mkexpr( EA
) );
25187 /* Permute the data to LE format */
25188 assign( perm_LE
, binop( Iop_64HLtoV128
, mkU64(0x0c0d0e0f08090a0bULL
),
25189 mkU64(0x0405060700010203ULL
)));
25191 t0
= binop( Iop_Perm8x16
, t0_BE
, mkexpr(perm_LE
) );
25193 t0
= load( Ity_V128
, mkexpr( EA
) );
25196 putVSReg( XT
, t0
);
25200 case 0x32C: // lxvh8x
25202 DIP("lxvh8x %u,r%u,r%u\n", (UInt
)XT
, rA_addr
, rB_addr
);
25211 tmp_low
[0] = newTemp( Ity_I64
);
25212 tmp_hi
[0] = newTemp( Ity_I64
);
25213 assign( tmp_low
[0], mkU64( 0 ) );
25214 assign( tmp_hi
[0], mkU64( 0 ) );
25216 for ( i
= 0; i
< 4; i
++ ) {
25217 h_word
[i
] = newTemp(Ity_I64
);
25218 tmp_low
[i
+1] = newTemp(Ity_I64
);
25220 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
25221 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
25224 assign( h_word
[i
], binop( Iop_Shl64
,
25226 load( Ity_I16
, irx_addr
) ),
25227 mkU8( 16 * ( 3 - i
) ) ) );
25229 assign( tmp_low
[i
+1],
25231 mkexpr( h_word
[i
] ), mkexpr( tmp_low
[i
] ) ) );
25234 for ( i
= 0; i
< 4; i
++ ) {
25235 h_word
[i
+4] = newTemp( Ity_I64
);
25236 tmp_hi
[i
+1] = newTemp( Ity_I64
);
25238 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
25239 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
25242 assign( h_word
[i
+4], binop( Iop_Shl64
,
25244 load( Ity_I16
, irx_addr
) ),
25245 mkU8( 16 * ( 3 - i
) ) ) );
25247 assign( tmp_hi
[i
+1], binop( Iop_Or64
,
25248 mkexpr( h_word
[i
+4] ),
25249 mkexpr( tmp_hi
[i
] ) ) );
25251 putVSReg( XT
, binop( Iop_64HLtoV128
,
25252 mkexpr( tmp_low
[4] ), mkexpr( tmp_hi
[4] ) ) );
25256 case 0x36C: // lxvb16x
25258 DIP("lxvb16x %u,r%u,r%u\n", (UInt
)XT
, rA_addr
, rB_addr
);
25260 /* The result of lxvb16x should be the same on big and little
25261 endian systems. We do a host load, then reverse the bytes in
25262 the double words. If the host load was little endian we swap
25263 them around again. */
25265 IRTemp high
= newTemp(Ity_I64
);
25266 IRTemp high_rev
= newTemp(Ity_I64
);
25267 IRTemp low
= newTemp(Ity_I64
);
25268 IRTemp low_rev
= newTemp(Ity_I64
);
25270 IRExpr
*t128
= load( Ity_V128
, mkexpr( EA
) );
25272 assign( high
, unop(Iop_V128HIto64
, t128
) );
25273 assign( high_rev
, unop(Iop_Reverse8sIn64_x1
, mkexpr(high
)) );
25274 assign( low
, unop(Iop_V128to64
, t128
) );
25275 assign( low_rev
, unop(Iop_Reverse8sIn64_x1
, mkexpr(low
)) );
25277 if (host_endness
== VexEndnessLE
)
25278 t128
= binop( Iop_64HLtoV128
, mkexpr (low_rev
), mkexpr (high_rev
) );
25280 t128
= binop( Iop_64HLtoV128
, mkexpr (high_rev
), mkexpr (low_rev
) );
25282 putVSReg( XT
, t128
);
25287 vex_printf( "dis_vx_load(ppc)(opc2)\n" );
25294 * VSX Move Instructions
25297 dis_vx_move ( UInt prefix
, UInt theInstr
)
25300 UChar opc1
= ifieldOPC( theInstr
);
25301 UChar XS
= ifieldRegXS( theInstr
);
25302 UChar rA_addr
= ifieldRegA( theInstr
);
25303 UChar rB_addr
= ifieldRegB( theInstr
);
25304 IRTemp vS
= newTemp( Ity_V128
);
25305 UInt opc2
= ifieldOPClo10( theInstr
);
25306 IRType ty
= Ity_I64
;
25308 /* There is no prefixed version of these instructions. */
25311 if ( opc1
!= 0x1F ) {
25312 vex_printf( "dis_vx_move(ppc)(instr)\n" );
25317 case 0x133: // mfvsrld RA,XS Move From VSR Lower Doubleword
25318 DIP("mfvsrld %u,r%u\n", (UInt
)XS
, rA_addr
);
25320 assign( vS
, getVSReg( XS
) );
25321 putIReg( rA_addr
, unop(Iop_V128to64
, mkexpr( vS
) ) );
25325 case 0x193: // mfvsrdd XT,RA,RB Move to VSR Double Doubleword
25327 IRTemp tmp
= newTemp( Ity_I32
);
25329 DIP("mfvsrdd %u,r%u\n", (UInt
)XS
, rA_addr
);
25331 assign( tmp
, unop( Iop_64to32
, getIReg(rA_addr
) ) );
25332 assign( vS
, binop( Iop_64HLtoV128
,
25333 binop( Iop_32HLto64
,
25336 binop( Iop_32HLto64
,
25338 mkexpr( tmp
) ) ) );
25339 putVSReg( XS
, mkexpr( vS
) );
25343 case 0x1B3: // mtvsrws XT,RA Move to VSR word & Splat
25345 IRTemp rA
= newTemp( ty
);
25346 IRTemp rB
= newTemp( ty
);
25348 DIP("mfvsrws %u,r%u\n", (UInt
)XS
, rA_addr
);
25350 if ( rA_addr
== 0 )
25351 assign( rA
, mkU64 ( 0 ) );
25353 assign( rA
, getIReg(rA_addr
) );
25355 assign( rB
, getIReg(rB_addr
) );
25356 assign( vS
, binop( Iop_64HLtoV128
, mkexpr( rA
), mkexpr( rB
) ) );
25357 putVSReg( XS
, mkexpr( vS
) );
25362 vex_printf( "dis_vx_move(ppc)(opc2)\n" );
25369 * VSX Store Instructions
25370 * NOTE: VSX supports word-aligned storage access.
25373 dis_vsx_vector_paired_load_store ( UInt prefix
, UInt theInstr
)
25375 /* X-Form/DS-Form */
25376 UInt opc2
= ifieldOPClo9(theInstr
);
25377 UChar rA_addr
= ifieldRegA(theInstr
);
25378 UChar rB_addr
= ifieldRegB(theInstr
);
25379 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
25380 IRTemp EA
= newTemp(ty
);
25381 IRTemp EA_16
= newTemp(ty
);
25382 UChar XTp
= ifieldRegXTp(theInstr
);
25384 assign( EA
, ea_rAor0_idxd( rA_addr
, rB_addr
) );
25386 // address of next 128bits
25387 assign( EA_16
, binop( Iop_Add64
, mkU64( 16), mkexpr( EA
) ) );
25390 case 0x14D: // lxvpx
25391 DIP( "lxvpx %u,%d(%u)\n", XTp
, rA_addr
, rB_addr
);
25392 if ( host_endness
== VexEndnessBE
) {
25393 putVSReg( XTp
, load( Ity_V128
, mkexpr( EA
) ) );
25394 putVSReg( XTp
+1, load( Ity_V128
, mkexpr( EA_16
) ) );
25396 putVSReg( XTp
+1, load( Ity_V128
, mkexpr( EA
) ) );
25397 putVSReg( XTp
, load( Ity_V128
, mkexpr( EA_16
) ) );
25401 case 0x1CD: { // stxvpx
25402 IRTemp EA_8
= newTemp(ty
);
25403 IRTemp EA_24
= newTemp(ty
);
25405 DIP( "stxvpx %u,%d(%u)\n", XTp
, rA_addr
, rB_addr
);
25407 assign( EA_8
, binop( Iop_Add64
, mkU64( 8 ), mkexpr( EA
) ) );
25408 assign( EA_24
, binop( Iop_Add64
, mkU64( 24 ), mkexpr( EA
) ) );
25410 if ( host_endness
== VexEndnessBE
) {
25411 store( mkexpr( EA
), unop( Iop_V128to64
, getVSReg( XTp
) ) );
25412 store( mkexpr( EA_8
), unop( Iop_V128HIto64
, getVSReg( XTp
) ) );
25413 store( mkexpr( EA_16
), unop( Iop_V128to64
, getVSReg( XTp
+1 ) ) );
25414 store( mkexpr( EA_24
), unop( Iop_V128HIto64
, getVSReg( XTp
+1 ) ) );
25417 store( mkexpr( EA
), unop( Iop_V128to64
, getVSReg( XTp
+1 ) ) );
25418 store( mkexpr( EA_8
), unop( Iop_V128HIto64
, getVSReg( XTp
+1 ) ) );
25419 store( mkexpr( EA_16
), unop( Iop_V128to64
, getVSReg( XTp
) ) );
25420 store( mkexpr( EA_24
), unop( Iop_V128HIto64
, getVSReg( XTp
) ) );
25426 vex_printf("dis_vsx_vector_paired_load_store\n");
25434 dis_vx_store ( UInt prefix
, UInt theInstr
)
25437 UChar opc1
= ifieldOPC( theInstr
);
25438 UChar XS
= ifieldRegXS( theInstr
);
25439 UChar rA_addr
= ifieldRegA( theInstr
);
25440 UChar rB_addr
= ifieldRegB( theInstr
);
25441 IRTemp vS
= newTemp( Ity_V128
);
25442 UInt opc2
= ifieldOPClo10( theInstr
);
25444 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
25445 IRTemp EA
= newTemp( ty
);
25447 /* There is no prefixed version of these instructions. */
25450 if (opc1
!= 0x1F) {
25451 vex_printf( "dis_vx_store(ppc)(instr)\n" );
25455 assign( EA
, ea_rAor0_idxd( rA_addr
, rB_addr
) );
25456 assign( vS
, getVSReg( XS
) );
25461 /* Need the next to the most significant 32-bit word from
25462 * the 128-bit vector.
25464 IRExpr
* high64
, * low32
;
25465 DIP("stxsiwx %d,r%u,r%u\n", XS
, rA_addr
, rB_addr
);
25466 high64
= unop( Iop_V128HIto64
, mkexpr( vS
) );
25467 low32
= unop( Iop_64to32
, high64
);
25468 store( mkexpr( EA
), low32
);
25472 case 0x18C: // stxvx Store VSX Vector Indexed
25476 IRTemp word0
= newTemp( Ity_I64
);
25477 IRTemp word1
= newTemp( Ity_I64
);
25478 IRTemp word2
= newTemp( Ity_I64
);
25479 IRTemp word3
= newTemp( Ity_I64
);
25480 DIP("stxvx %u,r%u,r%u\n", (UInt
)XS
, rA_addr
, rB_addr
);
25482 assign( word0
, binop( Iop_Shr64
,
25483 unop( Iop_V128HIto64
, mkexpr( vS
) ),
25486 assign( word1
, binop( Iop_And64
,
25487 unop( Iop_V128HIto64
, mkexpr( vS
) ),
25488 mkU64( 0xFFFFFFFF ) ) );
25490 assign( word2
, binop( Iop_Shr64
,
25491 unop( Iop_V128to64
, mkexpr( vS
) ),
25494 assign( word3
, binop( Iop_And64
,
25495 unop( Iop_V128to64
, mkexpr( vS
) ),
25496 mkU64( 0xFFFFFFFF ) ) );
25498 if (host_endness
== VexEndnessBE
) {
25499 store( mkexpr( EA
), unop( Iop_64to32
, mkexpr( word0
) ) );
25502 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
25503 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
25505 store( irx_addr
, unop( Iop_64to32
, mkexpr( word1
) ) );
25508 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
25509 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
25511 store( irx_addr
, unop( Iop_64to32
, mkexpr( word2
) ) );
25513 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
25514 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
25516 store( irx_addr
, unop( Iop_64to32
, mkexpr( word3
) ) );
25518 store( mkexpr( EA
), unop( Iop_64to32
, mkexpr( word3
) ) );
25521 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
25522 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
25524 store( irx_addr
, unop( Iop_64to32
, mkexpr( word2
) ) );
25527 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
25528 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
25530 store( irx_addr
, unop( Iop_64to32
, mkexpr( word1
) ) );
25532 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
25533 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
25535 store( irx_addr
, unop( Iop_64to32
, mkexpr( word0
) ) );
25540 case 0x18D: // stxvl Store VSX Vector Indexed
25544 IRTemp word0
= newTemp( Ity_I64
);
25545 IRTemp word1
= newTemp( Ity_I64
);
25546 IRTemp word2
= newTemp( Ity_I64
);
25547 IRTemp word3
= newTemp( Ity_I64
);
25548 IRTemp shift
= newTemp( Ity_I8
);
25549 IRTemp nb_gt16
= newTemp( Ity_I8
);
25550 IRTemp nb_zero
= newTemp( Ity_V128
);
25551 IRTemp nb
= newTemp( Ity_I8
);
25552 IRTemp nb_field
= newTemp( Ity_I64
);
25553 IRTemp n_bytes
= newTemp( Ity_I8
);
25554 IRTemp base_addr
= newTemp( ty
);
25555 IRTemp current_mem
= newTemp( Ity_V128
);
25556 IRTemp store_val
= newTemp( Ity_V128
);
25557 IRTemp nb_mask
= newTemp( Ity_V128
);
25559 DIP("stxvl %u,r%u,r%u\n", (UInt
)XS
, rA_addr
, rB_addr
);
25561 assign( nb_field
, binop( Iop_Shr64
,
25565 assign( nb
, unop( Iop_64to8
, mkexpr( nb_field
) ) );
25567 /* nb_gt16 will be all zeros if nb > 16 */
25568 assign( nb_gt16
, unop( Iop_1Sto8
,
25569 binop( Iop_CmpLT64U
,
25571 mkexpr( nb_field
),
25575 /* nb_zero is 0xFF..FF if the nb_field = 0 */
25576 assign( nb_zero
, binop( Iop_64HLtoV128
,
25578 binop( Iop_CmpEQ64
,
25579 mkexpr( nb_field
),
25582 binop( Iop_CmpEQ64
,
25583 mkexpr( nb_field
),
25584 mkU64( 0 ) ) ) ) );
25586 /* set n_bytes to 0 if nb >= 16. Otherwise, set to nb. */
25587 assign( n_bytes
, binop( Iop_And8
, mkexpr( nb
), mkexpr( nb_gt16
) ) );
25588 assign( shift
, unop( Iop_64to8
,
25593 mkexpr( n_bytes
) ) ),
25596 /* We only have a 32-bit store function. So, need to fetch the
25597 * contents of memory merge with the store value and do two
25598 * 32-byte stores so we preserve the contents of memory not
25601 assign( base_addr
, ea_rAor0( rA_addr
) );
25603 assign( current_mem
,
25604 binop( Iop_64HLtoV128
,
25606 binop( mkSzOp( ty
, Iop_Add8
),
25607 mkexpr( base_addr
),
25608 ty
== Ity_I64
? mkU64( 8 ) : mkU32( 8 )
25610 load( Ity_I64
, mkexpr( base_addr
) ) ) );
25612 /* Set the nb_mask to all zeros if nb = 0 so the current contents
25613 * of memory get written back without modifications.
25615 * The store_val is a combination of the current memory value
25616 * and the bytes you want to store. The nb_mask selects the
25617 * bytes you want stored from Vs.
25621 binop( Iop_AndV128
,
25624 binop( Iop_AndV128
,
25625 binop( Iop_ShrV128
,
25628 unop( Iop_NotV128
, mkexpr( nb_zero
) ) ) ) );
25632 binop( Iop_AndV128
,
25634 mkexpr( nb_mask
) ),
25635 binop( Iop_AndV128
,
25636 unop( Iop_NotV128
, mkexpr( nb_mask
) ),
25637 mkexpr( current_mem
) ) ) );
25639 /* Store the value in 32-byte chunks */
25640 assign( word0
, binop( Iop_Shr64
,
25641 unop( Iop_V128HIto64
, mkexpr( store_val
) ),
25644 assign( word1
, binop( Iop_And64
,
25645 unop( Iop_V128HIto64
, mkexpr( store_val
) ),
25646 mkU64( 0xFFFFFFFF ) ) );
25648 assign( word2
, binop( Iop_Shr64
,
25649 unop( Iop_V128to64
, mkexpr( store_val
) ),
25652 assign( word3
, binop( Iop_And64
,
25653 unop( Iop_V128to64
, mkexpr( store_val
) ),
25654 mkU64( 0xFFFFFFFF ) ) );
25657 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
25658 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
25660 store( irx_addr
, unop( Iop_64to32
, mkexpr( word3
) ) );
25663 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
25664 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
25666 store( irx_addr
, unop( Iop_64to32
, mkexpr( word2
) ) );
25669 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
25670 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
25672 store( irx_addr
, unop( Iop_64to32
, mkexpr( word1
) ) );
25675 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
25676 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
25678 store( irx_addr
, unop( Iop_64to32
, mkexpr( word0
) ) );
25682 case 0x1AD: // stxvll (Store VSX Vector Left-justified with length XX1-form)
25690 IRTemp shift
= newTemp(Ity_I8
);
25691 IRTemp nb_gt16
= newTemp(Ity_I8
);
25692 IRTemp nb_zero
= newTemp(Ity_V128
);
25693 IRTemp nb
= newTemp(Ity_I8
);
25694 IRTemp nb_field
= newTemp(Ity_I64
);
25695 IRTemp n_bytes
= newTemp(Ity_I8
);
25696 IRTemp base_addr
= newTemp( ty
);
25697 IRTemp current_mem
= newTemp(Ity_V128
);
25698 IRTemp store_val
= newTemp(Ity_V128
);
25699 IRTemp nb_mask
= newTemp(Ity_V128
);
25700 IRTemp mask
= newTemp( Ity_I64
);
25704 IRTemp nb_field_compare_zero
= newTemp( Ity_I64
);
25707 DIP("stxvll %u,r%u,r%u\n", (UInt
)XS
, rA_addr
, rB_addr
);
25709 assign( nb_field
, binop( Iop_Shr64
,
25712 assign( nb
, unop( Iop_64to8
, mkexpr( nb_field
) ) );
25713 assign( mask
, mkU64( 0xFFFFFFFFFFFFFFFFULL
) );
25715 /* nb_gt16 will be all zeros if nb > 16 */
25716 assign( nb_gt16
, unop( Iop_1Sto8
,
25717 binop( Iop_CmpLT64U
,
25719 mkexpr( nb_field
),
25723 assign( nb_field_compare_zero
, unop( Iop_1Sto64
,
25724 binop( Iop_CmpEQ64
,
25725 mkexpr( nb_field
),
25728 /* nb_zero is 0xFF..FF if the nb_field = 0 */
25729 assign( nb_zero
, binop( Iop_64HLtoV128
,
25730 mkexpr( nb_field_compare_zero
),
25731 mkexpr( nb_field_compare_zero
) ) );
25734 /* set n_bytes to 0 if nb >= 16. Otherwise, set to nb. */
25735 assign( n_bytes
, binop( Iop_And8
, mkexpr( nb
), mkexpr( nb_gt16
) ) );
25741 unop( Iop_8Uto64
, mkexpr( n_bytes
) )),
25744 /* We only have a 32-bit store function. So, need to fetch the
25745 * contents of memory merge with the store value and do two
25746 * 32-byte stores so we preserve the contents of memory not
25749 assign( base_addr
, ea_rAor0( rA_addr
) );
25750 /* fetch all 16 bytes and store in Big Endian format */
25751 word0
[0] = newTemp(Ity_I64
);
25752 assign( word0
[0], mkU64( 0 ) );
25754 word1
[0] = newTemp(Ity_I64
);
25755 assign( word1
[0], mkU64( 0 ) );
25757 word2
[0] = newTemp(Ity_I64
);
25758 assign( word2
[0], mkU64( 0 ) );
25760 word3
[0] = newTemp(Ity_I64
);
25761 assign( word3
[0], mkU64( 0 ) );
25763 for (i
= 0; i
< 4; i
++) {
25764 word0
[i
+1] = newTemp(Ity_I64
);
25766 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
25767 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
25770 /* Instruction always loads in Big Endian format */
25771 assign( word0
[i
+1],
25778 mkexpr( word0
[i
] ) ) );
25781 for (i
= 0; i
< 4; i
++) {
25782 word1
[i
+1] = newTemp(Ity_I64
);
25784 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
25785 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
25788 /* Instruction always loads in Big Endian format */
25789 assign( word1
[i
+1],
25796 mkexpr( word1
[i
] ) ) );
25798 for (i
= 0; i
< 4; i
++) {
25799 word2
[i
+1] = newTemp(Ity_I64
);
25801 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
25802 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
25805 /* Instruction always loads in Big Endian format */
25806 assign( word2
[i
+1],
25813 mkexpr( word2
[i
] ) ) );
25815 for (i
= 0; i
< 4; i
++) {
25816 word3
[i
+1] = newTemp(Ity_I64
);
25818 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
25819 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
25822 /* Instruction always loads in Big Endian format */
25823 assign( word3
[i
+1],
25830 mkexpr( word3
[i
] ) ) );
25834 assign( current_mem
,
25835 binop( Iop_64HLtoV128
,
25838 mkexpr( word0
[4] ),
25840 mkexpr( word1
[4] ) ),
25843 mkexpr( word2
[4] ),
25845 mkexpr( word3
[4] ) ) ) );
25847 /* Set the nb_mask to all zeros if nb = 0 so the current contents
25848 * of memory get written back without modifications.
25850 * The store_val is a combination of the current memory value
25851 * and the bytes you want to store. The nb_mask selects the
25852 * bytes you want stored from Vs.
25854 /* The instruction always uses Big Endian order */
25857 binop( Iop_AndV128
,
25858 binop( Iop_ShlV128
,
25859 binop( Iop_ShrV128
,
25860 binop( Iop_64HLtoV128
,
25865 unop( Iop_NotV128
, mkexpr( nb_zero
) ) ),
25866 binop( Iop_AndV128
,
25868 binop( Iop_64HLtoV128
,
25870 mkU64( 0x0 ) ) ) ) );
25874 binop( Iop_AndV128
,
25876 mkexpr( nb_mask
) ),
25877 binop( Iop_AndV128
,
25878 unop( Iop_NotV128
, mkexpr( nb_mask
) ),
25879 mkexpr( current_mem
) ) ) );
25881 /* store the merged value in Big Endian format */
25882 tmp_low
[0] = newTemp(Ity_I64
);
25883 tmp_hi
[0] = newTemp(Ity_I64
);
25884 assign( tmp_low
[0], mkU64( 0 ) );
25885 assign( tmp_hi
[0], mkU64( 0 ) );
25887 for (i
= 0; i
< 8; i
++) {
25888 byte
[i
] = newTemp(Ity_I64
);
25889 byte
[i
+8] = newTemp(Ity_I64
);
25890 tmp_low
[i
+1] = newTemp(Ity_I64
);
25891 tmp_hi
[i
+1] = newTemp(Ity_I64
);
25893 assign( byte
[i
], binop( Iop_And64
,
25895 unop( Iop_V128HIto64
,
25896 mkexpr( store_val
) ),
25899 assign( byte
[i
+8], binop( Iop_And64
,
25901 unop( Iop_V128to64
,
25902 mkexpr( store_val
) ),
25906 assign( tmp_low
[i
+1],
25908 mkexpr( tmp_low
[i
] ),
25909 binop( Iop_Shl64
, mkexpr( byte
[i
] ), mkU8( i
*8 ) ) ) );
25910 assign( tmp_hi
[i
+1],
25912 mkexpr( tmp_hi
[i
] ),
25913 binop( Iop_Shl64
, mkexpr( byte
[i
+8] ),
25917 /* Store the value in 32-byte chunks */
25919 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
25920 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
25922 store( irx_addr
, unop( Iop_64to32
, mkexpr( tmp_low
[8] ) ) );
25925 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
25926 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
25928 store( irx_addr
, unop( Iop_64HIto32
, mkexpr( tmp_low
[8] ) ) );
25931 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
25932 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
25934 store( irx_addr
, unop( Iop_64to32
, mkexpr( tmp_hi
[8] ) ) );
25937 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( base_addr
),
25938 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
25940 store( irx_addr
, unop( Iop_64HIto32
, mkexpr( tmp_hi
[8] ) ) );
25947 IRTemp high64
= newTemp(Ity_F64
);
25948 IRTemp val32
= newTemp(Ity_I32
);
25949 DIP("stxsspx %u,r%u,r%u\n", (UInt
)XS
, rA_addr
, rB_addr
);
25950 assign(high64
, unop( Iop_ReinterpI64asF64
,
25951 unop( Iop_V128HIto64
, mkexpr( vS
) ) ) );
25952 assign(val32
, unop( Iop_ReinterpF32asI32
,
25953 unop( Iop_TruncF64asF32
,
25954 mkexpr(high64
) ) ) );
25955 store( mkexpr( EA
), mkexpr( val32
) );
25961 DIP("stxsdx %u,r%u,r%u\n", (UInt
)XS
, rA_addr
, rB_addr
);
25962 high64
= unop( Iop_V128HIto64
, mkexpr( vS
) );
25963 store( mkexpr( EA
), high64
);
25967 case 0x38D: // stxsibx
25969 IRTemp byte_to_store
= newTemp( Ity_I8
);
25971 DIP("stxsibx %u,r%u,r%u\n", (UInt
)XS
, rA_addr
, rB_addr
);
25973 assign( byte_to_store
, unop( Iop_64to8
,
25974 unop( Iop_V128HIto64
,
25975 mkexpr( vS
) ) ) );
25977 store( mkexpr( EA
), mkexpr( byte_to_store
) );
25981 case 0x3AD: // stxsihx
25983 IRTemp hword_to_store
= newTemp( Ity_I16
);
25985 DIP("stxsihx %u,r%u,r%u\n", (UInt
)XS
, rA_addr
, rB_addr
);
25987 assign( hword_to_store
, unop( Iop_64to16
,
25988 unop( Iop_V128HIto64
,
25989 mkexpr( vS
) ) ) );
25991 store( mkexpr( EA
), mkexpr( hword_to_store
) );
25997 IRExpr
* high64
, *low64
;
25998 DIP("stxvd2x %u,r%u,r%u\n", (UInt
)XS
, rA_addr
, rB_addr
);
25999 high64
= unop( Iop_V128HIto64
, mkexpr( vS
) );
26000 low64
= unop( Iop_V128to64
, mkexpr( vS
) );
26001 store( mkexpr( EA
), high64
);
26002 store( binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
26003 ty
== Ity_I64
? mkU64( 8 ) : mkU32( 8 ) ), low64
);
26010 IRTemp hi64
= newTemp( Ity_I64
);
26011 IRTemp lo64
= newTemp( Ity_I64
);
26013 DIP("stxvw4x %u,r%u,r%u\n", (UInt
)XS
, rA_addr
, rB_addr
);
26015 // This instruction supports word-aligned stores, so EA may not be
26016 // quad-word aligned. Therefore, do 4 individual word-size stores.
26017 assign( hi64
, unop( Iop_V128HIto64
, mkexpr( vS
) ) );
26018 assign( lo64
, unop( Iop_V128to64
, mkexpr( vS
) ) );
26019 store( mkexpr( EA
), unop( Iop_64HIto32
, mkexpr( hi64
) ) );
26021 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
26022 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
26023 store( irx_addr
, unop( Iop_64to32
, mkexpr( hi64
) ) );
26025 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
26026 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
26027 store( irx_addr
, unop( Iop_64HIto32
, mkexpr( lo64
) ) );
26029 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
26030 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
26031 store( irx_addr
, unop( Iop_64to32
, mkexpr( lo64
) ) );
26035 case 0x3AC: // stxvh8x Store VSX Vector Halfword*8 Indexed
26039 IRTemp half_word0
= newTemp( Ity_I64
);
26040 IRTemp half_word1
= newTemp( Ity_I64
);
26041 IRTemp half_word2
= newTemp( Ity_I64
);
26042 IRTemp half_word3
= newTemp( Ity_I64
);
26043 IRTemp half_word4
= newTemp( Ity_I64
);
26044 IRTemp half_word5
= newTemp( Ity_I64
);
26045 IRTemp half_word6
= newTemp( Ity_I64
);
26046 IRTemp half_word7
= newTemp( Ity_I64
);
26048 DIP("stxvb8x %u,r%u,r%u\n", (UInt
)XS
, rA_addr
, rB_addr
);
26050 assign( half_word0
, binop( Iop_Shr64
,
26051 unop( Iop_V128HIto64
, mkexpr( vS
) ),
26054 assign( half_word1
, binop( Iop_And64
,
26056 unop( Iop_V128HIto64
, mkexpr( vS
) ),
26058 mkU64( 0xFFFF ) ) );
26060 assign( half_word2
, binop( Iop_And64
,
26062 unop( Iop_V128HIto64
, mkexpr( vS
) ),
26064 mkU64( 0xFFFF ) ) );
26066 assign( half_word3
, binop( Iop_And64
,
26067 unop( Iop_V128HIto64
, mkexpr( vS
) ),
26068 mkU64( 0xFFFF ) ) );
26070 assign( half_word4
, binop( Iop_Shr64
,
26071 unop( Iop_V128to64
, mkexpr( vS
) ),
26074 assign( half_word5
, binop( Iop_And64
,
26076 unop( Iop_V128to64
, mkexpr( vS
) ),
26078 mkU64( 0xFFFF ) ) );
26080 assign( half_word6
, binop( Iop_And64
,
26082 unop( Iop_V128to64
, mkexpr( vS
) ),
26084 mkU64( 0xFFFF ) ) );
26086 assign( half_word7
, binop( Iop_And64
,
26087 unop( Iop_V128to64
, mkexpr( vS
) ),
26088 mkU64( 0xFFFF ) ) );
26090 /* Do the 32-bit stores. The store() does an Endian aware store. */
26091 if ( host_endness
== VexEndnessBE
) {
26092 store( mkexpr( EA
), unop( Iop_64to32
,
26094 mkexpr( half_word1
),
26096 mkexpr( half_word0
),
26097 mkU8( 16 ) ) ) ) );
26100 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
26101 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
26104 store( irx_addr
, unop( Iop_64to32
,
26106 mkexpr( half_word3
),
26108 mkexpr( half_word2
),
26109 mkU8( 16 ) ) ) ) );
26112 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
26113 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
26115 store( irx_addr
, unop( Iop_64to32
,
26117 mkexpr( half_word5
),
26119 mkexpr( half_word4
),
26120 mkU8( 16 ) ) ) ) );
26122 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
26123 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
26125 store( irx_addr
, unop( Iop_64to32
,
26127 mkexpr( half_word7
),
26129 mkexpr( half_word6
),
26130 mkU8( 16 ) ) ) ) );
26133 store( mkexpr( EA
), unop( Iop_64to32
,
26135 mkexpr( half_word0
),
26137 mkexpr( half_word1
),
26138 mkU8( 16 ) ) ) ) );
26141 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
26142 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
26144 store( irx_addr
, unop( Iop_64to32
,
26146 mkexpr( half_word2
),
26148 mkexpr( half_word3
),
26149 mkU8( 16 ) ) ) ) );
26151 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
26152 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
26154 store( irx_addr
, unop( Iop_64to32
,
26156 mkexpr( half_word4
),
26158 mkexpr( half_word5
),
26159 mkU8( 16 ) ) ) ) );
26161 irx_addr
= binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
26162 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
26164 store( irx_addr
, unop( Iop_64to32
,
26166 mkexpr( half_word6
),
26168 mkexpr( half_word7
),
26169 mkU8( 16 ) ) ) ) );
26174 case 0x3EC: // stxvb16x Store VSX Vector Byte*16 Indexed
26181 DIP("stxvb16x %u,r%u,r%u\n", (UInt
)XS
, rA_addr
, rB_addr
);
26183 for ( i
= 0; i
< 8; i
++ ) {
26184 byte
[i
] = newTemp( Ity_I64
);
26185 byte
[i
+8] = newTemp( Ity_I64
);
26187 assign( byte
[i
], binop( Iop_And64
,
26189 unop( Iop_V128HIto64
, mkexpr( vS
) ),
26190 mkU8( 56 - i
*8 ) ),
26193 assign( byte
[i
+8], binop( Iop_And64
,
26195 unop( Iop_V128to64
, mkexpr( vS
) ),
26200 if ( host_endness
== VexEndnessBE
) {
26201 for ( i
= 0; i
< 16; i
= i
+ 4) {
26203 binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
26204 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
26210 mkexpr( byte
[i
+3] ),
26212 mkexpr( byte
[i
+2] ),
26216 mkexpr( byte
[i
+1] ),
26220 mkU8( 24 ) ) ) ) ) );
26225 for ( i
= 0; i
< 16; i
= i
+ 4) {
26227 binop( mkSzOp( ty
, Iop_Add8
), mkexpr( EA
),
26228 ty
== Ity_I64
? mkU64( ea_off
) : mkU32( ea_off
) );
26236 mkexpr( byte
[i
+1] ),
26240 mkexpr( byte
[i
+2] ),
26243 mkexpr( byte
[i
+3] ),
26244 mkU8( 24 ) ) ) ) ) );
26253 vex_printf( "dis_vx_store(ppc)(opc2)\n" );
26260 dis_vx_Scalar_Round_to_quad_integer( UInt prefix
, UInt theInstr
,
26261 const VexAbiInfo
* vbi
)
26263 /* The ISA 3.0 instructions supported in this function require
26264 * the underlying hardware platform that supports the ISA3.0
26268 UChar opc1
= ifieldOPC( theInstr
);
26269 UInt opc2
= IFIELD( theInstr
, 1, 8 );
26270 UChar vT_addr
= ifieldRegDS( theInstr
);
26271 UChar vB_addr
= ifieldRegB( theInstr
);
26272 IRTemp vB
= newTemp( Ity_F128
);
26273 IRTemp vT
= newTemp( Ity_F128
);
26274 UChar EX
= IFIELD( theInstr
, 0, 1 );
26276 /* There is no prefixed version of these instructions. */
26279 assign( vB
, getF128Reg( vB_addr
) );
26280 if (opc1
!= 0x3F) {
26281 vex_printf( "dis_vx_Scalar_Round_to_quad_integer(ppc)(instr)\n" );
26285 case 0x005: // VSX Scalar Round to Quad-Precision Integer [with Inexact]
26287 UChar R
= IFIELD( theInstr
, 16, 1 );
26288 UChar RMC
= IFIELD( theInstr
, 9, 2 );
26290 /* Store the rm specification bits. Will extract them later when
26291 * the isntruction is issued.
26293 IRExpr
* rm
= mkU32( R
<< 3 | RMC
<< 1 | EX
);
26295 if ( EX
== 0 ) { // xsrqpi
26296 DIP("xsrqpi %d,v%d,v%d,%d\n", R
, vT_addr
, vB_addr
, RMC
);
26297 assign( vT
, binop( Iop_F128toI128S
, rm
, mkexpr( vB
) ) );
26299 } else { // xsrqpix
26300 DIP("xsrqpix %d,v%d,v%d,%d\n", R
, vT_addr
, vB_addr
, RMC
);
26301 assign( vT
, binop( Iop_F128toI128S
, rm
, mkexpr( vB
) ) );
26303 generate_store_FPRF( Ity_F128
, vT
, vbi
);
26306 case 0x025: // xsrqpxp VSX Scalar Round Quad-Precision to
26307 // Double-Extended Precision
26309 UChar R
= IFIELD( theInstr
, 16, 1 );
26310 UChar RMC
= IFIELD( theInstr
, 9, 2 );
26312 /* Store the rm specification bits. Will extract them later when
26313 * the isntruction is issued.
26315 IRExpr
* rm
= mkU32( R
<< 3 | RMC
<< 1 );
26317 DIP("xsrqpxp %d,v%d,v%d,%d\n", R
, vT_addr
, vB_addr
, RMC
);
26318 assign( vT
, binop( Iop_RndF128
, rm
, mkexpr( vB
) ) );
26319 generate_store_FPRF( Ity_F128
, vT
, vbi
);
26323 vex_printf( "dis_vx_Scalar_Round_to_quad_integer(ppc)(opc2)\n" );
26325 } /* switch opc2 */
26326 putF128Reg( vT_addr
, mkexpr( vT
) );
26331 dis_vx_Floating_Point_Arithmetic_quad_precision( UInt prefix
, UInt theInstr
,
26332 const VexAbiInfo
* vbi
)
26334 /* The ISA 3.0 instructions supported in this function require
26335 * the underlying hardware platform that supports the ISA 3.0
26339 UChar opc1
= ifieldOPC( theInstr
);
26340 UInt opc2
= ifieldOPClo10( theInstr
);
26341 UChar vT_addr
= ifieldRegDS( theInstr
);
26342 UChar vA_addr
= ifieldRegA( theInstr
);
26343 UChar vB_addr
= ifieldRegB( theInstr
);
26344 IRTemp vA
= newTemp( Ity_F128
);
26345 IRTemp vB
= newTemp( Ity_F128
);
26346 IRTemp vT
= newTemp( Ity_F128
);
26347 IRExpr
* rm
= get_IR_roundingmode();
26348 UChar R0
= IFIELD( theInstr
, 0, 1 );
26350 /* There is no prefixed version of these instructions. */
26353 assign( vB
, getF128Reg( vB_addr
) );
26355 if ( opc1
!= 0x3F ) {
26356 vex_printf( "Erorr, dis_vx_Floating_Point_Arithmetic_quad_precision(ppc)(instr)\n" );
26360 case 0x004: // xsaddqp (VSX Scalar Add Quad-Precision[using round to Odd])
26362 assign( vA
, getF128Reg( vA_addr
) );
26365 /* rounding mode specified by RN. Issue inst with R0 = 0 */
26366 DIP("xsaddqp v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
26367 assign( vT
, triop( Iop_AddF128
, rm
, mkexpr( vA
), mkexpr( vB
) ) );
26370 /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
26371 DIP("xsaddqpo v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
26372 assign( vT
, triop( Iop_AddF128
, set_round_to_Oddmode(),
26373 mkexpr( vA
), mkexpr( vB
) ) );
26375 generate_store_FPRF( Ity_F128
, vT
, vbi
);
26378 case 0x024: // xsmulqp (VSX Scalar Multiply Quad-Precision[using round to Odd])
26380 assign( vA
, getF128Reg( vA_addr
) );
26383 /* rounding mode specified by RN. Issue inst with R0 = 0 */
26384 DIP("xsmulqp v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
26385 assign( vT
, triop( Iop_MulF128
, rm
, mkexpr( vA
), mkexpr( vB
) ) );
26388 /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
26389 DIP("xsmulqpo v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
26390 assign( vT
, triop( Iop_MulF128
, set_round_to_Oddmode(), mkexpr( vA
),
26393 generate_store_FPRF( Ity_F128
, vT
, vbi
);
26396 case 0x184: // xsmaddqp (VSX Scalar Multiply add Quad-Precision[using round to Odd])
26398 /* instruction computes (vA * vB) + vC */
26399 IRTemp vC
= newTemp( Ity_F128
);
26401 assign( vA
, getF128Reg( vA_addr
) );
26402 assign( vC
, getF128Reg( vT_addr
) );
26405 /* rounding mode specified by RN. Issue inst with R0 = 0 */
26406 DIP("xsmaddqp v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
26408 qop( Iop_MAddF128
, rm
, mkexpr( vA
),
26409 mkexpr( vC
), mkexpr( vB
) ) );
26412 /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
26413 DIP("xsmaddqpo v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
26415 qop( Iop_MAddF128
, set_round_to_Oddmode(), mkexpr( vA
),
26416 mkexpr( vC
), mkexpr( vB
) ) );
26418 generate_store_FPRF( Ity_F128
, vT
, vbi
);
26421 case 0x1A4: // xsmsubqp (VSX Scalar Multiply Subtract Quad-Precision[using round to Odd])
26423 IRTemp vC
= newTemp( Ity_F128
);
26425 assign( vA
, getF128Reg( vA_addr
) );
26426 assign( vC
, getF128Reg( vT_addr
) );
26429 /* rounding mode specified by RN. Issue inst with R0 = 0 */
26430 DIP("xsmsubqp v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
26432 qop( Iop_MSubF128
, rm
, mkexpr( vA
),
26433 mkexpr( vC
), mkexpr( vB
) ) );
26436 /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
26437 DIP("xsmsubqpo v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
26439 qop( Iop_MSubF128
, set_round_to_Oddmode(),
26440 mkexpr( vA
), mkexpr( vC
), mkexpr( vB
) ) );
26442 generate_store_FPRF( Ity_F128
, vT
, vbi
);
26445 case 0x1C4: // xsnmaddqp (VSX Scalar Negative Multiply Add Quad-Precision[using round to Odd])
26447 IRTemp vC
= newTemp( Ity_F128
);
26449 assign( vA
, getF128Reg( vA_addr
) );
26450 assign( vC
, getF128Reg( vT_addr
) );
26453 /* rounding mode specified by RN. Issue inst with R0 = 0 */
26454 DIP("xsnmaddqp v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
26456 qop( Iop_NegMAddF128
, rm
, mkexpr( vA
),
26457 mkexpr( vC
), mkexpr( vB
) ) );
26460 /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
26461 DIP("xsnmaddqpo v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
26463 qop( Iop_NegMAddF128
, set_round_to_Oddmode(),
26464 mkexpr( vA
), mkexpr( vC
), mkexpr( vB
) ) );
26466 generate_store_FPRF( Ity_F128
, vT
, vbi
);
26469 case 0x1E4: // xsmsubqp (VSX Scalar Negatve Multiply Subtract Quad-Precision[using round to Odd])
26471 IRTemp vC
= newTemp( Ity_F128
);
26473 assign( vA
, getF128Reg( vA_addr
) );
26474 assign( vC
, getF128Reg( vT_addr
) );
26477 /* rounding mode specified by RN. Issue inst with R0 = 0 */
26478 DIP("xsnmsubqp v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
26480 qop( Iop_NegMSubF128
, rm
, mkexpr( vA
),
26481 mkexpr( vC
), mkexpr( vB
) ) );
26484 /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
26485 DIP("xsnmsubqpo v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
26487 qop( Iop_NegMSubF128
, set_round_to_Oddmode(),
26488 mkexpr( vA
), mkexpr( vC
), mkexpr( vB
) ) );
26490 generate_store_FPRF( Ity_F128
, vT
, vbi
);
26493 case 0x204: // xssubqp (VSX Scalar Subtract Quad-Precision[using round to Odd])
26495 assign( vA
, getF128Reg( vA_addr
) );
26497 /* use rounding mode specified by RN. Issue inst with R0 = 0 */
26498 DIP("xssubqp v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
26499 assign( vT
, triop( Iop_SubF128
, rm
, mkexpr( vA
), mkexpr( vB
) ) );
26502 /* use rounding mode specified by Round to odd. Issue inst with R0 = 1 */
26503 DIP("xssubqpo v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
26504 assign( vT
, triop( Iop_SubF128
, set_round_to_Oddmode(), mkexpr( vA
),
26507 generate_store_FPRF( Ity_F128
, vT
, vbi
);
26510 case 0x224: // xsdivqp (VSX Scalar Divide Quad-Precision[using round to Odd])
26512 assign( vA
, getF128Reg( vA_addr
) );
26514 /* use rounding mode specified by RN. Issue inst with R0 = 0 */
26515 DIP("xsdivqp v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
26516 assign( vT
, triop( Iop_DivF128
, rm
, mkexpr( vA
), mkexpr( vB
) ) );
26519 /* use rounding mode specified by Round to odd. Issue inst with R0 = 1 */
26520 DIP("xsdivqpo v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
26521 assign( vT
, triop( Iop_DivF128
, set_round_to_Oddmode(), mkexpr( vA
),
26524 generate_store_FPRF( Ity_F128
, vT
, vbi
);
26527 case 0x324: // xssqrtqp (VSX Scalar Square root Quad-Precision[using round to Odd])
26529 UInt inst_select
= IFIELD( theInstr
, 16, 5 );
26531 switch (inst_select
) {
26534 if ( R0
== 0 ) { // xssqrtqp
26535 /* rounding mode specified by RN. Issue inst with R0 = 0 */
26536 DIP("xssqrtqp v%d,v%d\n", vT_addr
, vB_addr
);
26537 assign( vT
, binop( Iop_SqrtF128
, rm
, mkexpr( vB
) ) );
26539 } else { // xssqrtqpo
26540 /* rounding mode is Round to odd. Issue inst with R0 = 1 */
26541 DIP("xssqrtqpo v%d,v%d\n", vT_addr
, vB_addr
);
26542 assign( vT
, binop( Iop_SqrtF128
, set_round_to_Oddmode(),
26545 generate_store_FPRF( Ity_F128
, vT
, vbi
);
26547 } /* end case 27 */
26549 vex_printf("dis_vx_Floating_Point_Arithmetic_quad_precision(0x324 unknown inst_select)\n");
26551 } /* end switch inst_select */
26553 } /* end case 0x324 */
26557 UInt inst_select
= IFIELD( theInstr
, 16, 5);
26559 switch (inst_select
) {
26560 case 0: // xscvqpuqz, VSX Scalar Convert with round to zero
26561 // Quad-Precision to Unsigned Quadword X-form
26563 DIP("xscvqpuqz, v%d,v%d\n", vT_addr
, vB_addr
);
26564 assign( vT
, unop( Iop_TruncF128toI128U
, mkexpr( vB
) ) );
26567 case 1: // xscvqpuwz VSX Scalar Truncate & Convert Quad-Precision
26568 // format to Unsigned Word format
26570 DIP("xscvqpuwz v%d,v%d\n", vT_addr
, vB_addr
);
26571 assign( vT
, unop( Iop_TruncF128toI32U
, mkexpr( vB
) ) );
26574 case 2: // xscvudqp VSX Scalar Convert from Unsigned Doubleword
26575 // format to Quad-Precision format
26577 IRTemp tmp
= newTemp( Ity_I64
);
26579 DIP("xscvudqp v%d,v%d\n", vT_addr
, vB_addr
);
26580 assign( tmp
, unop( Iop_ReinterpF64asI64
,
26581 unop( Iop_F128HItoF64
, mkexpr( vB
) ) ) );
26582 assign( vT
, unop( Iop_I64UtoF128
, mkexpr( tmp
) ) );
26583 generate_store_FPRF( Ity_F128
, vT
, vbi
);
26586 case 3: // xscvuqqp, VSX Scalar Convert Unsigned Quadword
26587 // to Quad-Precision X-form
26589 DIP("xscvqpuqz, v%d,v%d\n", vT_addr
, vB_addr
);
26591 binop( Iop_I128UtoF128
, rm
,
26592 unop ( Iop_ReinterpF128asI128
,
26593 getF128Reg( vB_addr
) ) ) );
26594 generate_store_FPRF( Ity_F128
, vT
, vbi
);
26597 case 8: // xscvqpsqz, VSX Scalar Convert with round to zero
26598 // Quad-Precision to Signed Quadword X-form
26600 DIP("xscvqpsqz, v%d,v%d\n", vT_addr
, vB_addr
);
26601 assign( vT
, unop( Iop_TruncF128toI128S
, mkexpr( vB
) ) );
26604 case 9: // xsvqpswz VSX Scalar Truncate & Convert Quad-Precision
26605 // format to Signed Word format
26607 DIP("xscvqpswz v%d,v%d\n", vT_addr
, vB_addr
);
26608 assign( vT
, unop( Iop_TruncF128toI32S
, mkexpr( vB
) ) );
26611 case 10: // xscvsdqp VSX Scalar from Signed Doubleword format
26612 // Quad-Precision format
26614 IRTemp tmp
= newTemp( Ity_I64
);
26616 DIP("xscvsdqp v%d,v%d\n", vT_addr
, vB_addr
);
26618 assign( tmp
, unop( Iop_ReinterpF64asI64
,
26619 unop( Iop_F128HItoF64
, mkexpr( vB
) ) ) );
26620 assign( vT
, unop( Iop_I64StoF128
, mkexpr( tmp
) ) );
26621 generate_store_FPRF( Ity_F128
, vT
, vbi
);
26624 case 11: // xscvsqqp, VSX Scalar Convert Unsigned Quadword
26625 // to Quad-Precision X-form
26627 DIP("xscvsqqp, v%d,v%d\n", vT_addr
, vB_addr
);
26629 binop( Iop_I128StoF128
, rm
,
26630 unop ( Iop_ReinterpF128asI128
,
26631 mkexpr( vB
) ) ) );
26632 generate_store_FPRF( Ity_F128
, vT
, vbi
);
26635 case 17: // xsvqpudz VSX Scalar Truncate & Convert Quad-Precision
26636 // format to Unigned Doubleword format
26638 DIP("xscvqpudz v%d,v%d\n", vT_addr
, vB_addr
);
26639 assign( vT
, unop( Iop_TruncF128toI64U
, mkexpr( vB
) ) );
26642 case 20: // xscvqpdp Scalar round & Conver Quad-Precision
26643 // format to Double-Precision format [using round to Odd]
26645 IRTemp ftmp
= newTemp( Ity_F64
);
26646 IRTemp tmp
= newTemp( Ity_I64
);
26648 /* This instruction takes a 128-bit floating point value and
26649 * converts it to a 64-bit floating point value. The 64-bit
26650 * result is stored in the upper 64-bit of the 128-bit result
26651 * register. The lower 64-bit are undefined.
26653 if (R0
== 0) { // xscvqpdp
26654 /* rounding mode specified by RN. Issue inst with R0 = 0 */
26655 DIP("xscvqpdp v%d,v%d\n", vT_addr
, vB_addr
);
26657 assign( ftmp
, binop( Iop_F128toF64
, rm
, mkexpr( vB
) ) );
26659 } else { // xscvqpdpo
26660 /* rounding mode is Round to odd. Issue inst with R0 = 1 */
26661 DIP("xscvqpdpo v%d,v%d\n", vT_addr
, vB_addr
);
26663 binop( Iop_F128toF64
,
26664 set_round_to_Oddmode(), mkexpr( vB
) ) );
26667 /* store 64-bit float in upper 64-bits of 128-bit register,
26668 * lower 64-bits are zero.
26670 if (host_endness
== VexEndnessLE
)
26672 binop( Iop_F64HLtoF128
,
26674 unop( Iop_ReinterpI64asF64
, mkU64( 0 ) ) ) );
26677 binop( Iop_F64HLtoF128
,
26678 unop( Iop_ReinterpI64asF64
, mkU64( 0 ) ),
26679 mkexpr( ftmp
) ) );
26681 assign( tmp
, unop( Iop_ReinterpF64asI64
,
26682 unop( Iop_F128HItoF64
, mkexpr( vT
) ) ) );
26684 generate_store_FPRF( Ity_I64
, tmp
, vbi
);
26687 case 22: // xscvdpqp VSX Scalar Convert from Double-Precision
26688 // format to Quad-Precision format
26690 DIP("xscvdpqp v%d,v%d\n", vT_addr
, vB_addr
);
26691 /* The 64-bit value is in the upper 64 bit of the src */
26692 assign( vT
, unop( Iop_F64toF128
,
26693 unop( Iop_F128HItoF64
, mkexpr( vB
) ) ) );
26695 generate_store_FPRF( Ity_F128
, vT
, vbi
);
26698 case 25: // xsvqpsdz VSX Scalar Truncate & Convert Quad-Precision
26699 // format to Signed Doubleword format
26701 DIP("xscvqpsdz v%d,v%d\n", vT_addr
, vB_addr
);
26702 assign( vT
, unop( Iop_TruncF128toI64S
, mkexpr( vB
) ) );
26706 vex_printf( "dis_vx_Floating_Point_Arithmetic_quad_precision invalid inst_select (ppc)(opc2)\n" );
26708 } /* switch inst_select */
26709 } /* end case 0x344 */
26711 default: /* switch opc2 */
26712 vex_printf( "dis_vx_Floating_Point_Arithmetic_quad_precision(ppc)(opc2)\n" );
26715 putF128Reg( vT_addr
, mkexpr( vT
) );
26720 /* VSX Scalar Quad-Precision instructions */
26722 dis_vx_scalar_quad_precision ( UInt prefix
, UInt theInstr
)
26724 /* This function emulates the 128-bit floating point instructions
26725 * using existing 128-bit vector instructions (Iops). The 128-bit
26726 * floating point instructions use the same 128-bit vector register
26730 UChar opc1
= ifieldOPC( theInstr
);
26731 UInt opc2
= ifieldOPClo10( theInstr
);
26732 UChar VRT
= ifieldRegDS( theInstr
);
26733 UChar VRA
= ifieldRegA( theInstr
);
26734 UChar VRB
= ifieldRegB( theInstr
);
26735 UChar vT_addr
= VRT
+ 32;
26736 UChar vA_addr
= VRA
+ 32;
26737 UChar vB_addr
= VRB
+ 32;
26738 IRTemp vA
= newTemp( Ity_V128
);
26739 IRTemp vB
= newTemp( Ity_V128
);
26740 IRTemp vT
= newTemp( Ity_V128
);
26742 /* There is no prefixed version of these instructions. */
26745 assign( vB
, getVSReg( vB_addr
) );
26747 if (opc1
!= 0x3F) {
26748 vex_printf( "dis_vx_scalar_quad_precision(ppc)(instr)\n" );
26754 case 0x044: // xscmpeqqp (VSX Scalar Compare Equal Quad-Precision X-form)
26756 IRTemp vA_hi
= newTemp( Ity_I64
);
26757 IRTemp vA_lo
= newTemp( Ity_I64
);
26758 IRTemp vB_hi
= newTemp( Ity_I64
);
26759 IRTemp vB_lo
= newTemp( Ity_I64
);
26760 IRTemp tmp
= newTemp( Ity_I64
);
26761 IRTemp src_not_NaN
= newTemp( Ity_I64
);
26763 /* NOTE: exceptions are not implemented, will not set VXSNAN, VXVC or
26765 DIP("xscmpeqqp v%u,v%u,v%u\n", VRT
, VRA
, VRB
);
26767 assign( vA
, getVSReg( vA_addr
) );
26769 /* neither vA or vB is NaN */
26770 assign( src_not_NaN
,
26773 mkOR1( is_NaN( Ity_V128
, vA
),
26774 is_NaN( Ity_V128
, vB
) ) ) ) );
26776 assign( vA_hi
, unop( Iop_V128HIto64
, mkexpr( vA
) ) );
26777 assign( vA_lo
, unop( Iop_V128to64
, mkexpr( vA
) ) );
26778 assign( vB_hi
, unop( Iop_V128HIto64
, mkexpr( vB
) ) );
26779 assign( vB_lo
, unop( Iop_V128to64
, mkexpr( vB
) ) );
26783 mkexpr( src_not_NaN
),
26786 binop( Iop_CmpEQ64
,
26788 mkexpr( vB_hi
) ) ),
26790 binop( Iop_CmpEQ64
,
26792 mkexpr( vB_lo
) ) ) ) ) );
26793 assign( vT
, binop( Iop_64HLtoV128
, mkexpr( tmp
), mkexpr( tmp
) ) );
26797 case 0x064: // xscpsgnqp (VSX Scalar Copy Sign Quad-Precision)
26799 IRTemp sign_vA
= newTemp( Ity_I64
);
26800 IRTemp vB_hi
= newTemp( Ity_I64
);
26802 DIP("xscpsgnqp v%u,v%u,v%u\n", VRT
, VRA
, VRB
);
26804 assign( vA
, getVSReg(vA_addr
) );
26806 assign( sign_vA
, binop( Iop_And64
,
26807 unop( Iop_V128HIto64
,
26809 mkU64( 0x8000000000000000ULL
) ) );
26810 assign( vB_hi
, binop( Iop_Or64
,
26812 unop( Iop_V128HIto64
,
26814 mkU64( 0x7FFFFFFFFFFFFFFFULL
) ),
26815 mkexpr( sign_vA
) ) );
26816 assign( vT
, binop( Iop_64HLtoV128
,
26818 unop( Iop_V128to64
, mkexpr( vB
) ) ) );
26822 case 0x0C4: // xscmpgeqp (VSX Scalar Compare Greater Than or
26823 // Equal Quad-Precision X-form)
26825 IRTemp tmp
= newTemp( Ity_I64
);
26826 IRTemp src_not_NaN
= newTemp( Ity_I64
);
26828 /* NOTE: exceptions are not implemented, will not set VXSNAN, VXVC or
26830 DIP("xscmpgeqp v%u,v%u,v%u\n", VRT
, VRA
, VRB
);
26832 assign( vA
, getVSReg( vA_addr
) );
26834 /* neither vA or vB is NaN */
26835 assign( src_not_NaN
,
26838 mkOR1( is_NaN( Ity_V128
, vA
),
26839 is_NaN( Ity_V128
, vB
) ) ) ) );
26841 /* vA >= vB is Not( vB > vA) */
26844 mkexpr( src_not_NaN
),
26847 Quad_precision_gt( vB
, vA
) ) ) ) ) ;
26848 assign( vT
, binop( Iop_64HLtoV128
, mkexpr( tmp
), mkexpr( tmp
) ) );
26852 case 0x0E4: // xscmpgtqp (VSX Scalar Compare Greater Than
26853 // Quad-Precision X-form)
26855 IRTemp tmp
= newTemp( Ity_I64
);
26856 IRTemp src_not_NaN
= newTemp( Ity_I64
);
26858 /* NOTE: exceptions are not implemented, will not set VXSNAN, VXVC or
26860 DIP("xscmpgtqp v%u,v%u,v%u\n", VRT
, VRA
, VRB
);
26862 assign( vA
, getVSReg( vA_addr
) );
26864 /* neither vA or vB is NaN */
26865 assign( src_not_NaN
,
26868 mkOR1( is_NaN( Ity_V128
, vA
),
26869 is_NaN( Ity_V128
, vB
) ) ) ) );
26873 mkexpr( src_not_NaN
),
26874 unop( Iop_1Sto64
, Quad_precision_gt( vA
, vB
) ) ) );
26876 assign( vT
, binop( Iop_64HLtoV128
, mkexpr( tmp
), mkexpr( tmp
) ) );
26880 case 0x084: // xscmpoqp (VSX Scalar Compare Ordered Quad-Precision)
26881 case 0x284: // xscmpuqp (VSX Scalar Compare Unrdered Quad-Precision)
26883 /* Note, only differece between xscmoqp and xscmpuqp is the
26884 exception flag settings which are not supported anyway. */
26885 IRExpr
*bit4
, *bit5
, *bit6
, *bit7
;
26886 IRExpr
*bit_zero
, *bit_inf
, *same_sign
;
26887 UInt BF
= IFIELD( theInstr
, 23, 3 );
26888 IRTemp eq_lt_gt
= newTemp( Ity_I32
);
26889 IRTemp CC
= newTemp( Ity_I32
);
26891 if (opc2
== 0x084) {
26892 DIP("xscmpoqp %u,v%d,v%u\n", BF
, VRA
, VRB
);
26894 DIP("xscmpuqp %u,v%d,v%u\n", BF
, VRA
, VRB
);
26897 assign( vA
, getVSReg(vA_addr
));
26899 /* A and B have the same sign */
26900 same_sign
= binop( Iop_CmpEQ64
,
26902 unop( Iop_V128HIto64
,
26906 unop( Iop_V128HIto64
,
26911 bit4
= Quad_precision_gt( vB
, vA
);
26914 bit5
= Quad_precision_gt( vA
, vB
);
26917 bit6
= mkAND1( binop( Iop_CmpEQ64
,
26918 unop( Iop_V128HIto64
,
26920 unop( Iop_V128HIto64
,
26922 binop( Iop_CmpEQ64
,
26923 unop( Iop_V128to64
,
26925 unop( Iop_V128to64
,
26926 mkexpr( vB
) ) ) );
26928 /* test both zero don't care about sign */
26929 bit_zero
= mkAND1( is_Zero( Ity_V128
, vA
), is_Zero( Ity_V128
, vB
) );
26931 /* test both for infinity, don't care about sign */
26933 mkAND1( is_Inf( Ity_V128
, vA
), is_Inf( Ity_V128
, vB
) ),
26934 binop( Iop_CmpEQ64
,
26936 unop( Iop_V128to64
,
26938 mkU64( 0x80000000) ),
26940 unop( Iop_V128to64
,
26942 mkU64( 0x80000000) ) ) );
26944 /* exp A or exp B is NaN */
26945 bit7
= mkOR1( is_NaN( Ity_V128
, vA
),
26946 is_NaN( Ity_V128
, vB
) );
26952 unop( Iop_1Uto32
, bit4
),
26955 unop( Iop_1Uto32
, bit5
),
26959 unop( Iop_1Uto32
, bit6
),
26968 mkAND1( bit_inf
, same_sign
) ),
26969 mkU8( 1 ) ) ) ) ) );
26971 assign(CC
, binop( Iop_Or32
,
26974 unop( Iop_1Sto32
, bit7
) ),
26975 mkexpr( eq_lt_gt
) ),
26976 unop( Iop_1Uto32
, bit7
) ) );
26978 /* put result of the comparison into CC and FPCC */
26979 putGST_field( PPC_GST_CR
, mkexpr( CC
), BF
);
26980 putFPCC( mkexpr( CC
) );
26985 case 0xA4: // xscmpexpqp (VSX Scalar Compare Exponents Double-Precision)
26987 IRExpr
*bit4
, *bit5
, *bit6
, *bit7
;
26988 UInt BF
= IFIELD( theInstr
, 23, 3 );
26990 IRTemp eq_lt_gt
= newTemp( Ity_I32
);
26991 IRTemp CC
= newTemp( Ity_I32
);
26993 DIP("xscmpexpqp %u,v%u,v%u\n", BF
, VRA
, VRB
);
26995 assign( vA
, getVSReg(vA_addr
));
26997 /* A exp < B exp */
26998 bit4
= binop( Iop_CmpLT64U
,
27000 unop( Iop_V128HIto64
,
27002 mkU64( 0x7FFF000000000000 ) ),
27004 unop( Iop_V128HIto64
,
27006 mkU64( 0x7FFF000000000000 ) ) );
27008 bit5
= binop( Iop_CmpLT64U
,
27010 unop( Iop_V128HIto64
,
27012 mkU64( 0x7FFF000000000000 ) ),
27014 unop( Iop_V128HIto64
,
27016 mkU64( 0x7FFF000000000000 ) ) );
27018 bit6
= binop( Iop_CmpEQ64
,
27020 unop( Iop_V128HIto64
,
27022 mkU64( 0x7FFF000000000000 ) ),
27024 unop( Iop_V128HIto64
,
27026 mkU64( 0x7FFF000000000000 ) ) );
27028 /* exp A or exp B is NaN */
27029 bit7
= mkOR1( is_NaN( Ity_V128
, vA
),
27030 is_NaN( Ity_V128
, vB
) );
27032 /* NaN over rules the other comparisons */
27033 assign( eq_lt_gt
, binop( Iop_Or32
,
27035 unop( Iop_1Uto32
, bit4
),
27039 unop( Iop_1Uto32
, bit5
),
27042 unop( Iop_1Uto32
, bit6
),
27044 assign(CC
, binop( Iop_Or32
,
27047 unop( Iop_1Sto32
, bit7
) ),
27048 mkexpr( eq_lt_gt
) ),
27049 unop( Iop_1Uto32
, bit7
) ) );
27051 /* put result of the comparison into CC and FPCC */
27052 putGST_field( PPC_GST_CR
, mkexpr( CC
), BF
);
27053 putFPCC( mkexpr( CC
) );
27058 case 0x2A4: // xsmaxcqp (VSX Scalar Maximum Type-C Quad Precision)
27059 case 0x2E4: // xsmincqp (VSX Scalar Minimum Type-C Quad Precision)
27061 IRTemp tmp_cmp
= newTemp( Ity_I64
);
27062 IRTemp cmp_mask
= newTemp( Ity_V128
);
27063 IRTemp result
= newTemp( Ity_V128
);
27064 IRTemp src_not_NaN
= newTemp( Ity_V128
);
27065 IRTemp tmp_src_not_NaN
= newTemp( Ity_I64
);
27067 /* NOTE: exceptions are not implemented, will not set VXSNAN, VXVC or
27069 assign( vA
, getVSReg( vA_addr
) );
27071 if (opc2
== 0x2A4) {
27072 DIP("xsmaxcqp v%u,v%u,v%u\n", VRT
, VRA
, VRB
);
27073 assign( tmp_cmp
, unop( Iop_1Sto64
, Quad_precision_gt( vA
, vB
) ) );
27076 DIP("xsmincqp v%u,v%u,v%u\n", VRT
, VRA
, VRB
);
27077 assign( tmp_cmp
, unop( Iop_1Sto64
, Quad_precision_gt( vB
, vA
) ) );
27080 /* if either vA or vB is NaN, result is vB */
27081 assign( tmp_src_not_NaN
,
27084 mkOR1( is_NaN( Ity_V128
, vA
),
27085 is_NaN( Ity_V128
, vB
) ) ) ) );
27087 assign( src_not_NaN
, binop( Iop_64HLtoV128
,
27088 mkexpr( tmp_src_not_NaN
),
27089 mkexpr( tmp_src_not_NaN
) ) );
27091 assign( cmp_mask
, binop( Iop_64HLtoV128
,
27092 mkexpr( tmp_cmp
), mkexpr( tmp_cmp
) ) );
27094 /* comparison is True, then result = vA, otherwise result = vB */
27095 assign( result
, binop( Iop_OrV128
,
27096 binop( Iop_AndV128
,
27097 mkexpr( cmp_mask
),
27099 binop( Iop_AndV128
,
27100 unop( Iop_NotV128
, mkexpr( cmp_mask
) ),
27101 mkexpr( vB
) ) ) );
27105 binop( Iop_AndV128
,
27106 mkexpr( src_not_NaN
),
27107 mkexpr( result
) ),
27108 binop( Iop_AndV128
,
27109 unop( Iop_NotV128
, mkexpr( src_not_NaN
) ),
27110 mkexpr( vB
) ) ) );
27114 case 0x2C4: // xststdcqp (VSX Scalar Quad-Precision Test Data Class)
27116 UInt BF
= IFIELD( theInstr
, 23, 3 );
27117 UInt DCMX_mask
= IFIELD( theInstr
, 16, 7 );
27118 IRTemp CC
= newTemp( Ity_I64
);
27119 IRTemp NaN
= newTemp( Ity_I64
);
27120 IRTemp inf
= newTemp( Ity_I64
);
27121 IRTemp pos
= newTemp( Ity_I64
);
27122 IRTemp DCM
= newTemp( Ity_I64
);
27123 IRTemp zero
= newTemp( Ity_I64
);
27124 IRTemp dnorm
= newTemp( Ity_I64
);
27126 DIP("xststdcqp %u,v%u,%u\n", BF
, VRB
, DCMX_mask
);
27128 assign( zero
, unop( Iop_1Uto64
, is_Zero( Ity_V128
, vB
) ) );
27129 assign( pos
, unop( Iop_1Uto64
,
27130 binop( Iop_CmpEQ64
,
27132 unop( Iop_V128HIto64
,
27137 assign( NaN
, unop( Iop_1Uto64
, is_NaN( Ity_V128
, vB
) ) );
27138 assign( inf
, unop( Iop_1Uto64
, is_Inf( Ity_V128
, vB
) ) );
27140 assign( dnorm
, unop( Iop_1Uto64
, is_Denorm( Ity_V128
, vB
) ) );
27141 assign( DCM
, create_DCM( Ity_I64
, NaN
, inf
, zero
, dnorm
, pos
) );
27142 assign( CC
, binop( Iop_Or64
,
27143 binop( Iop_And64
, /* vB sign bit */
27145 unop( Iop_V128HIto64
, mkexpr( vB
) ),
27150 binop( Iop_CmpNE64
,
27153 mkU64( DCMX_mask
) ),
27157 putGST_field( PPC_GST_CR
, unop(Iop_64to32
, mkexpr( CC
) ), BF
);
27158 putFPCC( unop(Iop_64to32
, mkexpr( CC
) ) );
27163 case 0x324: // xsabsqp (VSX Scalar Absolute Quad-Precision)
27164 // xsxexpqp (VSX Scalaar Extract Exponent Quad-Precision)
27165 // xsnabsqp (VSX Scalar Negative Absolute Quad-Precision)
27166 // xsnegqp (VSX Scalar Negate Quad-Precision)
27167 // xsxsigqp (VSX Scalar Extract Significand Quad-Precision)
27169 UInt inst_select
= IFIELD( theInstr
, 16, 5);
27171 switch (inst_select
) {
27173 DIP("xsabsqp v%u,v%u\n", VRT
, VRB
);
27174 assign( vT
, binop( Iop_AndV128
, mkexpr( vB
),
27175 binop( Iop_64HLtoV128
,
27176 mkU64( 0x7FFFFFFFFFFFFFFF ),
27177 mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) );
27181 DIP("xsxexpqp v%u,v%u\n", VRT
, VRB
);
27182 assign( vT
, binop( Iop_ShrV128
,
27183 binop( Iop_AndV128
, mkexpr( vB
),
27184 binop( Iop_64HLtoV128
,
27185 mkU64( 0x7FFF000000000000 ),
27186 mkU64( 0x0000000000000000 ) ) ),
27191 DIP("xsnabsqp v%u,v%u\n", VRT
, VRB
);
27192 assign( vT
, binop( Iop_OrV128
, mkexpr( vB
),
27193 binop( Iop_64HLtoV128
,
27194 mkU64( 0x8000000000000000 ),
27195 mkU64( 0x0000000000000000 ) ) ) );
27199 DIP("xsnegqp v%u,v%u\n", VRT
, VRB
);
27200 assign( vT
, binop( Iop_XorV128
, mkexpr( vB
),
27201 binop( Iop_64HLtoV128
,
27202 mkU64( 0x8000000000000000 ),
27203 mkU64( 0x0000000000000000 ) ) ) );
27208 IRTemp expZero
= newTemp( Ity_I64
);
27209 IRTemp expInfinity
= newTemp( Ity_I64
);
27211 DIP("xsxsigqp v%u,v%u\n", VRT
, VRB
);
27213 assign( expZero
, unop( Iop_1Uto64
,
27214 binop( Iop_CmpNE64
,
27216 unop( Iop_V128HIto64
,
27218 mkU64( 0x7FFF000000000000 ) ),
27219 mkU64( 0x0 ) ) ) );
27221 assign( expInfinity
,
27223 binop( Iop_CmpNE64
,
27225 unop( Iop_V128HIto64
,
27227 mkU64( 0x7FFF000000000000 ) ),
27228 mkU64( 0x7FFF000000000000 ) ) ) );
27230 /* Clear upper 16 bits to 0x0000. If the exp was zero or infinity
27231 * set bit 48 (lsb = 0) to 0, otherwise set bit 48 to 1.
27235 binop( Iop_ShrV128
,
27236 binop( Iop_ShlV128
,
27240 binop( Iop_64HLtoV128
,
27244 mkexpr( expInfinity
) ),
27251 vex_printf( "dis_vx_scalar_quad_precision invalid inst_select (ppc)(opc2)\n" );
27256 case 0x364: // xsiexpqp (VST Scalar Insert Exponent Quad-Precision)
27258 IRTemp exp
= newTemp( Ity_I64
);
27260 DIP("xsiexpqp v%d,v%d,v%d\n", VRT
, VRA
, VRB
);
27262 assign( vA
, getVSReg( vA_addr
) );
27263 assign( exp
, binop( Iop_And64
,
27264 unop( Iop_V128HIto64
,
27266 mkU64( 0x7FFFULL
) ) );
27267 assign( vT
, binop( Iop_64HLtoV128
,
27270 unop( Iop_V128HIto64
,
27272 mkU64( 0x8000FFFFFFFFFFFFULL
) ),
27276 unop( Iop_V128to64
,
27277 mkexpr( vA
) ) ) );
27282 vex_printf( "dis_vx_scalar_quad_precision(ppc)(opc2)\n" );
27287 putVSReg( vT_addr
, mkexpr( vT
) );
27292 * VSX permute and other miscealleous instructions
27295 dis_vx_permute_misc( UInt prefix
, UInt theInstr
, UInt opc2
)
27298 UChar opc1
= ifieldOPC( theInstr
);
27299 UChar XT
= ifieldRegXT ( theInstr
);
27300 UChar XA
= ifieldRegXA ( theInstr
);
27301 UChar XB
= ifieldRegXB ( theInstr
);
27302 IRTemp vT
= newTemp( Ity_V128
);
27303 IRTemp vA
= newTemp( Ity_V128
);
27304 IRTemp vB
= newTemp( Ity_V128
);
27306 /* There is no prefixed version of these instructions. */
27309 if (opc1
!= 0x3C) {
27310 vex_printf( "dis_vx_permute_misc(ppc)(instr)\n" );
27314 assign( vA
, getVSReg( XA
) );
27315 assign( vB
, getVSReg( XB
) );
27318 case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate)
27320 UChar SHW
= ifieldSHW ( theInstr
);
27321 IRTemp result
= newTemp(Ity_V128
);
27323 IRTemp hi
= newTemp(Ity_V128
);
27324 IRTemp lo
= newTemp(Ity_V128
);
27325 assign( hi
, binop(Iop_ShlV128
, mkexpr(vA
), mkU8(SHW
*32)) );
27326 assign( lo
, binop(Iop_ShrV128
, mkexpr(vB
), mkU8(128-SHW
*32)) );
27327 assign ( result
, binop(Iop_OrV128
, mkexpr(hi
), mkexpr(lo
)) );
27329 assign ( result
, mkexpr(vA
) );
27330 DIP("xxsldwi v%d,v%d,v%d,%d\n", XT
, XA
, XB
, SHW
);
27331 putVSReg( XT
, mkexpr(result
) );
27334 case 0x28: // xpermdi (VSX Permute Doubleword Immediate)
27336 UChar DM
= ifieldDM ( theInstr
);
27337 IRTemp hi
= newTemp(Ity_I64
);
27338 IRTemp lo
= newTemp(Ity_I64
);
27341 assign( hi
, unop(Iop_V128to64
, mkexpr(vA
)) );
27343 assign( hi
, unop(Iop_V128HIto64
, mkexpr(vA
)) );
27346 assign( lo
, unop(Iop_V128to64
, mkexpr(vB
)) );
27348 assign( lo
, unop(Iop_V128HIto64
, mkexpr(vB
)) );
27350 assign( vT
, binop(Iop_64HLtoV128
, mkexpr(hi
), mkexpr(lo
)) );
27352 DIP("xxpermdi v%d,v%d,v%d,0x%x\n", XT
, XA
, XB
, DM
);
27353 putVSReg( XT
, mkexpr( vT
) );
27356 case 0x48: // xxmrghw (VSX Merge High Word)
27357 case 0xc8: // xxmrglw (VSX Merge Low Word)
27359 const HChar type
= (opc2
== 0x48) ? 'h' : 'l';
27360 IROp word_op
= (opc2
== 0x48) ? Iop_V128HIto64
: Iop_V128to64
;
27361 IRTemp a64
= newTemp(Ity_I64
);
27362 IRTemp ahi32
= newTemp(Ity_I32
);
27363 IRTemp alo32
= newTemp(Ity_I32
);
27364 IRTemp b64
= newTemp(Ity_I64
);
27365 IRTemp bhi32
= newTemp(Ity_I32
);
27366 IRTemp blo32
= newTemp(Ity_I32
);
27368 assign( a64
, unop(word_op
, mkexpr(vA
)) );
27369 assign( ahi32
, unop(Iop_64HIto32
, mkexpr(a64
)) );
27370 assign( alo32
, unop(Iop_64to32
, mkexpr(a64
)) );
27372 assign( b64
, unop(word_op
, mkexpr(vB
)) );
27373 assign( bhi32
, unop(Iop_64HIto32
, mkexpr(b64
)) );
27374 assign( blo32
, unop(Iop_64to32
, mkexpr(b64
)) );
27376 assign( vT
, binop(Iop_64HLtoV128
,
27377 binop(Iop_32HLto64
, mkexpr(ahi32
), mkexpr(bhi32
)),
27378 binop(Iop_32HLto64
, mkexpr(alo32
), mkexpr(blo32
))) );
27380 DIP("xxmrg%cw v%d,v%d,v%d\n", type
, XT
, XA
, XB
);
27381 putVSReg( XT
, mkexpr( vT
) );
27384 case 0x018: // xxsel (VSX Select)
27386 UChar XC
= ifieldRegXC(theInstr
);
27387 IRTemp vC
= newTemp( Ity_V128
);
27388 assign( vC
, getVSReg( XC
) );
27389 DIP("xxsel v%d,v%d,v%d,v%d\n", XT
, XA
, XB
, XC
);
27390 /* vD = (vA & ~vC) | (vB & vC) */
27391 putVSReg( XT
, binop(Iop_OrV128
,
27392 binop(Iop_AndV128
, mkexpr(vA
), unop(Iop_NotV128
, mkexpr(vC
))),
27393 binop(Iop_AndV128
, mkexpr(vB
), mkexpr(vC
))) );
27397 case 0x68: // xxperm (VSX Permute )
27398 case 0xE8: // xxpermr (VSX Permute right-index )
27401 /* The xxperm instruction performs the same operation as
27402 the vperm except the xxperm operates on the VSR register
27403 file. while vperm operates on the VR register file.
27404 Lets borrow some code here from vperm. The mapping of
27405 the source registers is also a little different.
27407 IRTemp a_perm
= newTemp(Ity_V128
);
27408 IRTemp b_perm
= newTemp(Ity_V128
);
27409 IRTemp mask
= newTemp(Ity_V128
);
27410 IRTemp perm_val
= newTemp(Ity_V128
);
27411 IRTemp vB_adj
= newTemp( Ity_V128
);
27413 if ( opc2
== 0x68 ) {
27414 DIP("xxperm v%u,v%u,v%u\n", (UInt
)XT
, (UInt
)XA
, (UInt
)XB
);
27417 /* Same as xperm just the index is 31 - idx */
27418 DIP("xxpermr v%u,v%u,v%u\n", (UInt
)XT
, (UInt
)XA
, (UInt
)XB
);
27421 assign( vT
, getVSReg( XT
) );
27423 if ( opc2
== 0x68 ) // xxperm
27424 assign( vB_adj
, mkexpr( vB
) );
27428 binop( Iop_Sub16x8
,
27429 unop( Iop_Dup8x16
, mkU8( 0x1F ) ),
27432 /* Limit the Perm8x16 steering values to 0 .. 15 as that is what
27433 IR specifies, and also to hide irrelevant bits from
27437 binop( Iop_AndV128
, mkexpr( vB_adj
),
27438 unop( Iop_Dup8x16
, mkU8( 0xF ) ) ) );
27440 binop( Iop_Perm8x16
, mkexpr( vA
), mkexpr( perm_val
) ) );
27442 binop( Iop_Perm8x16
, mkexpr( vT
), mkexpr( perm_val
) ) );
27443 assign( mask
, binop( Iop_SarN8x16
,
27444 binop( Iop_ShlN8x16
, mkexpr( vB_adj
),
27447 // dst = (a & ~mask) | (b & mask)
27448 putVSReg( XT
, binop( Iop_OrV128
,
27449 binop( Iop_AndV128
, mkexpr( a_perm
),
27450 unop( Iop_NotV128
, mkexpr( mask
) ) ),
27451 binop( Iop_AndV128
, mkexpr( b_perm
),
27452 mkexpr( mask
) ) ) );
27456 case 0x148: // xxspltw (VSX Splat Word)
27458 UChar UIM
= ifieldRegA(theInstr
) & 3;
27459 UChar sh_uim
= (3 - (UIM
)) * 32;
27460 DIP("xxspltw v%d,v%d,%d\n", XT
, XB
, UIM
);
27463 unop( Iop_V128to32
,
27464 binop( Iop_ShrV128
, mkexpr( vB
), mkU8( sh_uim
) ) ) ) );
27469 vex_printf( "dis_vx_permute_misc(ppc)(opc2)\n" );
27476 AltiVec Load Instructions
27478 static Bool
dis_av_load ( const VexAbiInfo
* vbi
, UInt prefix
, UInt theInstr
)
27481 UChar opc1
= ifieldOPC(theInstr
);
27482 UChar vD_addr
= ifieldRegDS(theInstr
);
27483 UChar rA_addr
= ifieldRegA(theInstr
);
27484 UChar rB_addr
= ifieldRegB(theInstr
);
27485 UInt opc2
= ifieldOPClo10(theInstr
);
27486 UChar b0
= ifieldBIT0(theInstr
);
27488 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
27489 IRTemp EA
= newTemp(ty
);
27490 IRTemp EA_align16
= newTemp(ty
);
27492 /* There is no prefixed version of these instructions. */
27495 if (opc1
!= 0x1F || b0
!= 0) {
27496 vex_printf("dis_av_load(ppc)(instr)\n");
27500 assign( EA
, ea_rAor0_idxd(rA_addr
, rB_addr
) );
27501 assign( EA_align16
, addr_align( mkexpr(EA
), 16 ) );
27505 case 0x006: { // lvsl (Load Vector for Shift Left, AV p123)
27507 UInt vD_off
= vectorGuestRegOffset(vD_addr
);
27508 IRExpr
** args_be
= mkIRExprVec_5(
27511 binop(Iop_And32
, mkNarrowTo32(ty
, mkexpr(EA
)),
27514 mkU32(1)/*Big Endian*/);
27515 IRExpr
** args_le
= mkIRExprVec_5(
27518 binop(Iop_And32
, mkNarrowTo32(ty
, mkexpr(EA
)),
27521 mkU32(0)/*Little Endian*/);
27523 d
= unsafeIRDirty_0_N (
27525 "ppc32g_dirtyhelper_LVS",
27526 fnptr_to_fnentry(vbi
, &ppc32g_dirtyhelper_LVS
),
27529 if (host_endness
== VexEndnessBE
)
27530 d
= unsafeIRDirty_0_N (
27532 "ppc64g_dirtyhelper_LVS",
27533 fnptr_to_fnentry(vbi
, &ppc64g_dirtyhelper_LVS
),
27536 d
= unsafeIRDirty_0_N (
27538 "ppc64g_dirtyhelper_LVS",
27539 fnptr_to_fnentry( vbi
, &ppc64g_dirtyhelper_LVS
),
27542 DIP("lvsl v%d,r%u,r%u\n", vD_addr
, rA_addr
, rB_addr
);
27543 /* declare guest state effects */
27545 vex_bzero(&d
->fxState
, sizeof(d
->fxState
));
27546 d
->fxState
[0].fx
= Ifx_Write
;
27547 d
->fxState
[0].offset
= vD_off
;
27548 d
->fxState
[0].size
= sizeof(U128
);
27550 /* execute the dirty call, side-effecting guest state */
27551 stmt( IRStmt_Dirty(d
) );
27554 case 0x026: { // lvsr (Load Vector for Shift Right, AV p125)
27556 UInt vD_off
= vectorGuestRegOffset(vD_addr
);
27557 IRExpr
** args_be
= mkIRExprVec_5(
27560 binop(Iop_And32
, mkNarrowTo32(ty
, mkexpr(EA
)),
27563 mkU32(1)/*Big Endian*/);
27564 IRExpr
** args_le
= mkIRExprVec_5(
27567 binop(Iop_And32
, mkNarrowTo32(ty
, mkexpr(EA
)),
27570 mkU32(0)/*Little Endian*/);
27573 d
= unsafeIRDirty_0_N (
27575 "ppc32g_dirtyhelper_LVS",
27576 fnptr_to_fnentry(vbi
, &ppc32g_dirtyhelper_LVS
),
27579 if (host_endness
== VexEndnessBE
)
27580 d
= unsafeIRDirty_0_N (
27582 "ppc64g_dirtyhelper_LVS",
27583 fnptr_to_fnentry(vbi
, &ppc64g_dirtyhelper_LVS
),
27586 d
= unsafeIRDirty_0_N (
27588 "ppc64g_dirtyhelper_LVS",
27589 fnptr_to_fnentry( vbi
, &ppc64g_dirtyhelper_LVS
),
27592 DIP("lvsr v%d,r%u,r%u\n", vD_addr
, rA_addr
, rB_addr
);
27593 /* declare guest state effects */
27595 vex_bzero(&d
->fxState
, sizeof(d
->fxState
));
27596 d
->fxState
[0].fx
= Ifx_Write
;
27597 d
->fxState
[0].offset
= vD_off
;
27598 d
->fxState
[0].size
= sizeof(U128
);
27600 /* execute the dirty call, side-effecting guest state */
27601 stmt( IRStmt_Dirty(d
) );
27604 case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119)
27605 DIP("lvebx v%d,r%u,r%u\n", vD_addr
, rA_addr
, rB_addr
);
27606 /* loads addressed byte into vector[EA[0:3]
27607 since all other destination bytes are undefined,
27608 can simply load entire vector from 16-aligned EA */
27609 putVReg( vD_addr
, load(Ity_V128
, mkexpr(EA_align16
)) );
27612 case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121)
27613 DIP("lvehx v%d,r%u,r%u\n", vD_addr
, rA_addr
, rB_addr
);
27614 /* see note for lvebx */
27615 putVReg( vD_addr
, load(Ity_V128
, mkexpr(EA_align16
)) );
27618 case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122)
27619 DIP("lvewx v%d,r%u,r%u\n", vD_addr
, rA_addr
, rB_addr
);
27620 /* see note for lvebx */
27621 putVReg( vD_addr
, load(Ity_V128
, mkexpr(EA_align16
)) );
27624 case 0x067: // lvx (Load Vector Indexed, AV p127)
27625 DIP("lvx v%d,r%u,r%u\n", vD_addr
, rA_addr
, rB_addr
);
27626 putVReg( vD_addr
, load(Ity_V128
, mkexpr(EA_align16
)) );
27629 case 0x167: // lvxl (Load Vector Indexed LRU, AV p128)
27630 DIP("lvxl v%d,r%u,r%u\n", vD_addr
, rA_addr
, rB_addr
);
27631 putVReg( vD_addr
, load(Ity_V128
, mkexpr(EA_align16
)) );
27635 vex_printf("dis_av_load(ppc)(opc2)\n");
27642 AltiVec Store Instructions
27644 static Bool
dis_av_store ( UInt prefix
, UInt theInstr
)
27647 UChar opc1
= ifieldOPC(theInstr
);
27648 UChar vS_addr
= ifieldRegDS(theInstr
);
27649 UChar rA_addr
= ifieldRegA(theInstr
);
27650 UChar rB_addr
= ifieldRegB(theInstr
);
27651 UInt opc2
= ifieldOPClo10(theInstr
);
27652 UChar b0
= ifieldBIT0(theInstr
);
27654 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
27655 IRTemp EA
= newTemp(ty
);
27656 IRTemp addr_aligned
= newTemp(ty
);
27657 IRTemp vS
= newTemp(Ity_V128
);
27658 IRTemp eb
= newTemp(Ity_I8
);
27659 IRTemp idx
= newTemp(Ity_I8
);
27661 /* There is no prefixed version of these instructions. */
27664 if (opc1
!= 0x1F || b0
!= 0) {
27665 vex_printf("dis_av_store(ppc)(instr)\n");
27669 assign( vS
, getVReg(vS_addr
));
27670 assign( EA
, ea_rAor0_idxd(rA_addr
, rB_addr
) );
27673 case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131)
27674 DIP("stvebx v%d,r%u,r%u\n", vS_addr
, rA_addr
, rB_addr
);
27675 assign( eb
, binop(Iop_And8
, mkU8(0xF),
27677 mkNarrowTo32(ty
, mkexpr(EA
)) )) );
27678 if (host_endness
== VexEndnessLE
) {
27679 assign( idx
, binop(Iop_Shl8
, mkexpr(eb
), mkU8(3)) );
27681 assign( idx
, binop(Iop_Shl8
,
27682 binop(Iop_Sub8
, mkU8(15), mkexpr(eb
)),
27686 unop( Iop_32to8
, unop(Iop_V128to32
,
27687 binop(Iop_ShrV128
, mkexpr(vS
), mkexpr(idx
)))) );
27690 case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132)
27691 DIP("stvehx v%d,r%u,r%u\n", vS_addr
, rA_addr
, rB_addr
);
27692 assign( addr_aligned
, addr_align(mkexpr(EA
), 2) );
27693 assign( eb
, binop(Iop_And8
, mkU8(0xF),
27694 mkNarrowTo8(ty
, mkexpr(addr_aligned
) )) );
27695 if (host_endness
== VexEndnessLE
) {
27696 assign( idx
, binop(Iop_Shl8
, mkexpr(eb
), mkU8(3)) );
27698 assign( idx
, binop(Iop_Shl8
,
27699 binop(Iop_Sub8
, mkU8(14), mkexpr(eb
)),
27702 store( mkexpr(addr_aligned
),
27703 unop( Iop_32to16
, unop(Iop_V128to32
,
27704 binop(Iop_ShrV128
, mkexpr(vS
), mkexpr(idx
)))) );
27707 case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133)
27708 DIP("stvewx v%d,r%u,r%u\n", vS_addr
, rA_addr
, rB_addr
);
27709 assign( addr_aligned
, addr_align(mkexpr(EA
), 4) );
27710 assign( eb
, binop(Iop_And8
, mkU8(0xF),
27711 mkNarrowTo8(ty
, mkexpr(addr_aligned
) )) );
27712 if (host_endness
== VexEndnessLE
) {
27713 assign( idx
, binop(Iop_Shl8
, mkexpr(eb
), mkU8(3)) );
27715 assign( idx
, binop(Iop_Shl8
,
27716 binop(Iop_Sub8
, mkU8(12), mkexpr(eb
)),
27719 store( mkexpr( addr_aligned
),
27720 unop( Iop_V128to32
,
27721 binop(Iop_ShrV128
, mkexpr(vS
), mkexpr(idx
))) );
27725 case 0x0E7: // stvx (Store Vector Indexed, AV p134)
27726 DIP("stvx v%d,r%u,r%u\n", vS_addr
, rA_addr
, rB_addr
);
27727 store( addr_align( mkexpr(EA
), 16 ), mkexpr(vS
) );
27730 case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135)
27731 DIP("stvxl v%d,r%u,r%u\n", vS_addr
, rA_addr
, rB_addr
);
27732 store( addr_align( mkexpr(EA
), 16 ), mkexpr(vS
) );
27736 vex_printf("dis_av_store(ppc)(opc2)\n");
27743 AltiVec Arithmetic Instructions
27745 static Bool
dis_av_arith ( UInt prefix
, UInt theInstr
)
27748 UChar opc1
= ifieldOPC(theInstr
);
27749 UChar vD_addr
= ifieldRegDS(theInstr
);
27750 UChar vA_addr
= ifieldRegA(theInstr
);
27751 UChar vB_addr
= ifieldRegB(theInstr
);
27752 UInt opc2
= IFIELD( theInstr
, 0, 11 );
27754 IRTemp vA
= newTemp(Ity_V128
);
27755 IRTemp vB
= newTemp(Ity_V128
);
27756 IRTemp z3
= newTemp(Ity_I64
);
27757 IRTemp z2
= newTemp(Ity_I64
);
27758 IRTemp z1
= newTemp(Ity_I64
);
27759 IRTemp z0
= newTemp(Ity_I64
);
27761 IRTemp a15
, a14
, a13
, a12
, a11
, a10
, a9
, a8
;
27762 IRTemp a7
, a6
, a5
, a4
, a3
, a2
, a1
, a0
;
27763 IRTemp b3
, b2
, b1
, b0
;
27765 /* There is no prefixed version of these instructions. */
27768 aEvn
= aOdd
= IRTemp_INVALID
;
27769 a15
= a14
= a13
= a12
= a11
= a10
= a9
= a8
= IRTemp_INVALID
;
27770 a7
= a6
= a5
= a4
= a3
= a2
= a1
= a0
= IRTemp_INVALID
;
27771 b3
= b2
= b1
= b0
= IRTemp_INVALID
;
27773 assign( vA
, getVReg( vA_addr
) );
27774 assign( vB
, getVReg( vB_addr
) );
27777 vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n");
27783 case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136)
27784 DIP("vaddcuw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
27785 /* unsigned_ov(x+y) = (y >u not(x)) */
27786 putVReg( vD_addr
, binop( Iop_ShrN32x4
,
27787 binop( Iop_CmpGT32Ux4
, mkexpr( vB
),
27788 unop( Iop_NotV128
, mkexpr( vA
) ) ),
27792 case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141)
27793 DIP("vaddubm v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
27794 putVReg( vD_addr
, binop(Iop_Add8x16
, mkexpr(vA
), mkexpr(vB
)) );
27797 case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143)
27798 DIP("vadduhm v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
27799 putVReg( vD_addr
, binop(Iop_Add16x8
, mkexpr(vA
), mkexpr(vB
)) );
27802 case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145)
27803 DIP("vadduwm v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
27804 putVReg( vD_addr
, binop(Iop_Add32x4
, mkexpr(vA
), mkexpr(vB
)) );
27807 case 0x0C0: // vaddudm (Add Unsigned Double Word Modulo)
27808 DIP("vaddudm v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
27809 putVReg( vD_addr
, binop(Iop_Add64x2
, mkexpr(vA
), mkexpr(vB
)) );
27812 case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142)
27813 DIP("vaddubs v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
27814 putVReg( vD_addr
, binop(Iop_QAdd8Ux16
, mkexpr(vA
), mkexpr(vB
)) );
27815 // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16
27818 case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144)
27819 DIP("vadduhs v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
27820 putVReg( vD_addr
, binop(Iop_QAdd16Ux8
, mkexpr(vA
), mkexpr(vB
)) );
27821 // TODO: set VSCR[SAT]
27824 case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146)
27825 DIP("vadduws v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
27826 putVReg( vD_addr
, binop(Iop_QAdd32Ux4
, mkexpr(vA
), mkexpr(vB
)) );
27827 // TODO: set VSCR[SAT]
27830 case 0x0C8: // vmuloud (Vector multiply Odd Unsigned Doubleword VX-form)
27831 case 0x1C8: // vmulosd (Vector multiply Odd Signed Doubleword VX-form)
27832 case 0x2C8: // vmuleud (Vector multiply Even Unsigned Doubleword VX-form)
27833 case 0x3C8: // vmulesd (Vector multiply Even Signed Doubleword VX-form)
27835 IRTemp hi
= newTemp(Ity_I64
);
27836 IRTemp lo
= newTemp(Ity_I64
);
27837 IRTemp tmp128
= newTemp(Ity_I128
);
27839 if ( opc2
== 0x0C8) {
27840 DIP("vmuloud v%u,v%u,v%u\n", vD_addr
, vA_addr
, vB_addr
);
27841 /* multiply lower D-words together, upper D-words not used. */
27842 assign( tmp128
, binop( Iop_MullU64
,
27843 unop( Iop_V128to64
, mkexpr( vA
) ),
27844 unop( Iop_V128to64
, mkexpr( vB
) ) ) );
27846 } else if ( opc2
== 0x1C8) {
27847 DIP("vmulosd v%u,v%u,v%u\n", vD_addr
, vA_addr
, vB_addr
);
27848 /* multiply lower D-words together, upper D-words not used. */
27849 assign( tmp128
, binop( Iop_MullS64
,
27850 unop( Iop_V128to64
, mkexpr( vA
) ),
27851 unop( Iop_V128to64
, mkexpr( vB
) ) ) );
27853 } else if ( opc2
== 0x2C8) {
27854 DIP("vmuleud v%u,v%u,v%u\n", vD_addr
, vA_addr
, vB_addr
);
27855 /* multiply upper D-words together, lower D-words not used. */
27856 assign( tmp128
, binop( Iop_MullU64
,
27857 unop( Iop_V128HIto64
, mkexpr( vA
) ),
27858 unop( Iop_V128HIto64
, mkexpr( vB
) ) ) );
27861 DIP("vmulesd v%u,v%u,v%u\n", vD_addr
, vA_addr
, vB_addr
);
27862 /* multiply upper D-words together, lower D-words not used. */
27863 assign( tmp128
, binop( Iop_MullS64
,
27864 unop( Iop_V128HIto64
, mkexpr( vA
) ),
27865 unop( Iop_V128HIto64
, mkexpr( vB
) ) ) );
27868 /* Need to convert from I128 to V128. Don't have a direct
27870 assign( hi
, unop( Iop_128HIto64
, mkexpr( tmp128
) ) );
27871 assign( lo
, unop( Iop_128to64
, mkexpr( tmp128
) ) );
27874 binop( Iop_64HLtoV128
, mkexpr( hi
), mkexpr( lo
) ) );
27878 case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138)
27879 DIP("vaddsbs v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
27880 putVReg( vD_addr
, binop(Iop_QAdd8Sx16
, mkexpr(vA
), mkexpr(vB
)) );
27881 // TODO: set VSCR[SAT]
27884 case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139)
27885 DIP("vaddshs v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
27886 putVReg( vD_addr
, binop(Iop_QAdd16Sx8
, mkexpr(vA
), mkexpr(vB
)) );
27887 // TODO: set VSCR[SAT]
27890 case 0x380: // vaddsws (Add Signed Word Saturate, AV p140)
27891 DIP("vaddsws v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
27892 putVReg( vD_addr
, binop(Iop_QAdd32Sx4
, mkexpr(vA
), mkexpr(vB
)) );
27893 // TODO: set VSCR[SAT]
27896 case 0x08B: // vdivuw Vector Divide Unsigned Word
27897 case 0x18B: // vdivsw Vector Divide Signed Word
27898 case 0x289: // vmulhuw Vector Multiply High Unsigned Word
27899 case 0x389: // vmulhsw Vector Multiply High Signed Word
27900 case 0x28B: // vdiveuw Vector divide Extended Unsigned Word
27901 case 0x38B: // vdivesw Vector divide Extended Signed Word
27902 case 0x68B: // vmoduw Vector Modulo Unsigned Word
27903 case 0x78B: // vmodsw Vector Modulo Signed Word
27906 IROp expand_op
= Iop_32Uto64
;
27907 IROp extract_res
= Iop_64to32
;
27908 IROp operation
= Iop_DivU64
;
27909 IRTemp srcA_tmp
[MAX_ELE
];
27910 IRTemp srcB_tmp
[MAX_ELE
];
27911 IRTemp res_tmp
[MAX_ELE
];
27912 IRTemp res_tmp2
[MAX_ELE
];
27913 IRTemp res_tmp3
[MAX_ELE
];
27914 UInt shift_by
= 32;
27916 IRType size_op
= Ity_I64
, size_res
= Ity_I32
;
27918 if (opc2
== 0x08B) {
27919 DIP("vdivuw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
27920 expand_op
= Iop_32Uto64
;
27921 operation
= Iop_DivU64
;
27922 extract_res
= Iop_64to32
;
27924 } else if (opc2
== 0x68B) {
27925 DIP("vmoduw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
27926 expand_op
= Iop_32Uto64
;
27927 operation
= Iop_DivU64
;
27928 extract_res
= Iop_64to32
;
27930 } else if (opc2
== 0x18B) {
27931 DIP("vdivsw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
27932 expand_op
= Iop_32Sto64
;
27933 operation
= Iop_DivS64
;
27934 extract_res
= Iop_64to32
;
27936 } else if (opc2
== 0x78B) {
27937 DIP("vmodsw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
27938 expand_op
= Iop_32Sto64
;
27939 operation
= Iop_DivS64
;
27940 extract_res
= Iop_64to32
;
27942 } else if (opc2
== 0x289) {
27943 DIP("vmulhuw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
27944 expand_op
= Iop_32Uto64
;
27945 operation
= Iop_Mul64
;
27946 extract_res
= Iop_64HIto32
;
27948 } else if (opc2
== 0x389) {
27949 DIP("vmulhsw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
27950 expand_op
= Iop_32Sto64
;
27951 operation
= Iop_Mul64
;
27952 extract_res
= Iop_64HIto32
;
27954 } else if (opc2
== 0x28B) {
27955 DIP("vdiveuw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
27956 expand_op
= Iop_32Uto64
;
27957 operation
= Iop_DivU64
;
27958 extract_res
= Iop_64to32
;
27960 } else if (opc2
== 0x38B) {
27961 DIP("vdivesw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
27962 expand_op
= Iop_32Sto64
;
27963 operation
= Iop_DivS64
;
27964 extract_res
= Iop_64to32
;
27967 for (i
=0; i
<MAX_ELE
; i
++) {
27968 srcA_tmp
[i
] = newTemp( size_op
);
27969 srcB_tmp
[i
] = newTemp( size_op
);
27970 res_tmp
[i
] = newTemp( size_res
);
27972 if (( opc2
== 0x28B ) || ( opc2
== 0x38B )) {
27973 // Operand A is left shifted 32 bits
27974 assign( srcA_tmp
[i
],
27978 unop( Iop_V128to64
,
27979 binop( Iop_ShrV128
,
27981 mkU8( i
*shift_by
) )))),
27984 assign( srcA_tmp
[i
],
27987 unop( Iop_V128to64
,
27988 binop( Iop_ShrV128
,
27990 mkU8( i
*shift_by
) ) ) ) ) );
27993 assign( srcB_tmp
[i
],
27996 unop( Iop_V128to64
,
27997 binop( Iop_ShrV128
,
27999 mkU8( i
*shift_by
) ) ) ) ) );
28001 if ( opc2
== 0x38B ) { // vdivesw
28002 /* Take absolute value of signed operands to determine if the result fits in 31 bits.
28003 Set result to zeros if it doesn't fit to match the HW functionality. */
28004 res_tmp2
[i
] = newTemp( Ity_I64
);
28005 res_tmp3
[i
] = newTemp( Ity_I64
);
28007 /* Calculate actual result */
28008 assign( res_tmp2
[i
],
28010 mkexpr( srcA_tmp
[i
] ),
28011 mkexpr( srcB_tmp
[i
] ) ) );
28013 /* Calculate result for ABS(srcA) and ABS(srcB) */
28014 assign( res_tmp3
[i
], binop( operation
, absI64( srcA_tmp
[i
] ), absI64( srcB_tmp
[i
] ) ) );
28016 assign( res_tmp
[i
],
28020 binop( Iop_CmpEQ64
,
28021 binop( Iop_Shr64
, mkexpr( res_tmp3
[i
] ), mkU8( 31 )),
28023 mkexpr( res_tmp2
[i
] ) ) ) );
28025 } else if ( opc2
== 0x28B ) { // vdiveuw
28026 /* Check if result fits in 32-bits, set result to zeros if it doesn't fit to
28027 match the HW functionality. */
28028 res_tmp2
[i
] = newTemp( Ity_I64
);
28029 assign( res_tmp2
[i
],
28031 mkexpr( srcA_tmp
[i
] ),
28032 mkexpr( srcB_tmp
[i
] ) ) );
28033 assign( res_tmp
[i
],
28037 binop( Iop_CmpEQ64
,
28038 binop( Iop_Shr64
, mkexpr( res_tmp2
[i
] ), mkU8( 32 )),
28040 mkexpr( res_tmp2
[i
] ) ) ) );
28042 assign( res_tmp
[i
],
28045 mkexpr( srcA_tmp
[i
] ),
28046 mkexpr( srcB_tmp
[i
] ) ) ) );
28050 if (!(( opc2
== 0x68B ) || ( opc2
== 0x78B ))) {
28051 /* Doing a multiply or divide instruction */
28053 Abs_Zero_Vector( Ity_I32
,
28054 binop( Iop_64HLtoV128
,
28055 binop( Iop_32HLto64
,
28056 mkexpr( res_tmp
[ 3 ] ),
28057 mkexpr( res_tmp
[ 2 ] ) ),
28058 binop( Iop_32HLto64
,
28059 mkexpr( res_tmp
[ 1 ] ),
28060 mkexpr( res_tmp
[ 0 ] ) ) ) ) );
28062 /* Doing a modulo instruction, vmodsw/vmoduw
28063 res_tmp[] contains the quotients of VRA/VRB.
28064 Calculate modulo as VRA - VRB * res_tmp. */
28065 IRTemp res_Tmp
= newTemp( Ity_V128
);
28068 Abs_Zero_Vector( Ity_I32
,
28069 binop( Iop_64HLtoV128
,
28070 binop( Iop_32HLto64
,
28071 mkexpr( res_tmp
[ 3 ] ),
28072 mkexpr( res_tmp
[ 2 ] ) ),
28073 binop( Iop_32HLto64
,
28074 mkexpr( res_tmp
[ 1 ] ),
28075 mkexpr( res_tmp
[ 0 ] ) ) ) ) );
28077 putVReg( vD_addr
, binop( Iop_Sub32x4
,
28079 binop( Iop_Mul32x4
,
28081 mkexpr( vB
) ) ) );
28086 case 0x1C9: // vmulld Vector Multiply Low Signed Doubleword
28087 case 0x2C9: // vmulhud Vector Multiply High Unsigned Doubleword
28088 case 0x3C9: // vmulhsd Vector Multiply High Signed Doubleword
28089 case 0x0CB: // vdivud Vector Divide Unsigned Doubleword
28090 case 0x1CB: // vdivsd Vector Divide Signed Doubleword
28091 case 0x6CB: // vmodud Vector Modulo Unsigned Doubleword
28092 case 0x7CB: // vmodsd Vector Modulo Signed Doubleword
28095 IROp extract_res
= Iop_64to32
;
28096 IROp operation
= Iop_MullS64
;
28097 IRTemp srcA_tmp
[MAX_ELE
];
28098 IRTemp srcB_tmp
[MAX_ELE
];
28099 IRTemp res_tmp
[MAX_ELE
];
28100 UInt shift_by
= 64;
28102 IRType size_op
= Ity_I64
, size_res
= Ity_I64
;
28104 if (opc2
== 0x1C9) {
28105 DIP("vmulld v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28106 operation
= Iop_MullS64
;
28107 extract_res
= Iop_128to64
;
28109 } else if (opc2
== 0x2C9) {
28110 DIP("vmulhud v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28111 operation
= Iop_MullU64
;
28112 extract_res
= Iop_128HIto64
;
28114 } else if (opc2
== 0x3C9) {
28115 DIP("vmulhsd v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28116 operation
= Iop_MullS64
;
28117 extract_res
= Iop_128HIto64
;
28119 } else if (opc2
== 0x0CB) {
28120 DIP("vdivud v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28121 operation
= Iop_DivU64
;
28123 } else if (opc2
== 0x1CB) {
28124 DIP("vdivsd v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28125 operation
= Iop_DivS64
;
28127 } else if (opc2
== 0x6CB) {
28128 DIP("vmodud v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28129 operation
= Iop_DivU64
;
28131 } else if (opc2
== 0x7CB) {
28132 DIP("vmodsd v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28133 operation
= Iop_DivS64
;
28136 for (i
=0; i
<MAX_ELE
; i
++) {
28137 srcA_tmp
[i
] = newTemp( size_op
);
28138 srcB_tmp
[i
] = newTemp( size_op
);
28139 res_tmp
[i
] = newTemp( size_res
);
28141 assign( srcA_tmp
[i
],
28142 unop( Iop_V128to64
,
28143 binop( Iop_ShrV128
,
28145 mkU8( i
*shift_by
) ) ) );
28147 assign( srcB_tmp
[i
],
28148 unop( Iop_V128to64
,
28149 binop( Iop_ShrV128
,
28151 mkU8( i
*shift_by
) ) ) );
28153 if ((opc2
== 0x1C9) || (opc2
== 0x2C9) || (opc2
== 0x3C9)) {
28154 /* multiply result is I128 */
28155 assign( res_tmp
[i
],
28158 mkexpr( srcA_tmp
[i
] ),
28159 mkexpr( srcB_tmp
[i
] ) ) ) );
28161 /* divide result is I64 */
28162 assign( res_tmp
[i
],
28164 mkexpr( srcA_tmp
[i
] ),
28165 mkexpr( srcB_tmp
[i
] ) ) );
28169 if ((opc2
== 0x6CB) || (opc2
== 0x7CB)) {
28170 /* Doing a modulo instruction,
28171 res_tmp[] contains the quotients of VRA/VRB.
28172 Calculate modulo as VRA - VRB * res_tmp. */
28173 IRTemp res_Tmp
= newTemp( Ity_V128
);
28175 assign( res_Tmp
, binop( Iop_64HLtoV128
,
28177 mkexpr( res_tmp
[ 1 ] ),
28178 mkexpr( srcB_tmp
[1] ) ),
28180 mkexpr( res_tmp
[0] ),
28181 mkexpr( srcB_tmp
[0] ) ) ) );
28183 putVReg( vD_addr
, binop( Iop_Sub64x2
,
28185 mkexpr( res_Tmp
) ) );
28188 putVReg( vD_addr
, binop( Iop_64HLtoV128
,
28189 mkexpr( res_tmp
[ 1 ] ),
28190 mkexpr( res_tmp
[ 0 ] ) ) );
28197 case 0x2CB: // vdiveud Vector Divide Extended Unsigned Doubleword
28198 case 0x3CB: { // vdivesd Vector Divide Extended Signed Doubleword
28199 /* Do vector inst as two scalar operations */
28200 IRTemp divisor_hi
= newTemp(Ity_I64
);
28201 IRTemp divisor_lo
= newTemp(Ity_I64
);
28202 IRTemp dividend_hi
= newTemp(Ity_I64
);
28203 IRTemp dividend_lo
= newTemp(Ity_I64
);
28204 IRTemp result_hi
= newTemp(Ity_I64
);
28205 IRTemp result_lo
= newTemp(Ity_I64
);
28207 assign( dividend_hi
, unop( Iop_V128HIto64
, mkexpr( vA
) ) );
28208 assign( dividend_lo
, unop( Iop_V128to64
, mkexpr( vA
) ) );
28209 assign( divisor_hi
, unop( Iop_V128HIto64
, mkexpr( vB
) ) );
28210 assign( divisor_lo
, unop( Iop_V128to64
, mkexpr( vB
) ) );
28212 if (opc2
== 0x2CB) {
28213 DIP("vdiveud v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28215 binop( Iop_DivU64E
, mkexpr( dividend_hi
),
28216 mkexpr( divisor_hi
) ) );
28218 binop( Iop_DivU64E
, mkexpr( dividend_lo
),
28219 mkexpr( divisor_lo
) ) );
28220 putVReg( vD_addr
, binop( Iop_64HLtoV128
, mkexpr( result_hi
),
28221 mkexpr( result_lo
) ) );
28224 DIP("vdivesd v%d,v%d,v%d", vD_addr
, vA_addr
, vB_addr
);
28226 binop( Iop_DivS64E
, mkexpr( dividend_hi
),
28227 mkexpr( divisor_hi
) ) );
28229 binop( Iop_DivS64E
, mkexpr( dividend_lo
),
28230 mkexpr( divisor_lo
) ) );
28231 putVReg( vD_addr
, binop( Iop_64HLtoV128
, mkexpr( result_hi
),
28232 mkexpr( result_lo
) ) );
28238 case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260)
28239 DIP("vsubcuw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28240 /* unsigned_ov(x-y) = (y >u x) */
28241 putVReg( vD_addr
, binop(Iop_ShrN32x4
,
28243 binop(Iop_CmpGT32Ux4
, mkexpr(vB
),
28248 case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265)
28249 DIP("vsububm v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28250 putVReg( vD_addr
, binop(Iop_Sub8x16
, mkexpr(vA
), mkexpr(vB
)) );
28253 case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267)
28254 DIP("vsubuhm v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28255 putVReg( vD_addr
, binop(Iop_Sub16x8
, mkexpr(vA
), mkexpr(vB
)) );
28258 case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269)
28259 DIP("vsubuwm v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28260 putVReg( vD_addr
, binop(Iop_Sub32x4
, mkexpr(vA
), mkexpr(vB
)) );
28263 case 0x4C0: // vsubudm (Subtract Unsigned Double Word Modulo)
28264 DIP("vsubudm v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28265 putVReg( vD_addr
, binop(Iop_Sub64x2
, mkexpr(vA
), mkexpr(vB
)) );
28268 case 0x600: // vsububs (Subtract Unsigned Byte Saturate, AV p266)
28269 DIP("vsububs v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28270 putVReg( vD_addr
, binop(Iop_QSub8Ux16
, mkexpr(vA
), mkexpr(vB
)) );
28271 // TODO: set VSCR[SAT]
28274 case 0x640: // vsubuhs (Subtract Unsigned HWord Saturate, AV p268)
28275 DIP("vsubuhs v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28276 putVReg( vD_addr
, binop(Iop_QSub16Ux8
, mkexpr(vA
), mkexpr(vB
)) );
28277 // TODO: set VSCR[SAT]
28280 case 0x680: // vsubuws (Subtract Unsigned Word Saturate, AV p270)
28281 DIP("vsubuws v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28282 putVReg( vD_addr
, binop(Iop_QSub32Ux4
, mkexpr(vA
), mkexpr(vB
)) );
28283 // TODO: set VSCR[SAT]
28286 case 0x700: // vsubsbs (Subtract Signed Byte Saturate, AV p262)
28287 DIP("vsubsbs v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28288 putVReg( vD_addr
, binop(Iop_QSub8Sx16
, mkexpr(vA
), mkexpr(vB
)) );
28289 // TODO: set VSCR[SAT]
28292 case 0x740: // vsubshs (Subtract Signed Half Word Saturate, AV p263)
28293 DIP("vsubshs v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28294 putVReg( vD_addr
, binop(Iop_QSub16Sx8
, mkexpr(vA
), mkexpr(vB
)) );
28295 // TODO: set VSCR[SAT]
28298 case 0x780: // vsubsws (Subtract Signed Word Saturate, AV p264)
28299 DIP("vsubsws v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28300 putVReg( vD_addr
, binop(Iop_QSub32Sx4
, mkexpr(vA
), mkexpr(vB
)) );
28301 // TODO: set VSCR[SAT]
28306 case 0x002: // vmaxub (Maximum Unsigned Byte, AV p182)
28307 DIP("vmaxub v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28308 putVReg( vD_addr
, binop(Iop_Max8Ux16
, mkexpr(vA
), mkexpr(vB
)) );
28311 case 0x042: // vmaxuh (Maximum Unsigned Half Word, AV p183)
28312 DIP("vmaxuh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28313 putVReg( vD_addr
, binop(Iop_Max16Ux8
, mkexpr(vA
), mkexpr(vB
)) );
28316 case 0x082: // vmaxuw (Maximum Unsigned Word, AV p184)
28317 DIP("vmaxuw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28318 putVReg( vD_addr
, binop(Iop_Max32Ux4
, mkexpr(vA
), mkexpr(vB
)) );
28321 case 0x0C2: // vmaxud (Maximum Unsigned Double word)
28322 DIP("vmaxud v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28323 putVReg( vD_addr
, binop(Iop_Max64Ux2
, mkexpr(vA
), mkexpr(vB
)) );
28326 case 0x102: // vmaxsb (Maximum Signed Byte, AV p179)
28327 DIP("vmaxsb v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28328 putVReg( vD_addr
, binop(Iop_Max8Sx16
, mkexpr(vA
), mkexpr(vB
)) );
28331 case 0x142: // vmaxsh (Maximum Signed Half Word, AV p180)
28332 DIP("vmaxsh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28333 putVReg( vD_addr
, binop(Iop_Max16Sx8
, mkexpr(vA
), mkexpr(vB
)) );
28336 case 0x182: // vmaxsw (Maximum Signed Word, AV p181)
28337 DIP("vmaxsw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28338 putVReg( vD_addr
, binop(Iop_Max32Sx4
, mkexpr(vA
), mkexpr(vB
)) );
28341 case 0x1C2: // vmaxsd (Maximum Signed Double word)
28342 DIP("vmaxsd v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28343 putVReg( vD_addr
, binop(Iop_Max64Sx2
, mkexpr(vA
), mkexpr(vB
)) );
28347 case 0x202: // vminub (Minimum Unsigned Byte, AV p191)
28348 DIP("vminub v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28349 putVReg( vD_addr
, binop(Iop_Min8Ux16
, mkexpr(vA
), mkexpr(vB
)) );
28352 case 0x242: // vminuh (Minimum Unsigned Half Word, AV p192)
28353 DIP("vminuh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28354 putVReg( vD_addr
, binop(Iop_Min16Ux8
, mkexpr(vA
), mkexpr(vB
)) );
28357 case 0x282: // vminuw (Minimum Unsigned Word, AV p193)
28358 DIP("vminuw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28359 putVReg( vD_addr
, binop(Iop_Min32Ux4
, mkexpr(vA
), mkexpr(vB
)) );
28362 case 0x2C2: // vminud (Minimum Unsigned Double Word)
28363 DIP("vminud v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28364 putVReg( vD_addr
, binop(Iop_Min64Ux2
, mkexpr(vA
), mkexpr(vB
)) );
28367 case 0x302: // vminsb (Minimum Signed Byte, AV p188)
28368 DIP("vminsb v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28369 putVReg( vD_addr
, binop(Iop_Min8Sx16
, mkexpr(vA
), mkexpr(vB
)) );
28372 case 0x342: // vminsh (Minimum Signed Half Word, AV p189)
28373 DIP("vminsh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28374 putVReg( vD_addr
, binop(Iop_Min16Sx8
, mkexpr(vA
), mkexpr(vB
)) );
28377 case 0x382: // vminsw (Minimum Signed Word, AV p190)
28378 DIP("vminsw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28379 putVReg( vD_addr
, binop(Iop_Min32Sx4
, mkexpr(vA
), mkexpr(vB
)) );
28382 case 0x3C2: // vminsd (Minimum Signed Double Word)
28383 DIP("vminsd v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28384 putVReg( vD_addr
, binop(Iop_Min64Sx2
, mkexpr(vA
), mkexpr(vB
)) );
28389 case 0x402: // vavgub (Average Unsigned Byte, AV p152)
28390 DIP("vavgub v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28391 putVReg( vD_addr
, binop(Iop_Avg8Ux16
, mkexpr(vA
), mkexpr(vB
)) );
28394 case 0x442: // vavguh (Average Unsigned Half Word, AV p153)
28395 DIP("vavguh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28396 putVReg( vD_addr
, binop(Iop_Avg16Ux8
, mkexpr(vA
), mkexpr(vB
)) );
28399 case 0x482: // vavguw (Average Unsigned Word, AV p154)
28400 DIP("vavguw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28401 putVReg( vD_addr
, binop(Iop_Avg32Ux4
, mkexpr(vA
), mkexpr(vB
)) );
28404 case 0x502: // vavgsb (Average Signed Byte, AV p149)
28405 DIP("vavgsb v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28406 putVReg( vD_addr
, binop(Iop_Avg8Sx16
, mkexpr(vA
), mkexpr(vB
)) );
28409 case 0x542: // vavgsh (Average Signed Half Word, AV p150)
28410 DIP("vavgsh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28411 putVReg( vD_addr
, binop(Iop_Avg16Sx8
, mkexpr(vA
), mkexpr(vB
)) );
28414 case 0x582: // vavgsw (Average Signed Word, AV p151)
28415 DIP("vavgsw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28416 putVReg( vD_addr
, binop(Iop_Avg32Sx4
, mkexpr(vA
), mkexpr(vB
)) );
28421 case 0x008: // vmuloub (Multiply Odd Unsigned Byte, AV p213)
28422 DIP("vmuloub v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28424 binop(Iop_MullEven8Ux16
, mkexpr(vA
), mkexpr(vB
)));
28427 case 0x048: // vmulouh (Multiply Odd Unsigned Half Word, AV p214)
28428 DIP("vmulouh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28430 binop(Iop_MullEven16Ux8
, mkexpr(vA
), mkexpr(vB
)));
28433 case 0x088: // vmulouw (Multiply Odd Unsigned Word)
28434 DIP("vmulouw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28435 putVReg( vD_addr
, binop( Iop_MullEven32Ux4
, mkexpr(vA
), mkexpr(vB
) ) );
28438 case 0x089: // vmuluwm (Multiply Unsigned Word Modulo)
28439 DIP("vmuluwm v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28440 putVReg( vD_addr
, binop( Iop_Mul32x4
, mkexpr(vA
), mkexpr(vB
) ) );
28443 case 0x108: // vmulosb (Multiply Odd Signed Byte, AV p211)
28444 DIP("vmulosb v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28446 binop(Iop_MullEven8Sx16
, mkexpr(vA
), mkexpr(vB
)));
28449 case 0x148: // vmulosh (Multiply Odd Signed Half Word, AV p212)
28450 DIP("vmulosh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28452 binop(Iop_MullEven16Sx8
, mkexpr(vA
), mkexpr(vB
)));
28455 case 0x188: // vmulosw (Multiply Odd Signed Word)
28456 DIP("vmulosw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28457 putVReg( vD_addr
, binop( Iop_MullEven32Sx4
, mkexpr(vA
), mkexpr(vB
) ) );
28460 case 0x208: // vmuleub (Multiply Even Unsigned Byte, AV p209)
28461 DIP("vmuleub v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28462 putVReg( vD_addr
, MK_Iop_MullOdd8Ux16( mkexpr(vA
), mkexpr(vB
) ));
28465 case 0x248: // vmuleuh (Multiply Even Unsigned Half Word, AV p210)
28466 DIP("vmuleuh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28467 putVReg( vD_addr
, MK_Iop_MullOdd16Ux8( mkexpr(vA
), mkexpr(vB
) ));
28470 case 0x288: // vmuleuw (Multiply Even Unsigned Word)
28471 DIP("vmuleuw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28472 putVReg( vD_addr
, MK_Iop_MullOdd32Ux4( mkexpr(vA
), mkexpr(vB
) ) );
28475 case 0x308: // vmulesb (Multiply Even Signed Byte, AV p207)
28476 DIP("vmulesb v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28477 putVReg( vD_addr
, MK_Iop_MullOdd8Sx16( mkexpr(vA
), mkexpr(vB
) ));
28480 case 0x348: // vmulesh (Multiply Even Signed Half Word, AV p208)
28481 DIP("vmulesh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28482 putVReg( vD_addr
, MK_Iop_MullOdd16Sx8( mkexpr(vA
), mkexpr(vB
) ));
28485 case 0x388: // vmulesw (Multiply Even Signed Word)
28486 DIP("vmulesw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28487 putVReg( vD_addr
, MK_Iop_MullOdd32Sx4( mkexpr(vA
), mkexpr(vB
) ) );
28490 /* Sum Across Partial */
28491 case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275)
28492 IRTemp aEE
, aEO
, aOE
, aOO
;
28493 aEE
= aEO
= aOE
= aOO
= IRTemp_INVALID
;
28494 DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28496 /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */
28497 expand8Ux16( mkexpr(vA
), &aEvn
, &aOdd
); // (15,13...),(14,12...)
28498 expand16Ux8( mkexpr(aEvn
), &aEE
, &aEO
); // (15,11...),(13, 9...)
28499 expand16Ux8( mkexpr(aOdd
), &aOE
, &aOO
); // (14,10...),(12, 8...)
28501 /* break V128 to 4xI32's, zero-extending to I64's */
28502 breakV128to4x64U( mkexpr(aEE
), &a15
, &a11
, &a7
, &a3
);
28503 breakV128to4x64U( mkexpr(aOE
), &a14
, &a10
, &a6
, &a2
);
28504 breakV128to4x64U( mkexpr(aEO
), &a13
, &a9
, &a5
, &a1
);
28505 breakV128to4x64U( mkexpr(aOO
), &a12
, &a8
, &a4
, &a0
);
28506 breakV128to4x64U( mkexpr(vB
), &b3
, &b2
, &b1
, &b0
);
28509 assign( z3
, binop(Iop_Add64
, mkexpr(b3
),
28511 binop(Iop_Add64
, mkexpr(a15
), mkexpr(a14
)),
28512 binop(Iop_Add64
, mkexpr(a13
), mkexpr(a12
)))) );
28513 assign( z2
, binop(Iop_Add64
, mkexpr(b2
),
28515 binop(Iop_Add64
, mkexpr(a11
), mkexpr(a10
)),
28516 binop(Iop_Add64
, mkexpr(a9
), mkexpr(a8
)))) );
28517 assign( z1
, binop(Iop_Add64
, mkexpr(b1
),
28519 binop(Iop_Add64
, mkexpr(a7
), mkexpr(a6
)),
28520 binop(Iop_Add64
, mkexpr(a5
), mkexpr(a4
)))) );
28521 assign( z0
, binop(Iop_Add64
, mkexpr(b0
),
28523 binop(Iop_Add64
, mkexpr(a3
), mkexpr(a2
)),
28524 binop(Iop_Add64
, mkexpr(a1
), mkexpr(a0
)))) );
28526 /* saturate-narrow to 32bit, and combine to V128 */
28527 putVReg( vD_addr
, mkV128from4x64U( mkexpr(z3
), mkexpr(z2
),
28528 mkexpr(z1
), mkexpr(z0
)) );
28531 case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273)
28532 IRTemp aEE
, aEO
, aOE
, aOO
;
28533 aEE
= aEO
= aOE
= aOO
= IRTemp_INVALID
;
28534 DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28536 /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */
28537 expand8Sx16( mkexpr(vA
), &aEvn
, &aOdd
); // (15,13...),(14,12...)
28538 expand16Sx8( mkexpr(aEvn
), &aEE
, &aEO
); // (15,11...),(13, 9...)
28539 expand16Sx8( mkexpr(aOdd
), &aOE
, &aOO
); // (14,10...),(12, 8...)
28541 /* break V128 to 4xI32's, sign-extending to I64's */
28542 breakV128to4x64S( mkexpr(aEE
), &a15
, &a11
, &a7
, &a3
);
28543 breakV128to4x64S( mkexpr(aOE
), &a14
, &a10
, &a6
, &a2
);
28544 breakV128to4x64S( mkexpr(aEO
), &a13
, &a9
, &a5
, &a1
);
28545 breakV128to4x64S( mkexpr(aOO
), &a12
, &a8
, &a4
, &a0
);
28546 breakV128to4x64S( mkexpr(vB
), &b3
, &b2
, &b1
, &b0
);
28549 assign( z3
, binop(Iop_Add64
, mkexpr(b3
),
28551 binop(Iop_Add64
, mkexpr(a15
), mkexpr(a14
)),
28552 binop(Iop_Add64
, mkexpr(a13
), mkexpr(a12
)))) );
28553 assign( z2
, binop(Iop_Add64
, mkexpr(b2
),
28555 binop(Iop_Add64
, mkexpr(a11
), mkexpr(a10
)),
28556 binop(Iop_Add64
, mkexpr(a9
), mkexpr(a8
)))) );
28557 assign( z1
, binop(Iop_Add64
, mkexpr(b1
),
28559 binop(Iop_Add64
, mkexpr(a7
), mkexpr(a6
)),
28560 binop(Iop_Add64
, mkexpr(a5
), mkexpr(a4
)))) );
28561 assign( z0
, binop(Iop_Add64
, mkexpr(b0
),
28563 binop(Iop_Add64
, mkexpr(a3
), mkexpr(a2
)),
28564 binop(Iop_Add64
, mkexpr(a1
), mkexpr(a0
)))) );
28566 /* saturate-narrow to 32bit, and combine to V128 */
28567 putVReg( vD_addr
, mkV128from4x64S( mkexpr(z3
), mkexpr(z2
),
28568 mkexpr(z1
), mkexpr(z0
)) );
28571 case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274)
28572 DIP("vsum4shs v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28574 /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */
28575 expand16Sx8( mkexpr(vA
), &aEvn
, &aOdd
); // (7,5...),(6,4...)
28577 /* break V128 to 4xI32's, sign-extending to I64's */
28578 breakV128to4x64S( mkexpr(aEvn
), &a7
, &a5
, &a3
, &a1
);
28579 breakV128to4x64S( mkexpr(aOdd
), &a6
, &a4
, &a2
, &a0
);
28580 breakV128to4x64S( mkexpr(vB
), &b3
, &b2
, &b1
, &b0
);
28583 assign( z3
, binop(Iop_Add64
, mkexpr(b3
),
28584 binop(Iop_Add64
, mkexpr(a7
), mkexpr(a6
))));
28585 assign( z2
, binop(Iop_Add64
, mkexpr(b2
),
28586 binop(Iop_Add64
, mkexpr(a5
), mkexpr(a4
))));
28587 assign( z1
, binop(Iop_Add64
, mkexpr(b1
),
28588 binop(Iop_Add64
, mkexpr(a3
), mkexpr(a2
))));
28589 assign( z0
, binop(Iop_Add64
, mkexpr(b0
),
28590 binop(Iop_Add64
, mkexpr(a1
), mkexpr(a0
))));
28592 /* saturate-narrow to 32bit, and combine to V128 */
28593 putVReg( vD_addr
, mkV128from4x64S( mkexpr(z3
), mkexpr(z2
),
28594 mkexpr(z1
), mkexpr(z0
)) );
28597 case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272)
28598 DIP("vsum2sws v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28600 /* break V128 to 4xI32's, sign-extending to I64's */
28601 breakV128to4x64S( mkexpr(vA
), &a3
, &a2
, &a1
, &a0
);
28602 breakV128to4x64S( mkexpr(vB
), &b3
, &b2
, &b1
, &b0
);
28605 assign( z2
, binop(Iop_Add64
, mkexpr(b2
),
28606 binop(Iop_Add64
, mkexpr(a3
), mkexpr(a2
))) );
28607 assign( z0
, binop(Iop_Add64
, mkexpr(b0
),
28608 binop(Iop_Add64
, mkexpr(a1
), mkexpr(a0
))) );
28610 /* saturate-narrow to 32bit, and combine to V128 */
28611 putVReg( vD_addr
, mkV128from4x64S( mkU64(0), mkexpr(z2
),
28612 mkU64(0), mkexpr(z0
)) );
28615 case 0x788: { // vsumsws (Sum SW Saturate, AV p271)
28616 DIP("vsumsws v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
28618 /* break V128 to 4xI32's, sign-extending to I64's */
28619 breakV128to4x64S( mkexpr(vA
), &a3
, &a2
, &a1
, &a0
);
28620 breakV128to4x64S( mkexpr(vB
), &b3
, &b2
, &b1
, &b0
);
28623 assign( z0
, binop(Iop_Add64
, mkexpr(b0
),
28625 binop(Iop_Add64
, mkexpr(a3
), mkexpr(a2
)),
28626 binop(Iop_Add64
, mkexpr(a1
), mkexpr(a0
)))) );
28628 /* saturate-narrow to 32bit, and combine to V128 */
28629 putVReg( vD_addr
, mkV128from4x64S( mkU64(0), mkU64(0),
28630 mkU64(0), mkexpr(z0
)) );
28634 vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2
);
28640 static Bool
dis_vx_quadword_arith ( UInt prefix
, UInt theInstr
)
28642 /* Quad word operations, VX-Form */
28643 UChar vT_addr
= ifieldRegDS(theInstr
);
28644 UChar vA_addr
= ifieldRegA(theInstr
);
28645 UChar vB_addr
= ifieldRegB(theInstr
);
28646 UChar opc1
= ifieldOPC(theInstr
);
28648 IRTemp vA
= newTemp(Ity_V128
);
28649 IRTemp vB
= newTemp(Ity_V128
);
28652 vex_printf("ERROR: dis_vx_quadword_arith(ppc)\n");
28656 assign( vA
, getVReg( vA_addr
) );
28657 assign( vB
, getVReg( vB_addr
) );
28659 opc2
= IFIELD(theInstr
, 0, 6);
28661 case 0x017: // vmsumcud Vector Multiply-Sum & write Carry-out Unsigned
28662 // Doubleword VA-form
28664 UChar vC_addr
= ifieldRegC(theInstr
);
28665 IRTemp vC
= newTemp(Ity_V128
);
28667 assign( vC
, getVReg( vC_addr
) );
28669 DIP("vmsumcud %d,%d,%d,%d\n", vT_addr
, vA_addr
, vB_addr
, vC_addr
);
28670 putVReg( vT_addr
, triop( Iop_2xMultU64Add128CarryOut
,
28671 mkexpr( vA
), mkexpr( vB
), mkexpr( vC
) ) );
28676 break; /* fall thru to next case statement */
28677 } /* switch (opc2) */
28679 opc2
= ifieldOPClo11( theInstr
);
28681 case 0x005: //vrlq Vector Rotate Left Quadword
28683 IRTemp sh
= newTemp(Ity_I8
); /* shift amout is vB[57:63] */
28684 IRTemp shr
= newTemp(Ity_I8
);
28685 IRTemp vA_shl
= newTemp(Ity_V128
);
28686 IRTemp vA_shr
= newTemp(Ity_V128
);
28688 DIP("vrlq v%u,v%u,v%u\n", vT_addr
, vA_addr
, vB_addr
);
28696 unop( Iop_V128HIto64
,
28697 mkexpr( vB
) ) ) ) ) ) );
28699 assign( shr
, binop( Iop_Sub8
, mkU8( 128 ), mkexpr( sh
) ) );
28700 assign( vA_shl
, binop( Iop_ShlV128
, mkexpr( vA
), mkexpr( sh
) ) );
28701 assign( vA_shr
, binop( Iop_ShrV128
, mkexpr( vA
), mkexpr( shr
) ) );
28703 binop( Iop_OrV128
, mkexpr( vA_shl
), mkexpr( vA_shr
) ) );
28707 case 0x00B: //vdivuq Vector Divide Unsigned Quadword
28708 DIP("vdivuq %d,%d,%d\n", vT_addr
, vA_addr
, vB_addr
);
28709 putVReg( vT_addr
, binop( Iop_DivU128
, mkexpr( vA
), mkexpr( vB
) ) );
28712 case 0x101: //vcmpuq Vector Compare Unsigned Quadword
28714 IRTemp lt
= newTemp(Ity_I32
);
28715 IRTemp gt
= newTemp(Ity_I32
);
28716 IRTemp eq
= newTemp(Ity_I32
);
28717 IRTemp cc
= newTemp(Ity_I32
);
28718 UInt BF
= IFIELD( theInstr
, (31-8), 3 );
28720 DIP("vcmpuq %u,v%u,v%u\n", BF
, vA_addr
, vB_addr
);
28722 assign ( lt
, unop( Iop_1Uto32
, Quad_precision_uint_gt( vB
, vA
) ) );
28723 assign ( gt
, unop( Iop_1Uto32
, Quad_precision_uint_gt( vA
, vB
) ) );
28724 assign ( eq
, unop( Iop_1Uto32
, Quad_precision_int_eq( vA
, vB
) ) );
28726 assign( cc
, binop( Iop_Or32
,
28727 binop( Iop_Shl32
, mkexpr( lt
), mkU8( 3 ) ),
28730 mkexpr( gt
), mkU8( 2 ) ),
28732 mkexpr( eq
), mkU8( 1 ) ) ) ) );
28734 putGST_field( PPC_GST_CR
, mkexpr( cc
), BF
);
28738 case 0x105: //vslq Vector Shift Left Quadword
28739 case 0x205: //vsrq Vector Shift Right Quadword
28741 IRTemp sh
= newTemp(Ity_I8
); /* shift amout is vB[57:63] */
28749 unop( Iop_V128HIto64
,
28750 mkexpr( vB
) ) ) ) ) ) );
28752 if (opc2
== 0x105) {
28753 DIP("vslq v%u,v%u,v%u\n", vT_addr
, vA_addr
, vB_addr
);
28755 binop( Iop_ShlV128
, mkexpr( vA
), mkexpr( sh
) ) );
28758 DIP("vsrq v%u,v%u,v%u\n", vT_addr
, vA_addr
, vB_addr
);
28760 binop( Iop_ShrV128
, mkexpr( vA
), mkexpr( sh
) ) );
28765 case 0x10B: //vdivsq Vector Divide Signed Quadword
28766 DIP("vdivsq %d,%d,%d\n", vT_addr
, vA_addr
, vB_addr
);
28767 putVReg( vT_addr
, binop( Iop_DivS128
, mkexpr( vA
), mkexpr( vB
) ) );
28770 case 0x141: //vcmpsq Vector Compare Signed Quadword
28772 IRTemp lt
= newTemp(Ity_I32
);
28773 IRTemp gt
= newTemp(Ity_I32
);
28774 IRTemp eq
= newTemp(Ity_I32
);
28775 IRTemp cc
= newTemp(Ity_I32
);
28776 UInt BF
= IFIELD( theInstr
, (31-8), 3 );
28778 DIP("vcmpsq %u,v%u,v%u\n", BF
, vA_addr
, vB_addr
);
28780 assign ( lt
, unop( Iop_1Uto32
, Quad_precision_sint_gt( vB
, vA
) ) );
28781 assign ( gt
, unop( Iop_1Uto32
, Quad_precision_sint_gt( vA
, vB
) ) );
28782 assign ( eq
, unop( Iop_1Uto32
, Quad_precision_int_eq( vA
, vB
) ) );
28784 assign( cc
, binop( Iop_Or32
,
28785 binop( Iop_Shl32
, mkexpr( lt
), mkU8( 3 ) ),
28788 mkexpr( gt
), mkU8( 2 ) ),
28790 mkexpr( eq
), mkU8( 1 ) ) ) ) );
28792 putGST_field( PPC_GST_CR
, mkexpr( cc
), BF
);
28796 case 0x045: //vrlqmi Vector Rotate Left Quadword then Mask Insert
28797 case 0x145: //vrlqnm Vector Rotate Left Quadword then AND with Mask
28799 IRTemp sh
= newTemp(Ity_I8
);
28800 IRTemp shr
= newTemp(Ity_I8
);
28801 IRTemp vA_shl
= newTemp(Ity_V128
);
28802 IRTemp vA_shr
= newTemp(Ity_V128
);
28803 IRTemp mask
= newTemp(Ity_V128
);
28804 IRTemp mb
= newTemp(Ity_I8
); /* mask begin */
28805 IRTemp me
= newTemp(Ity_I8
); /* mask end */
28806 IRTemp tmp
= newTemp(Ity_I8
); /* mask end tmp */
28808 /* rotate value in bits vB[57:63] */
28815 unop( Iop_V128HIto64
,
28816 mkexpr( vB
) ) ) ) ) ) );
28818 /* mask begin in bits vB[41:47] */
28826 unop( Iop_V128HIto64
,
28828 mkU8 ( 16 ) ) ) ) ) );
28830 /* mask end in bits vB[49:55] */
28836 unop( Iop_V128HIto64
,
28838 mkU8 ( 8 ) ) ) ) );
28845 mkexpr( tmp
) ) ) );
28847 /* Create mask, Start with all 1's, shift right and then left by
28848 (127-me) to clear the lower me bits. Similarly, shift left then
28849 right by mb to clear upper bits. */
28852 binop( Iop_ShrV128
,
28853 binop( Iop_ShlV128
,
28854 binop( Iop_ShlV128
,
28855 binop( Iop_ShrV128
,
28856 binop( Iop_64HLtoV128
,
28857 mkU64( 0xFFFFFFFFFFFFFFFF ),
28858 mkU64( 0xFFFFFFFFFFFFFFFF ) ),
28864 assign( shr
, binop( Iop_Sub8
, mkU8( 128 ), mkexpr( sh
) ) );
28865 assign( vA_shl
, binop( Iop_ShlV128
, mkexpr( vA
), mkexpr( sh
) ) );
28866 assign( vA_shr
, binop( Iop_ShrV128
, mkexpr( vA
), mkexpr( shr
) ) );
28868 if (opc2
== 0x045) {
28869 IRTemp vT_initial
= newTemp(Ity_V128
);
28871 DIP("vrlqmi v%u,v%u,v%u\n", vT_addr
, vA_addr
, vB_addr
);
28873 assign( vT_initial
, getVReg( vT_addr
) );
28875 /* Mask rotated value from vA and insert into vT */
28878 binop( Iop_AndV128
,
28879 unop( Iop_NotV128
, mkexpr( mask
) ),
28880 mkexpr( vT_initial
) ),
28881 binop( Iop_AndV128
,
28884 mkexpr( vA_shr
) ),
28885 mkexpr( mask
) ) ) );
28888 DIP("vrlqnm v%u,v%u\n", vA_addr
, vB_addr
);
28891 binop( Iop_AndV128
,
28894 mkexpr( vA_shr
) ),
28895 mkexpr( mask
) ) );
28900 case 0x1C7: //vcmpequq Vector Compare Equal Quadword
28901 case 0x5C7: //vcmpequq.
28903 IRTemp eq
= newTemp(Ity_I1
);
28904 IRTemp cc
= newTemp(Ity_I32
);
28905 UInt Rc
= IFIELD( theInstr
, (31-21), 1 );
28908 DIP("vcmpequq%s v%u,v%u,v%u\n",
28909 Rc
? ".":"", vT_addr
, vA_addr
, vB_addr
);
28911 assign ( eq
, Quad_precision_int_eq( vA
, vB
) );
28913 /* if true cc = 0b0100, if flase cc= 0b0010 */
28914 assign( cc
, binop( Iop_Or32
,
28916 unop( Iop_1Uto32
, mkexpr( eq
) ),
28920 unop( Iop_Not1
, mkexpr( eq
) ) ),
28923 if (Rc
) putGST_field( PPC_GST_CR
, mkexpr( cc
), cc_field
);
28925 putVReg( vT_addr
, binop( Iop_64HLtoV128
,
28926 unop( Iop_1Sto64
, mkexpr( eq
) ),
28927 unop( Iop_1Sto64
, mkexpr( eq
) ) ) );
28931 case 0x287: //vcmpgtuq Vector Compare Greater Than Unsigned Quadword
28932 case 0x687: //vcmpgtuq.
28933 case 0x387: //vcmpgtsq Vector Compare Greater Than Signed Quadword
28934 case 0x787: //vcmpgtsq.
28936 IRTemp gt
= newTemp(Ity_I1
);
28937 IRTemp cc
= newTemp(Ity_I32
);
28938 UInt Rc
= IFIELD( theInstr
, (31-21), 1 );
28941 if ((opc2
== 0x287) || (opc2
== 0x687)) {
28942 DIP("vcmpgtuq%s v%u,v%u,v%u\n",
28943 Rc
? ".":"", vT_addr
, vA_addr
, vB_addr
);
28945 assign ( gt
, Quad_precision_uint_gt( vA
, vB
) );
28948 DIP("vcmpgtsq%s v%u,v%u,v%u\n",
28949 Rc
? ".":"", vT_addr
, vA_addr
, vB_addr
);
28951 assign ( gt
, Quad_precision_sint_gt( vA
, vB
) );
28954 /* if true cc = 0b0100, if flase cc= 0b0010 */
28955 assign( cc
, binop( Iop_Or32
,
28957 unop( Iop_1Uto32
, mkexpr( gt
) ),
28961 unop( Iop_Not1
, mkexpr( gt
) ) ),
28963 if (Rc
) putGST_field( PPC_GST_CR
, mkexpr( cc
), cc_field
);
28965 putVReg( vT_addr
, binop( Iop_64HLtoV128
,
28966 unop( Iop_1Sto64
, mkexpr( gt
) ),
28967 unop( Iop_1Sto64
, mkexpr( gt
) ) ) );
28971 case 0x20B: //vdiveuq Vector Divide Extended Unsigned Quadword VX form
28972 DIP("vdiveuq %d,%d,%d\n", vT_addr
, vA_addr
, vB_addr
);
28973 putVReg( vT_addr
, binop( Iop_DivU128E
, mkexpr( vA
), mkexpr( vB
) ) );
28976 case 0x305: //vsraq Vector Shift Right Algebraic Quadword
28978 IRTemp sh
= newTemp(Ity_I8
); /* shift amout is vB[57:63] */
28979 IRTemp shr
= newTemp(Ity_I8
);
28980 IRTemp tmp
= newTemp(Ity_I64
);
28981 IRTemp vA_sign
= newTemp(Ity_V128
); /* sign bit of vA replicated */
28983 DIP("vsraq v%u,v%u,v%u\n", vT_addr
, vA_addr
, vB_addr
);
28991 unop( Iop_V128HIto64
,
28992 mkexpr( vB
) ) ) ) ) ) );
28993 assign( shr
, binop( Iop_Sub8
, mkU8( 128 ), mkexpr( sh
) ) );
28995 /* Replicate the sign bit in all bit positions if sh is not zero. Clear the lower bits
28996 from [sh:127] by shifting right, then left by (127-sh).
29001 binop( Iop_CmpNE8
, mkexpr( sh
), mkU8( 0 ) ) ),
29005 unop( Iop_V128HIto64
,
29007 mkU8( 63 ) ) ) ) ) );
29009 binop( Iop_ShlV128
,
29010 binop( Iop_ShrV128
,
29011 binop( Iop_64HLtoV128
,
29019 binop( Iop_ShrV128
, mkexpr( vA
), mkexpr( sh
) ),
29020 mkexpr( vA_sign
) ) );
29024 case 0x30B: //vdivesq Vector Divide Extended Signed Quadword VX form
29025 DIP("vdivesq %d,%d,%d\n", vT_addr
, vA_addr
, vB_addr
);
29026 putVReg( vT_addr
, binop( Iop_DivS128E
, mkexpr( vA
), mkexpr( vB
) ) );
29029 case 0x60B: //vmoduq Vector Modulo Unsigned Quadword
29030 DIP("vmoduq %d,%d,%d\n", vT_addr
, vA_addr
, vB_addr
);
29031 putVReg( vT_addr
, binop( Iop_ModU128
, mkexpr( vA
), mkexpr( vB
) ) );
29034 case 0x70B: //vmodsq Vector Modulo Signed Quadword
29035 DIP("vmodsq %d,%d,%d\n", vT_addr
, vA_addr
, vB_addr
);
29036 putVReg( vT_addr
, binop( Iop_ModS128
, mkexpr( vA
), mkexpr( vB
) ) );
29040 vex_printf("dis_av_arith(ppc)(opc2 bits[21:31]=0x%x)\n", opc2
);
29042 } /* switch (opc2) */
29049 AltiVec Logic Instructions
29051 static Bool
dis_av_logic ( UInt prefix
, UInt theInstr
)
29054 UChar opc1
= ifieldOPC(theInstr
);
29055 UChar vT_addr
= ifieldRegDS(theInstr
);
29056 UChar vA_addr
= ifieldRegA(theInstr
);
29057 UChar vB_addr
= ifieldRegB(theInstr
);
29058 UInt opc2
= IFIELD( theInstr
, 0, 11 );
29060 IRTemp vA
= newTemp(Ity_V128
);
29061 IRTemp vB
= newTemp(Ity_V128
);
29062 assign( vA
, getVReg(vA_addr
));
29063 assign( vB
, getVReg(vB_addr
));
29065 /* There is no prefixed version of these instructions. */
29069 vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n");
29074 case 0x404: // vand (And, AV p147)
29075 DIP("vand v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
29076 putVReg( vT_addr
, binop(Iop_AndV128
, mkexpr(vA
), mkexpr(vB
)) );
29079 case 0x444: // vandc (And, AV p148)
29080 DIP("vandc v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
29081 putVReg( vT_addr
, binop(Iop_AndV128
, mkexpr(vA
),
29082 unop(Iop_NotV128
, mkexpr(vB
))) );
29085 case 0x484: // vor (Or, AV p217)
29086 DIP("vor v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
29087 putVReg( vT_addr
, binop(Iop_OrV128
, mkexpr(vA
), mkexpr(vB
)) );
29090 case 0x4C4: // vxor (Xor, AV p282)
29091 DIP("vxor v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
29092 putVReg( vT_addr
, binop(Iop_XorV128
, mkexpr(vA
), mkexpr(vB
)) );
29095 case 0x504: // vnor (Nor, AV p216)
29096 DIP("vnor v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
29098 unop(Iop_NotV128
, binop(Iop_OrV128
, mkexpr(vA
), mkexpr(vB
))) );
29101 case 0x544: // vorc (vA Or'd with complement of vb)
29102 DIP("vorc v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
29103 putVReg( vT_addr
, binop( Iop_OrV128
,
29105 unop( Iop_NotV128
, mkexpr( vB
) ) ) );
29108 case 0x584: // vnand (Nand)
29109 DIP("vnand v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
29110 putVReg( vT_addr
, unop( Iop_NotV128
,
29111 binop(Iop_AndV128
, mkexpr( vA
),
29112 mkexpr( vB
) ) ) );
29115 case 0x684: // veqv (complemented XOr)
29116 DIP("veqv v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
29117 putVReg( vT_addr
, unop( Iop_NotV128
,
29118 binop( Iop_XorV128
, mkexpr( vA
),
29119 mkexpr( vB
) ) ) );
29123 vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2
);
29130 AltiVec Compare Instructions
29132 static Bool
dis_av_cmp ( UInt prefix
, UInt theInstr
)
29135 UChar opc1
= ifieldOPC(theInstr
);
29136 UChar vD_addr
= ifieldRegDS(theInstr
);
29137 UChar vA_addr
= ifieldRegA(theInstr
);
29138 UChar vB_addr
= ifieldRegB(theInstr
);
29139 UChar flag_rC
= ifieldBIT10(theInstr
);
29140 UInt opc2
= IFIELD( theInstr
, 0, 10 );
29142 IRTemp vA
= newTemp(Ity_V128
);
29143 IRTemp vB
= newTemp(Ity_V128
);
29144 IRTemp vD
= newTemp(Ity_V128
);
29146 /* There is no prefixed version of these instructions. */
29149 assign( vA
, getVReg(vA_addr
));
29150 assign( vB
, getVReg(vB_addr
));
29153 vex_printf("dis_av_cmp(ppc)(instr)\n");
29158 case 0x006: // vcmpequb (Compare Equal-to Unsigned B, AV p160)
29159 DIP("vcmpequb%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
29160 vD_addr
, vA_addr
, vB_addr
);
29161 assign( vD
, binop(Iop_CmpEQ8x16
, mkexpr(vA
), mkexpr(vB
)) );
29164 case 0x007: // vcmpneb (Compare Not Equal byte)
29165 DIP("vcmpneb%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
29166 vD_addr
, vA_addr
, vB_addr
);
29167 assign( vD
, unop( Iop_NotV128
,
29168 binop( Iop_CmpEQ8x16
, mkexpr( vA
), mkexpr( vB
) ) ) );
29171 case 0x046: // vcmpequh (Compare Equal-to Unsigned HW, AV p161)
29172 DIP("vcmpequh%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
29173 vD_addr
, vA_addr
, vB_addr
);
29174 assign( vD
, binop(Iop_CmpEQ16x8
, mkexpr(vA
), mkexpr(vB
)) );
29177 case 0x047: // vcmpneh (Compare Not Equal-to Halfword)
29178 DIP("vcmpneh%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
29179 vD_addr
, vA_addr
, vB_addr
);
29180 assign( vD
, unop( Iop_NotV128
,
29181 binop( Iop_CmpEQ16x8
, mkexpr( vA
), mkexpr( vB
) ) ) );
29184 case 0x086: // vcmpequw (Compare Equal-to Unsigned W, AV p162)
29185 DIP("vcmpequw%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
29186 vD_addr
, vA_addr
, vB_addr
);
29187 assign( vD
, binop(Iop_CmpEQ32x4
, mkexpr(vA
), mkexpr(vB
)) );
29190 case 0x087: // vcmpnew (Compare Not Equal-to Word)
29191 DIP("vcmpnew%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
29192 vD_addr
, vA_addr
, vB_addr
);
29193 assign( vD
, unop( Iop_NotV128
,
29194 binop( Iop_CmpEQ32x4
, mkexpr( vA
), mkexpr( vB
) ) ) );
29197 case 0x107: // vcmpnezb (Compare Not Equal or Zero byte)
29199 IRTemp vAeqvB
= newTemp( Ity_V128
);
29200 IRTemp vAeq0
= newTemp( Ity_V128
);
29201 IRTemp vBeq0
= newTemp( Ity_V128
);
29202 IRTemp zero
= newTemp( Ity_V128
);
29204 DIP("vcmpnezb%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
29205 vD_addr
, vA_addr
, vB_addr
);
29207 assign( zero
, binop( Iop_64HLtoV128
, mkU64( 0 ), mkU64( 0 ) ) );
29208 assign( vAeq0
, binop( Iop_CmpEQ8x16
, mkexpr( vA
), mkexpr( zero
) ) );
29209 assign( vBeq0
, binop( Iop_CmpEQ8x16
, mkexpr( vB
), mkexpr( zero
) ) );
29210 assign( vAeqvB
, unop( Iop_NotV128
,
29211 binop( Iop_CmpEQ8x16
, mkexpr( vA
),
29212 mkexpr( vB
) ) ) );
29214 assign( vD
, mkOr3_V128( vAeqvB
, vAeq0
, vBeq0
) );
29218 case 0x147: // vcmpnezh (Compare Not Equal or Zero Halfword)
29220 IRTemp vAeqvB
= newTemp( Ity_V128
);
29221 IRTemp vAeq0
= newTemp( Ity_V128
);
29222 IRTemp vBeq0
= newTemp( Ity_V128
);
29223 IRTemp zero
= newTemp( Ity_V128
);
29225 DIP("vcmpnezh%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
29226 vD_addr
, vA_addr
, vB_addr
);
29228 assign( zero
, binop( Iop_64HLtoV128
, mkU64( 0 ), mkU64( 0 ) ) );
29229 assign( vAeq0
, binop( Iop_CmpEQ16x8
, mkexpr( vA
), mkexpr( zero
) ) );
29230 assign( vBeq0
, binop( Iop_CmpEQ16x8
, mkexpr( vB
), mkexpr( zero
) ) );
29231 assign( vAeqvB
, unop( Iop_NotV128
,
29232 binop(Iop_CmpEQ16x8
, mkexpr( vA
),
29233 mkexpr( vB
) ) ) );
29235 assign( vD
, binop( Iop_OrV128
,
29239 mkexpr( vAeqvB
) ) );
29243 case 0x187: // vcmpnezw (Compare Not Equal or Zero Word)
29245 IRTemp vAeqvB
= newTemp( Ity_V128
);
29246 IRTemp vAeq0
= newTemp( Ity_V128
);
29247 IRTemp vBeq0
= newTemp( Ity_V128
);
29248 IRTemp zero
= newTemp( Ity_V128
);
29250 DIP("vcmpnezw%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
29251 vD_addr
, vA_addr
, vB_addr
);
29253 assign( zero
, binop( Iop_64HLtoV128
, mkU64( 0 ), mkU64( 0 ) ) );
29254 assign( vAeq0
, binop( Iop_CmpEQ32x4
, mkexpr( vA
), mkexpr( zero
) ) );
29255 assign( vBeq0
, binop( Iop_CmpEQ32x4
, mkexpr( vB
), mkexpr( zero
) ) );
29256 assign( vAeqvB
, unop( Iop_NotV128
,
29257 binop(Iop_CmpEQ32x4
, mkexpr( vA
),
29258 mkexpr( vB
) ) ) );
29260 assign( vD
, binop( Iop_OrV128
,
29264 mkexpr( vAeqvB
) ) );
29268 case 0x0C7: // vcmpequd (Compare Equal-to Unsigned Doubleword)
29269 DIP("vcmpequd%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
29270 vD_addr
, vA_addr
, vB_addr
);
29271 assign( vD
, binop(Iop_CmpEQ64x2
, mkexpr(vA
), mkexpr(vB
)) );
29274 case 0x206: // vcmpgtub (Compare Greater-than Unsigned B, AV p168)
29275 DIP("vcmpgtub%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
29276 vD_addr
, vA_addr
, vB_addr
);
29277 assign( vD
, binop(Iop_CmpGT8Ux16
, mkexpr(vA
), mkexpr(vB
)) );
29280 case 0x246: // vcmpgtuh (Compare Greater-than Unsigned HW, AV p169)
29281 DIP("vcmpgtuh%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
29282 vD_addr
, vA_addr
, vB_addr
);
29283 assign( vD
, binop(Iop_CmpGT16Ux8
, mkexpr(vA
), mkexpr(vB
)) );
29286 case 0x286: // vcmpgtuw (Compare Greater-than Unsigned W, AV p170)
29287 DIP("vcmpgtuw%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
29288 vD_addr
, vA_addr
, vB_addr
);
29289 assign( vD
, binop(Iop_CmpGT32Ux4
, mkexpr(vA
), mkexpr(vB
)) );
29292 case 0x2C7: // vcmpgtud (Compare Greater-than Unsigned double)
29293 DIP("vcmpgtud%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
29294 vD_addr
, vA_addr
, vB_addr
);
29295 assign( vD
, binop(Iop_CmpGT64Ux2
, mkexpr(vA
), mkexpr(vB
)) );
29298 case 0x306: // vcmpgtsb (Compare Greater-than Signed B, AV p165)
29299 DIP("vcmpgtsb%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
29300 vD_addr
, vA_addr
, vB_addr
);
29301 assign( vD
, binop(Iop_CmpGT8Sx16
, mkexpr(vA
), mkexpr(vB
)) );
29304 case 0x346: // vcmpgtsh (Compare Greater-than Signed HW, AV p166)
29305 DIP("vcmpgtsh%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
29306 vD_addr
, vA_addr
, vB_addr
);
29307 assign( vD
, binop(Iop_CmpGT16Sx8
, mkexpr(vA
), mkexpr(vB
)) );
29310 case 0x386: // vcmpgtsw (Compare Greater-than Signed W, AV p167)
29311 DIP("vcmpgtsw%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
29312 vD_addr
, vA_addr
, vB_addr
);
29313 assign( vD
, binop(Iop_CmpGT32Sx4
, mkexpr(vA
), mkexpr(vB
)) );
29316 case 0x3C7: // vcmpgtsd (Compare Greater-than Signed double)
29317 DIP("vcmpgtsd%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
29318 vD_addr
, vA_addr
, vB_addr
);
29319 assign( vD
, binop(Iop_CmpGT64Sx2
, mkexpr(vA
), mkexpr(vB
)) );
29323 vex_printf("dis_av_cmp(ppc)(opc2)\n");
29327 putVReg( vD_addr
, mkexpr(vD
) );
29330 set_AV_CR6( mkexpr(vD
), True
);
29336 AltiVec Multiply-Sum Instructions
29338 static Bool
dis_av_multarith ( UInt prefix
, UInt theInstr
)
29341 UChar opc1
= ifieldOPC(theInstr
);
29342 UChar vD_addr
= ifieldRegDS(theInstr
);
29343 UChar vA_addr
= ifieldRegA(theInstr
);
29344 UChar vB_addr
= ifieldRegB(theInstr
);
29345 UChar vC_addr
= ifieldRegC(theInstr
);
29346 UChar opc2
= toUChar( IFIELD( theInstr
, 0, 6 ) );
29348 IRTemp vA
= newTemp(Ity_V128
);
29349 IRTemp vB
= newTemp(Ity_V128
);
29350 IRTemp vC
= newTemp(Ity_V128
);
29351 IRTemp zeros
= newTemp(Ity_V128
);
29352 IRTemp aLo
= newTemp(Ity_V128
);
29353 IRTemp bLo
= newTemp(Ity_V128
);
29354 IRTemp cLo
= newTemp(Ity_V128
);
29355 IRTemp zLo
= newTemp(Ity_V128
);
29356 IRTemp aHi
= newTemp(Ity_V128
);
29357 IRTemp bHi
= newTemp(Ity_V128
);
29358 IRTemp cHi
= newTemp(Ity_V128
);
29359 IRTemp zHi
= newTemp(Ity_V128
);
29360 IRTemp abEvn
= newTemp(Ity_V128
);
29361 IRTemp abOdd
= newTemp(Ity_V128
);
29362 IRTemp z3
= newTemp(Ity_I64
);
29363 IRTemp z2
= newTemp(Ity_I64
);
29364 IRTemp z1
= newTemp(Ity_I64
);
29365 IRTemp z0
= newTemp(Ity_I64
);
29366 IRTemp ab7
, ab6
, ab5
, ab4
, ab3
, ab2
, ab1
, ab0
;
29367 IRTemp c3
, c2
, c1
, c0
;
29369 /* There is no prefixed version of these instructions. */
29372 ab7
= ab6
= ab5
= ab4
= ab3
= ab2
= ab1
= ab0
= IRTemp_INVALID
;
29373 c3
= c2
= c1
= c0
= IRTemp_INVALID
;
29375 assign( vA
, getVReg(vA_addr
));
29376 assign( vB
, getVReg(vB_addr
));
29377 assign( vC
, getVReg(vC_addr
));
29378 assign( zeros
, unop(Iop_Dup32x4
, mkU32(0)) );
29381 vex_printf("dis_av_multarith(ppc)(instr)\n");
29387 case 0x20: { // vmhaddshs (Mult Hi, Add Signed HW Saturate, AV p185)
29388 IRTemp cSigns
= newTemp(Ity_V128
);
29389 DIP("vmhaddshs v%d,v%d,v%d,v%d\n",
29390 vD_addr
, vA_addr
, vB_addr
, vC_addr
);
29391 assign(cSigns
, binop(Iop_CmpGT16Sx8
, mkexpr(zeros
), mkexpr(vC
)));
29392 assign(aLo
, binop(Iop_InterleaveLO16x8
, mkexpr(zeros
), mkexpr(vA
)));
29393 assign(bLo
, binop(Iop_InterleaveLO16x8
, mkexpr(zeros
), mkexpr(vB
)));
29394 assign(cLo
, binop(Iop_InterleaveLO16x8
, mkexpr(cSigns
),mkexpr(vC
)));
29395 assign(aHi
, binop(Iop_InterleaveHI16x8
, mkexpr(zeros
), mkexpr(vA
)));
29396 assign(bHi
, binop(Iop_InterleaveHI16x8
, mkexpr(zeros
), mkexpr(vB
)));
29397 assign(cHi
, binop(Iop_InterleaveHI16x8
, mkexpr(cSigns
),mkexpr(vC
)));
29399 assign( zLo
, binop(Iop_Add32x4
, mkexpr(cLo
),
29400 binop(Iop_SarN32x4
,
29401 binop(Iop_MullEven16Sx8
,
29402 mkexpr(aLo
), mkexpr(bLo
)),
29405 assign( zHi
, binop(Iop_Add32x4
, mkexpr(cHi
),
29406 binop(Iop_SarN32x4
,
29407 binop(Iop_MullEven16Sx8
,
29408 mkexpr(aHi
), mkexpr(bHi
)),
29412 binop(Iop_QNarrowBin32Sto16Sx8
, mkexpr(zHi
), mkexpr(zLo
)) );
29415 case 0x21: { // vmhraddshs (Mult High Round, Add Signed HW Saturate, AV p186)
29416 IRTemp zKonst
= newTemp(Ity_V128
);
29417 IRTemp cSigns
= newTemp(Ity_V128
);
29418 DIP("vmhraddshs v%d,v%d,v%d,v%d\n",
29419 vD_addr
, vA_addr
, vB_addr
, vC_addr
);
29420 assign(cSigns
, binop(Iop_CmpGT16Sx8
, mkexpr(zeros
), mkexpr(vC
)) );
29421 assign(aLo
, binop(Iop_InterleaveLO16x8
, mkexpr(zeros
), mkexpr(vA
)));
29422 assign(bLo
, binop(Iop_InterleaveLO16x8
, mkexpr(zeros
), mkexpr(vB
)));
29423 assign(cLo
, binop(Iop_InterleaveLO16x8
, mkexpr(cSigns
),mkexpr(vC
)));
29424 assign(aHi
, binop(Iop_InterleaveHI16x8
, mkexpr(zeros
), mkexpr(vA
)));
29425 assign(bHi
, binop(Iop_InterleaveHI16x8
, mkexpr(zeros
), mkexpr(vB
)));
29426 assign(cHi
, binop(Iop_InterleaveHI16x8
, mkexpr(cSigns
),mkexpr(vC
)));
29428 /* shifting our const avoids store/load version of Dup */
29429 assign( zKonst
, binop(Iop_ShlN32x4
, unop(Iop_Dup32x4
, mkU32(0x1)),
29432 assign( zLo
, binop(Iop_Add32x4
, mkexpr(cLo
),
29433 binop(Iop_SarN32x4
,
29434 binop(Iop_Add32x4
, mkexpr(zKonst
),
29435 binop(Iop_MullEven16Sx8
,
29436 mkexpr(aLo
), mkexpr(bLo
))),
29439 assign( zHi
, binop(Iop_Add32x4
, mkexpr(cHi
),
29440 binop(Iop_SarN32x4
,
29441 binop(Iop_Add32x4
, mkexpr(zKonst
),
29442 binop(Iop_MullEven16Sx8
,
29443 mkexpr(aHi
), mkexpr(bHi
))),
29447 binop(Iop_QNarrowBin32Sto16Sx8
, mkexpr(zHi
), mkexpr(zLo
)) );
29450 case 0x22: { // vmladduhm (Mult Low, Add Unsigned HW Modulo, AV p194)
29451 DIP("vmladduhm v%d,v%d,v%d,v%d\n",
29452 vD_addr
, vA_addr
, vB_addr
, vC_addr
);
29453 assign(aLo
, binop(Iop_InterleaveLO16x8
, mkexpr(zeros
), mkexpr(vA
)));
29454 assign(bLo
, binop(Iop_InterleaveLO16x8
, mkexpr(zeros
), mkexpr(vB
)));
29455 assign(cLo
, binop(Iop_InterleaveLO16x8
, mkexpr(zeros
), mkexpr(vC
)));
29456 assign(aHi
, binop(Iop_InterleaveHI16x8
, mkexpr(zeros
), mkexpr(vA
)));
29457 assign(bHi
, binop(Iop_InterleaveHI16x8
, mkexpr(zeros
), mkexpr(vB
)));
29458 assign(cHi
, binop(Iop_InterleaveHI16x8
, mkexpr(zeros
), mkexpr(vC
)));
29459 assign(zLo
, binop(Iop_Add32x4
,
29460 binop(Iop_MullEven16Ux8
, mkexpr(aLo
), mkexpr(bLo
)),
29462 assign(zHi
, binop(Iop_Add32x4
,
29463 binop(Iop_MullEven16Ux8
, mkexpr(aHi
), mkexpr(bHi
)),
29466 binop(Iop_NarrowBin32to16x8
, mkexpr(zHi
), mkexpr(zLo
)) );
29470 case 0x23: { // vmsumudm
29471 DIP("vmsumudm v%d,v%d,v%d,v%d\n",
29472 vD_addr
, vA_addr
, vB_addr
, vC_addr
);
29473 /* This instruction takes input vectors VA, VB consisting of 2 usigned
29474 64-bit integer elements and a 128 bit unsigned input U128_C. The
29475 instruction performs the following operation:
29477 VA[0] * VB[0] -> U128_mul_result0;
29478 VA[1] * VB[1] -> U128_mul_result1;
29479 U128_C + U128_mul_result0 + U128_mul_result1 -> U128_partial_sum;
29480 carry out and overflow is discarded.
29483 /* The Iop_MulI128low assumes the upper 64-bits in the two input operands
29485 IRTemp mul_result0
= newTemp( Ity_I128
);
29486 IRTemp mul_result1
= newTemp( Ity_I128
);
29487 IRTemp partial_sum_hi
= newTemp( Ity_I64
);
29488 IRTemp partial_sum_low
= newTemp( Ity_I64
);
29489 IRTemp result_hi
= newTemp( Ity_I64
);
29490 IRTemp result_low
= newTemp( Ity_I64
);
29491 IRExpr
*ca_sum
, *ca_result
;
29494 /* Do multiplications */
29495 assign ( mul_result0
, binop( Iop_MullU64
,
29496 unop( Iop_V128to64
, mkexpr( vA
) ),
29497 unop( Iop_V128to64
, mkexpr( vB
) ) ) );
29499 assign ( mul_result1
, binop( Iop_MullU64
,
29500 unop( Iop_V128HIto64
, mkexpr( vA
) ),
29501 unop( Iop_V128HIto64
, mkexpr( vB
) ) ) );
29503 /* Add the two 128-bit results using 64-bit unsigned adds, calculate carry
29504 from low 64-bits add into sum of upper 64-bits. Throw away carry out
29505 of the upper 64-bit sum. */
29506 assign ( partial_sum_low
, binop( Iop_Add64
,
29507 unop( Iop_128to64
, mkexpr( mul_result0
) ),
29508 unop( Iop_128to64
, mkexpr( mul_result1
) )
29511 /* ca_sum is type U32 */
29512 ca_sum
= calculate_XER_CA_64 ( PPCG_FLAG_OP_ADD
,
29513 mkexpr(partial_sum_low
),
29514 unop( Iop_128to64
, mkexpr( mul_result0
) ),
29515 unop( Iop_128to64
, mkexpr( mul_result1
) ),
29518 assign ( partial_sum_hi
,
29521 unop( Iop_128HIto64
, mkexpr( mul_result0
) ),
29522 unop( Iop_128HIto64
, mkexpr( mul_result1
) ) ),
29523 binop( Iop_32HLto64
, mkU32( 0 ), ca_sum
) ) );
29525 /* Now add in the value of C */
29526 assign ( result_low
, binop( Iop_Add64
,
29527 mkexpr( partial_sum_low
),
29528 unop( Iop_V128to64
, mkexpr( vC
) ) ) );
29530 /* ca_result is type U32 */
29531 ca_result
= calculate_XER_CA_64( PPCG_FLAG_OP_ADD
,
29532 mkexpr( result_low
),
29533 mkexpr( partial_sum_low
),
29534 unop( Iop_V128to64
,
29538 assign ( result_hi
,
29541 mkexpr( partial_sum_hi
),
29542 unop( Iop_V128HIto64
, mkexpr( vC
) ) ),
29543 binop( Iop_32HLto64
, mkU32( 0 ), ca_result
) ) );
29545 putVReg( vD_addr
, binop( Iop_64HLtoV128
,
29546 mkexpr( result_hi
), mkexpr ( result_low
) ) );
29551 case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204)
29552 IRTemp abEE
, abEO
, abOE
, abOO
;
29553 abEE
= abEO
= abOE
= abOO
= IRTemp_INVALID
;
29554 DIP("vmsumubm v%d,v%d,v%d,v%d\n",
29555 vD_addr
, vA_addr
, vB_addr
, vC_addr
);
29557 /* multiply vA,vB (unsigned, widening) */
29558 assign( abEvn
, MK_Iop_MullOdd8Ux16( mkexpr(vA
), mkexpr(vB
) ));
29559 assign( abOdd
, binop(Iop_MullEven8Ux16
, mkexpr(vA
), mkexpr(vB
)) );
29561 /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */
29562 expand16Ux8( mkexpr(abEvn
), &abEE
, &abEO
);
29563 expand16Ux8( mkexpr(abOdd
), &abOE
, &abOO
);
29566 binop(Iop_Add32x4
, mkexpr(vC
),
29568 binop(Iop_Add32x4
, mkexpr(abEE
), mkexpr(abEO
)),
29569 binop(Iop_Add32x4
, mkexpr(abOE
), mkexpr(abOO
)))) );
29572 case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201)
29573 IRTemp aEvn
, aOdd
, bEvn
, bOdd
;
29574 IRTemp abEE
= newTemp(Ity_V128
);
29575 IRTemp abEO
= newTemp(Ity_V128
);
29576 IRTemp abOE
= newTemp(Ity_V128
);
29577 IRTemp abOO
= newTemp(Ity_V128
);
29578 IRTemp prod
= newTemp(Ity_V128
);
29579 IRTemp sum0
= newTemp(Ity_I32
);
29580 IRTemp sum1
= newTemp(Ity_I32
);
29581 IRTemp sum2
= newTemp(Ity_I32
);
29582 IRTemp sum3
= newTemp(Ity_I32
);
29584 aEvn
= aOdd
= bEvn
= bOdd
= IRTemp_INVALID
;
29585 DIP("vmsummbm v%d,v%d,v%d,v%d\n",
29586 vD_addr
, vA_addr
, vB_addr
, vC_addr
);
29588 /* sign-extend vA, zero-extend vB, for mixed-sign multiply
29589 (separating out adjacent lanes to different vectors) */
29590 expand8Sx16( mkexpr(vA
), &aEvn
, &aOdd
);
29591 expand8Ux16( mkexpr(vB
), &bEvn
, &bOdd
);
29593 /* multiply vA, vB, again separating adjacent lanes */
29594 assign( abEE
, MK_Iop_MullOdd16Sx8( mkexpr(aEvn
), mkexpr(bEvn
) ));
29595 assign( abEO
, binop(Iop_MullEven16Sx8
, mkexpr(aEvn
), mkexpr(bEvn
)) );
29596 assign( abOE
, MK_Iop_MullOdd16Sx8( mkexpr(aOdd
), mkexpr(bOdd
) ));
29597 assign( abOO
, binop(Iop_MullEven16Sx8
, mkexpr(aOdd
), mkexpr(bOdd
)) );
29599 /* add results together, + vC */
29600 /* Unfortunately, we need to chop the results of the adds to 32-bits. The
29601 following lane based calculations don't handle the overflow correctly. Need
29602 to explicitly do the adds and 32-bit chops.
29605 binop(Iop_QAdd32Sx4, mkexpr(vC),
29606 binop(Iop_QAdd32Sx4,
29607 binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)),
29608 binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)))) );
29612 binop(Iop_QAdd32Sx4
,
29613 binop(Iop_QAdd32Sx4
, mkexpr(abEE
), mkexpr(abEO
)),
29614 binop(Iop_QAdd32Sx4
, mkexpr(abOE
), mkexpr(abOO
))));
29619 unop(Iop_64HIto32
, unop(Iop_V128HIto64
, mkexpr(prod
)))),
29621 unop(Iop_64HIto32
, unop(Iop_V128HIto64
, mkexpr(vC
)))))));
29626 unop(Iop_64to32
, unop(Iop_V128HIto64
, mkexpr(prod
)))),
29628 unop(Iop_64to32
, unop(Iop_V128HIto64
, mkexpr(vC
)))))));
29633 unop(Iop_64HIto32
, unop(Iop_V128to64
, mkexpr(prod
)))),
29635 unop(Iop_64HIto32
, unop(Iop_V128to64
, mkexpr(vC
)))))));
29640 unop(Iop_64to32
, unop(Iop_V128to64
, mkexpr(prod
)))),
29642 unop(Iop_64to32
, unop(Iop_V128to64
, mkexpr(vC
)))))));
29643 putVReg( vD_addr
, binop(Iop_64HLtoV128
,
29644 binop(Iop_32HLto64
, mkexpr(sum0
), mkexpr(sum1
)),
29645 binop(Iop_32HLto64
, mkexpr(sum2
), mkexpr(sum3
))));
29649 case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205)
29650 DIP("vmsumuhm v%d,v%d,v%d,v%d\n",
29651 vD_addr
, vA_addr
, vB_addr
, vC_addr
);
29652 assign( abEvn
, MK_Iop_MullOdd16Ux8( mkexpr(vA
), mkexpr(vB
) ));
29653 assign( abOdd
, binop(Iop_MullEven16Ux8
, mkexpr(vA
), mkexpr(vB
)) );
29655 binop(Iop_Add32x4
, mkexpr(vC
),
29656 binop(Iop_Add32x4
, mkexpr(abEvn
), mkexpr(abOdd
))) );
29659 case 0x27: { // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206)
29660 DIP("vmsumuhs v%d,v%d,v%d,v%d\n",
29661 vD_addr
, vA_addr
, vB_addr
, vC_addr
);
29662 /* widening multiply, separating lanes */
29663 assign( abEvn
, MK_Iop_MullOdd16Ux8(mkexpr(vA
), mkexpr(vB
) ));
29664 assign( abOdd
, binop(Iop_MullEven16Ux8
, mkexpr(vA
), mkexpr(vB
)) );
29666 /* break V128 to 4xI32's, zero-extending to I64's */
29667 breakV128to4x64U( mkexpr(abEvn
), &ab7
, &ab5
, &ab3
, &ab1
);
29668 breakV128to4x64U( mkexpr(abOdd
), &ab6
, &ab4
, &ab2
, &ab0
);
29669 breakV128to4x64U( mkexpr(vC
), &c3
, &c2
, &c1
, &c0
);
29672 assign( z3
, binop(Iop_Add64
, mkexpr(c3
),
29673 binop(Iop_Add64
, mkexpr(ab7
), mkexpr(ab6
))));
29674 assign( z2
, binop(Iop_Add64
, mkexpr(c2
),
29675 binop(Iop_Add64
, mkexpr(ab5
), mkexpr(ab4
))));
29676 assign( z1
, binop(Iop_Add64
, mkexpr(c1
),
29677 binop(Iop_Add64
, mkexpr(ab3
), mkexpr(ab2
))));
29678 assign( z0
, binop(Iop_Add64
, mkexpr(c0
),
29679 binop(Iop_Add64
, mkexpr(ab1
), mkexpr(ab0
))));
29681 /* saturate-narrow to 32bit, and combine to V128 */
29682 putVReg( vD_addr
, mkV128from4x64U( mkexpr(z3
), mkexpr(z2
),
29683 mkexpr(z1
), mkexpr(z0
)) );
29687 case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202)
29688 DIP("vmsumshm v%d,v%d,v%d,v%d\n",
29689 vD_addr
, vA_addr
, vB_addr
, vC_addr
);
29690 assign( abEvn
, MK_Iop_MullOdd16Sx8( mkexpr(vA
), mkexpr(vB
) ));
29691 assign( abOdd
, binop(Iop_MullEven16Sx8
, mkexpr(vA
), mkexpr(vB
)) );
29693 binop(Iop_Add32x4
, mkexpr(vC
),
29694 binop(Iop_Add32x4
, mkexpr(abOdd
), mkexpr(abEvn
))) );
29697 case 0x29: { // vmsumshs (Multiply Sum Signed HW Saturate, AV p203)
29698 DIP("vmsumshs v%d,v%d,v%d,v%d\n",
29699 vD_addr
, vA_addr
, vB_addr
, vC_addr
);
29700 /* widening multiply, separating lanes */
29701 assign( abEvn
, MK_Iop_MullOdd16Sx8( mkexpr(vA
), mkexpr(vB
) ));
29702 assign( abOdd
, binop(Iop_MullEven16Sx8
, mkexpr(vA
), mkexpr(vB
)) );
29704 /* break V128 to 4xI32's, sign-extending to I64's */
29705 breakV128to4x64S( mkexpr(abEvn
), &ab7
, &ab5
, &ab3
, &ab1
);
29706 breakV128to4x64S( mkexpr(abOdd
), &ab6
, &ab4
, &ab2
, &ab0
);
29707 breakV128to4x64S( mkexpr(vC
), &c3
, &c2
, &c1
, &c0
);
29710 assign( z3
, binop(Iop_Add64
, mkexpr(c3
),
29711 binop(Iop_Add64
, mkexpr(ab7
), mkexpr(ab6
))));
29712 assign( z2
, binop(Iop_Add64
, mkexpr(c2
),
29713 binop(Iop_Add64
, mkexpr(ab5
), mkexpr(ab4
))));
29714 assign( z1
, binop(Iop_Add64
, mkexpr(c1
),
29715 binop(Iop_Add64
, mkexpr(ab3
), mkexpr(ab2
))));
29716 assign( z0
, binop(Iop_Add64
, mkexpr(c0
),
29717 binop(Iop_Add64
, mkexpr(ab1
), mkexpr(ab0
))));
29719 /* saturate-narrow to 32bit, and combine to V128 */
29720 putVReg( vD_addr
, mkV128from4x64S( mkexpr(z3
), mkexpr(z2
),
29721 mkexpr(z1
), mkexpr(z0
)) );
29725 vex_printf("dis_av_multarith(ppc)(opc2)\n");
29732 AltiVec Polynomial Multiply-Sum Instructions
29734 static Bool
dis_av_polymultarith ( UInt prefix
, UInt theInstr
)
29737 UChar opc1
= ifieldOPC(theInstr
);
29738 UChar vD_addr
= ifieldRegDS(theInstr
);
29739 UChar vA_addr
= ifieldRegA(theInstr
);
29740 UChar vB_addr
= ifieldRegB(theInstr
);
29741 UChar vC_addr
= ifieldRegC(theInstr
);
29742 UInt opc2
= IFIELD(theInstr
, 0, 11);
29743 IRTemp vA
= newTemp(Ity_V128
);
29744 IRTemp vB
= newTemp(Ity_V128
);
29745 IRTemp vC
= newTemp(Ity_V128
);
29747 /* There is no prefixed version of these instructions. */
29750 assign( vA
, getVReg(vA_addr
));
29751 assign( vB
, getVReg(vB_addr
));
29752 assign( vC
, getVReg(vC_addr
));
29755 vex_printf("dis_av_polymultarith(ppc)(instr)\n");
29760 /* Polynomial Multiply-Add */
29761 case 0x408: // vpmsumb Vector Polynomial Multiply-sum Byte
29762 DIP("vpmsumb v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
29763 putVReg( vD_addr
, binop(Iop_PolynomialMulAdd8x16
,
29764 mkexpr(vA
), mkexpr(vB
)) );
29766 case 0x448: // vpmsumd Vector Polynomial Multiply-sum Double Word
29767 DIP("vpmsumd v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
29768 putVReg( vD_addr
, binop(Iop_PolynomialMulAdd64x2
,
29769 mkexpr(vA
), mkexpr(vB
)) );
29771 case 0x488: // vpmsumw Vector Polynomial Multiply-sum Word
29772 DIP("vpmsumw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
29773 putVReg( vD_addr
, binop(Iop_PolynomialMulAdd32x4
,
29774 mkexpr(vA
), mkexpr(vB
)) );
29776 case 0x4C8: // vpmsumh Vector Polynomial Multiply-sum Half Word
29777 DIP("vpmsumh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
29778 putVReg( vD_addr
, binop(Iop_PolynomialMulAdd16x8
,
29779 mkexpr(vA
), mkexpr(vB
)) );
29782 vex_printf("dis_av_polymultarith(ppc)(opc2=0x%x)\n", opc2
);
29789 AltiVec Shift/Rotate Instructions
29791 static Bool
dis_av_shift ( UInt prefix
, UInt theInstr
)
29794 UChar opc1
= ifieldOPC(theInstr
);
29795 UChar vD_addr
= ifieldRegDS(theInstr
);
29796 UChar vA_addr
= ifieldRegA(theInstr
);
29797 UChar vB_addr
= ifieldRegB(theInstr
);
29798 UInt opc2_vx_form
= IFIELD( theInstr
, 0, 11 );
29799 UInt opc2_vn_form
= IFIELD( theInstr
, 0, 6 );
29801 IRTemp vA
= newTemp(Ity_V128
);
29802 IRTemp vB
= newTemp(Ity_V128
);
29804 /* There is no prefixed version of these instructions. */
29807 assign( vA
, getVReg(vA_addr
));
29808 assign( vB
, getVReg(vB_addr
));
29811 vex_printf("dis_av_shift(ppc)(instr)\n");
29814 if (opc2_vn_form
== 0x16) {
29815 UInt SH
= IFIELD( theInstr
, 6, 3 );
29816 UInt bit21_22
= IFIELD( theInstr
, 9, 2 );
29817 IRTemp Middle_128
= newTemp(Ity_V128
);
29818 IRTemp tmpLo_64
= newTemp(Ity_I64
);
29819 IRTemp tmpHi_64
= newTemp(Ity_I64
);
29820 IRTemp result
= newTemp(Ity_V128
);
29822 assign( Middle_128
, binop( Iop_64HLtoV128
,
29823 unop( Iop_V128to64
, mkexpr( vA
) ),
29824 unop( Iop_V128HIto64
, mkexpr( vB
) ) ) );
29826 if (bit21_22
== 0) {
29827 // Vector Shift Left Double by Bit Immediate VN-form
29828 DIP("vsldbi v%u,v%u,v%u,%u\n", vD_addr
, vA_addr
, vB_addr
, SH
);
29831 unop( Iop_V128HIto64
,
29832 binop( Iop_ShlV128
,
29836 binop( Iop_64HLtoV128
,
29837 mkexpr( tmpHi_64
),
29838 unop( Iop_V128HIto64
,
29839 binop( Iop_ShlV128
,
29840 mkexpr( Middle_128
),
29841 mkU8( SH
) ) ) ) );
29843 // Vector Shift right Double by Bit Immediate VN-form
29844 DIP("vsrdbi v%u,v%u,v%u,%u\n", vD_addr
, vA_addr
, vB_addr
, SH
);
29847 unop( Iop_V128to64
,
29848 binop( Iop_ShrV128
,
29852 binop( Iop_64HLtoV128
,
29853 unop( Iop_V128to64
,
29854 binop( Iop_ShrV128
,
29855 mkexpr( Middle_128
),
29857 mkexpr( tmpLo_64
) ) );
29859 putVReg( vD_addr
, mkexpr( result
) );
29863 switch (opc2_vx_form
) {
29865 case 0x004: // vrlb (Rotate Left Integer B, AV p234)
29866 DIP("vrlb v%u,v%u,v%u\n", vD_addr
, vA_addr
, vB_addr
);
29867 putVReg( vD_addr
, binop(Iop_Rol8x16
, mkexpr(vA
), mkexpr(vB
)) );
29870 case 0x044: // vrlh (Rotate Left Integer HW, AV p235)
29871 DIP("vrlh v%u,v%u,v%u\n", vD_addr
, vA_addr
, vB_addr
);
29872 putVReg( vD_addr
, binop(Iop_Rol16x8
, mkexpr(vA
), mkexpr(vB
)) );
29875 case 0x084: // vrlw (Rotate Left Integer W, AV p236)
29876 DIP("vrlw v%u,v%u,v%u\n", vD_addr
, vA_addr
, vB_addr
);
29877 putVReg( vD_addr
, binop(Iop_Rol32x4
, mkexpr(vA
), mkexpr(vB
)) );
29880 case 0x0C4: // vrld (Rotate Left Integer Double Word)
29881 DIP("vrld v%u,v%u,v%u\n", vD_addr
, vA_addr
, vB_addr
);
29882 putVReg( vD_addr
, binop(Iop_Rol64x2
, mkexpr(vA
), mkexpr(vB
)) );
29887 case 0x104: // vslb (Shift Left Integer B, AV p240)
29888 DIP("vslb v%u,v%u,v%u\n", vD_addr
, vA_addr
, vB_addr
);
29889 putVReg( vD_addr
, binop(Iop_Shl8x16
, mkexpr(vA
), mkexpr(vB
)) );
29892 case 0x144: // vslh (Shift Left Integer HW, AV p242)
29893 DIP("vslh v%u,v%u,v%u\n", vD_addr
, vA_addr
, vB_addr
);
29894 putVReg( vD_addr
, binop(Iop_Shl16x8
, mkexpr(vA
), mkexpr(vB
)) );
29897 case 0x184: // vslw (Shift Left Integer W, AV p244)
29898 DIP("vslw v%u,v%u,v%u\n", vD_addr
, vA_addr
, vB_addr
);
29899 putVReg( vD_addr
, binop(Iop_Shl32x4
, mkexpr(vA
), mkexpr(vB
)) );
29902 case 0x5C4: // vsld (Shift Left Integer Double Word)
29903 DIP("vsld v%u,v%u,v%u\n", vD_addr
, vA_addr
, vB_addr
);
29904 putVReg( vD_addr
, binop(Iop_Shl64x2
, mkexpr(vA
), mkexpr(vB
)) );
29907 case 0x1C4: { // vsl (Shift Left, AV p239)
29908 IRTemp sh
= newTemp(Ity_I8
);
29909 DIP("vsl v%u,v%u,v%u\n", vD_addr
, vA_addr
, vB_addr
);
29910 assign( sh
, binop(Iop_And8
, mkU8(0x7),
29912 unop(Iop_V128to32
, mkexpr(vB
)))) );
29914 binop(Iop_ShlV128
, mkexpr(vA
), mkexpr(sh
)) );
29917 case 0x40C: { // vslo (Shift Left by Octet, AV p243)
29918 IRTemp sh
= newTemp(Ity_I8
);
29919 DIP("vslo v%u,v%u,v%u\n", vD_addr
, vA_addr
, vB_addr
);
29920 assign( sh
, binop(Iop_And8
, mkU8(0x78),
29922 unop(Iop_V128to32
, mkexpr(vB
)))) );
29924 binop(Iop_ShlV128
, mkexpr(vA
), mkexpr(sh
)) );
29930 case 0x204: // vsrb (Shift Right B, AV p256)
29931 DIP("vsrb v%u,v%u,v%u\n", vD_addr
, vA_addr
, vB_addr
);
29932 putVReg( vD_addr
, binop(Iop_Shr8x16
, mkexpr(vA
), mkexpr(vB
)) );
29935 case 0x244: // vsrh (Shift Right HW, AV p257)
29936 DIP("vsrh v%u,v%u,v%u\n", vD_addr
, vA_addr
, vB_addr
);
29937 putVReg( vD_addr
, binop(Iop_Shr16x8
, mkexpr(vA
), mkexpr(vB
)) );
29940 case 0x284: // vsrw (Shift Right W, AV p259)
29941 DIP("vsrw v%u,v%u,v%u\n", vD_addr
, vA_addr
, vB_addr
);
29942 putVReg( vD_addr
, binop(Iop_Shr32x4
, mkexpr(vA
), mkexpr(vB
)) );
29945 case 0x2C4: { // vsr (Shift Right, AV p251)
29946 IRTemp sh
= newTemp(Ity_I8
);
29947 DIP("vsr v%u,v%u,v%u\n", vD_addr
, vA_addr
, vB_addr
);
29948 assign( sh
, binop(Iop_And8
, mkU8(0x7),
29950 unop(Iop_V128to32
, mkexpr(vB
)))) );
29952 binop(Iop_ShrV128
, mkexpr(vA
), mkexpr(sh
)) );
29955 case 0x304: // vsrab (Shift Right Alg B, AV p253)
29956 DIP("vsrab v%u,v%u,v%u\n", vD_addr
, vA_addr
, vB_addr
);
29957 putVReg( vD_addr
, binop(Iop_Sar8x16
, mkexpr(vA
), mkexpr(vB
)) );
29960 case 0x344: // vsrah (Shift Right Alg HW, AV p254)
29961 DIP("vsrah v%u,v%u,v%u\n", vD_addr
, vA_addr
, vB_addr
);
29962 putVReg( vD_addr
, binop(Iop_Sar16x8
, mkexpr(vA
), mkexpr(vB
)) );
29965 case 0x384: // vsraw (Shift Right Alg W, AV p255)
29966 DIP("vsraw v%u,v%u,v%u\n", vD_addr
, vA_addr
, vB_addr
);
29967 putVReg( vD_addr
, binop(Iop_Sar32x4
, mkexpr(vA
), mkexpr(vB
)) );
29970 case 0x3C4: // vsrad (Shift Right Alg Double Word)
29971 DIP("vsrad v%u,v%u,v%u\n", vD_addr
, vA_addr
, vB_addr
);
29972 putVReg( vD_addr
, binop(Iop_Sar64x2
, mkexpr(vA
), mkexpr(vB
)) );
29975 case 0x44C: { // vsro (Shift Right by Octet, AV p258)
29976 IRTemp sh
= newTemp(Ity_I8
);
29977 DIP("vsro v%u,v%u,v%u\n", vD_addr
, vA_addr
, vB_addr
);
29978 assign( sh
, binop(Iop_And8
, mkU8(0x78),
29980 unop(Iop_V128to32
, mkexpr(vB
)))) );
29982 binop(Iop_ShrV128
, mkexpr(vA
), mkexpr(sh
)) );
29986 case 0x6C4: // vsrd (Shift Right Double Word)
29987 DIP("vsrd v%u,v%u,v%u\n", vD_addr
, vA_addr
, vB_addr
);
29988 putVReg( vD_addr
, binop(Iop_Shr64x2
, mkexpr(vA
), mkexpr(vB
)) );
29993 vex_printf("dis_av_shift(ppc)(opc2)\n");
30000 AltiVec Permute Instructions
30002 static Bool
dis_av_permute ( UInt prefix
, UInt theInstr
)
30004 /* VA-Form, VX-Form */
30005 UChar opc1
= ifieldOPC(theInstr
);
30006 UChar vD_addr
= ifieldRegDS(theInstr
);
30007 UChar vA_addr
= ifieldRegA(theInstr
);
30008 UChar UIMM_5
= vA_addr
;
30009 UChar vB_addr
= ifieldRegB(theInstr
);
30010 UChar vC_addr
= ifieldRegC(theInstr
);
30011 UChar b10
= ifieldBIT10(theInstr
);
30012 UChar SHB_uimm4
= toUChar( IFIELD( theInstr
, 6, 4 ) );
30013 UInt opc2
= toUChar( IFIELD( theInstr
, 0, 6 ) );
30015 UChar SIMM_8
= extend_s_5to8(UIMM_5
);
30017 IRTemp vA
= newTemp(Ity_V128
);
30018 IRTemp vB
= newTemp(Ity_V128
);
30019 IRTemp vC
= newTemp(Ity_V128
);
30021 /* There is no prefixed version of these instructions. */
30024 assign( vA
, getVReg(vA_addr
));
30025 assign( vB
, getVReg(vB_addr
));
30026 assign( vC
, getVReg(vC_addr
));
30029 vex_printf("dis_av_permute(ppc)(instr)\n");
30034 case 0x2A: // vsel (Conditional Select, AV p238)
30035 DIP("vsel v%d,v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
, vC_addr
);
30036 /* vD = (vA & ~vC) | (vB & vC) */
30037 putVReg( vD_addr
, binop(Iop_OrV128
,
30038 binop(Iop_AndV128
, mkexpr(vA
), unop(Iop_NotV128
, mkexpr(vC
))),
30039 binop(Iop_AndV128
, mkexpr(vB
), mkexpr(vC
))) );
30042 case 0x2B: { // vperm (Permute, AV p218)
30043 /* limited to two args for IR, so have to play games... */
30044 IRTemp a_perm
= newTemp(Ity_V128
);
30045 IRTemp b_perm
= newTemp(Ity_V128
);
30046 IRTemp mask
= newTemp(Ity_V128
);
30047 IRTemp vC_andF
= newTemp(Ity_V128
);
30048 DIP("vperm v%d,v%d,v%d,v%d\n",
30049 vD_addr
, vA_addr
, vB_addr
, vC_addr
);
30050 /* Limit the Perm8x16 steering values to 0 .. 15 as that is what
30051 IR specifies, and also to hide irrelevant bits from
30054 binop(Iop_AndV128
, mkexpr(vC
),
30055 unop(Iop_Dup8x16
, mkU8(0xF))) );
30057 binop(Iop_Perm8x16
, mkexpr(vA
), mkexpr(vC_andF
)) );
30059 binop(Iop_Perm8x16
, mkexpr(vB
), mkexpr(vC_andF
)) );
30060 // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0
30061 assign( mask
, binop(Iop_SarN8x16
,
30062 binop(Iop_ShlN8x16
, mkexpr(vC
), mkU8(3)),
30064 // dst = (a & ~mask) | (b & mask)
30065 putVReg( vD_addr
, binop(Iop_OrV128
,
30066 binop(Iop_AndV128
, mkexpr(a_perm
),
30067 unop(Iop_NotV128
, mkexpr(mask
))),
30068 binop(Iop_AndV128
, mkexpr(b_perm
),
30072 case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241)
30074 vex_printf("dis_av_permute(ppc)(vsldoi)\n");
30077 DIP("vsldoi v%d,v%d,v%d,%d\n",
30078 vD_addr
, vA_addr
, vB_addr
, SHB_uimm4
);
30079 if (SHB_uimm4
== 0)
30080 putVReg( vD_addr
, mkexpr(vA
) );
30084 binop(Iop_ShlV128
, mkexpr(vA
), mkU8(SHB_uimm4
*8)),
30085 binop(Iop_ShrV128
, mkexpr(vB
), mkU8((16-SHB_uimm4
)*8))) );
30087 case 0x2D: { // vpermxor (Vector Permute and Exclusive-OR)
30088 IRTemp a_perm
= newTemp(Ity_V128
);
30089 IRTemp b_perm
= newTemp(Ity_V128
);
30090 IRTemp vrc_a
= newTemp(Ity_V128
);
30091 IRTemp vrc_b
= newTemp(Ity_V128
);
30093 DIP("vpermxor v%d,v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
, vC_addr
);
30095 /* IBM index is 0:7, Change index value to index 7:0 */
30096 assign( vrc_b
, binop( Iop_AndV128
, mkexpr( vC
),
30097 unop( Iop_Dup8x16
, mkU8( 0xF ) ) ) );
30098 assign( vrc_a
, binop( Iop_ShrV128
,
30099 binop( Iop_AndV128
, mkexpr( vC
),
30100 unop( Iop_Dup8x16
, mkU8( 0xF0 ) ) ),
30102 assign( a_perm
, binop( Iop_Perm8x16
, mkexpr( vA
), mkexpr( vrc_a
) ) );
30103 assign( b_perm
, binop( Iop_Perm8x16
, mkexpr( vB
), mkexpr( vrc_b
) ) );
30104 putVReg( vD_addr
, binop( Iop_XorV128
,
30105 mkexpr( a_perm
), mkexpr( b_perm
) ) );
30109 case 0x3B: { // vpermr (Vector Permute Right-indexed)
30110 /* limited to two args for IR, so have to play games... */
30111 IRTemp a_perm
= newTemp( Ity_V128
);
30112 IRTemp b_perm
= newTemp( Ity_V128
);
30113 IRTemp mask
= newTemp( Ity_V128
);
30114 IRTemp vC_andF
= newTemp( Ity_V128
);
30115 IRTemp vC_adj
= newTemp( Ity_V128
);
30117 DIP( "vpermr v%d,v%d,v%d,v%d\n",
30118 vD_addr
, vA_addr
, vB_addr
, vC_addr
);
30119 /* Limit the Perm8x16 steering values to 0 .. 15 as that is what
30120 IR specifies, and also to hide irrelevant bits from
30125 binop( Iop_Sub16x8
,
30126 unop( Iop_Dup8x16
, mkU8( 0x1F ) ),
30129 binop( Iop_AndV128
, mkexpr( vC_adj
),
30130 unop( Iop_Dup8x16
, mkU8( 0xF ) ) ) );
30132 binop( Iop_Perm8x16
, mkexpr( vA
), mkexpr( vC_andF
) ) );
30134 binop( Iop_Perm8x16
, mkexpr( vB
), mkexpr( vC_andF
) ) );
30135 // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0
30136 assign( mask
, binop(Iop_SarN8x16
,
30137 binop( Iop_ShlN8x16
, mkexpr( vC_adj
),
30138 mkU8( 3 ) ), mkU8( 7 ) ) );
30139 // dst = (a & ~mask) | (b & mask)
30140 putVReg( vD_addr
, binop( Iop_OrV128
,
30141 binop( Iop_AndV128
, mkexpr( a_perm
),
30142 unop( Iop_NotV128
, mkexpr( mask
) ) ),
30143 binop( Iop_AndV128
, mkexpr( b_perm
),
30144 mkexpr( mask
) ) ) );
30149 break; // Fall through...
30152 opc2
= IFIELD( theInstr
, 0, 11 );
30156 case 0x00C: // vmrghb (Merge High B, AV p195)
30157 DIP("vmrghb v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
30159 binop(Iop_InterleaveHI8x16
, mkexpr(vA
), mkexpr(vB
)) );
30162 case 0x04C: // vmrghh (Merge High HW, AV p196)
30163 DIP("vmrghh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
30165 binop(Iop_InterleaveHI16x8
, mkexpr(vA
), mkexpr(vB
)) );
30168 case 0x08C: // vmrghw (Merge High W, AV p197)
30169 DIP("vmrghw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
30171 binop(Iop_InterleaveHI32x4
, mkexpr(vA
), mkexpr(vB
)) );
30174 case 0x10C: // vmrglb (Merge Low B, AV p198)
30175 DIP("vmrglb v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
30177 binop(Iop_InterleaveLO8x16
, mkexpr(vA
), mkexpr(vB
)) );
30180 case 0x14C: // vmrglh (Merge Low HW, AV p199)
30181 DIP("vmrglh v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
30183 binop(Iop_InterleaveLO16x8
, mkexpr(vA
), mkexpr(vB
)) );
30186 case 0x18C: // vmrglw (Merge Low W, AV p200)
30187 DIP("vmrglw v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
30189 binop(Iop_InterleaveLO32x4
, mkexpr(vA
), mkexpr(vB
)) );
30192 /* Extract instructions */
30193 case 0x20D: // vextractub (Vector Extract Unsigned Byte)
30195 UChar uim
= IFIELD( theInstr
, 16, 4 );
30197 DIP("vextractub v%d,v%d,%d\n", vD_addr
, vB_addr
, uim
);
30199 putVReg( vD_addr
, binop( Iop_ShlV128
,
30200 binop( Iop_AndV128
,
30201 binop( Iop_ShrV128
,
30206 mkU32( 31 - uim
) ) ) ),
30207 binop( Iop_64HLtoV128
,
30209 mkU64( 0xFFULL
) ) ),
30214 case 0x24D: // vextractuh (Vector Extract Unsigned Halfword)
30216 UChar uim
= IFIELD( theInstr
, 16, 4 );
30218 DIP("vextractuh v%d,v%d,%d\n", vD_addr
, vB_addr
, uim
);
30220 putVReg( vD_addr
, binop( Iop_ShlV128
,
30221 binop( Iop_AndV128
,
30222 binop( Iop_ShrV128
,
30227 mkU32( 30 - uim
) ) ) ),
30228 binop( Iop_64HLtoV128
,
30230 mkU64( 0xFFFFULL
) ) ),
30235 case 0x28D: // vextractuw (Vector Extract Unsigned Word)
30237 UChar uim
= IFIELD( theInstr
, 16, 4 );
30239 DIP("vextractuw v%d,v%d,%d\n", vD_addr
, vB_addr
, uim
);
30242 binop( Iop_ShlV128
,
30243 binop( Iop_AndV128
,
30244 binop( Iop_ShrV128
,
30249 mkU32( 28 - uim
) ) ) ),
30250 binop( Iop_64HLtoV128
,
30252 mkU64( 0xFFFFFFFFULL
) ) ),
30257 case 0x2CD: // vextractd (Vector Extract Double Word)
30259 UChar uim
= IFIELD( theInstr
, 16, 4 );
30261 DIP("vextractd v%d,v%d,%d\n", vD_addr
, vB_addr
, uim
);
30264 binop( Iop_ShlV128
,
30265 binop( Iop_AndV128
,
30266 binop( Iop_ShrV128
,
30271 mkU32( 24 - uim
) ) ) ),
30272 binop( Iop_64HLtoV128
,
30274 mkU64( 0xFFFFFFFFFFFFFFFFULL
) ) ),
30279 /* Insert instructions */
30280 case 0x30D: // vinsertb (Vector insert Unsigned Byte)
30282 UChar uim
= IFIELD( theInstr
, 16, 4 );
30283 IRTemp shift
= newTemp( Ity_I8
);
30284 IRTemp vD
= newTemp( Ity_V128
);
30286 DIP("vinsertb v%d,v%d,%d\n", vD_addr
, vB_addr
, uim
);
30288 assign( vD
, getVReg( vD_addr
) );
30290 assign( shift
, unop( Iop_32to8
,
30293 mkU32( 15 - ( uim
+ 0 ) ) ) ) );
30297 binop( Iop_ShlV128
,
30298 binop( Iop_AndV128
,
30299 binop( Iop_ShrV128
,
30301 mkU8( ( 15 - 7 )*8 ) ),
30302 binop( Iop_64HLtoV128
,
30304 mkU64( 0xFFULL
) ) ),
30306 binop( Iop_AndV128
,
30308 binop( Iop_ShlV128
,
30309 binop( Iop_64HLtoV128
,
30311 mkU64( 0xFFULL
) ),
30312 mkexpr( shift
) ) ),
30313 mkexpr( vD
) ) ) );
30317 case 0x34D: // vinserth (Vector insert Halfword)
30319 UChar uim
= IFIELD( theInstr
, 16, 4 );
30320 IRTemp shift
= newTemp( Ity_I8
);
30321 IRTemp vD
= newTemp( Ity_V128
);
30323 DIP("vinserth v%d,v%d,%d\n", vD_addr
, vB_addr
, uim
);
30325 assign( vD
, getVReg( vD_addr
) );
30327 assign( shift
, unop( Iop_32to8
,
30330 mkU32( 15 - ( uim
+ 1 ) ) ) ) );
30334 binop( Iop_ShlV128
,
30335 binop( Iop_AndV128
,
30336 binop( Iop_ShrV128
,
30338 mkU8( (7 - 3)*16 ) ),
30339 binop( Iop_64HLtoV128
,
30341 mkU64( 0xFFFFULL
) ) ),
30343 binop( Iop_AndV128
,
30345 binop( Iop_ShlV128
,
30346 binop( Iop_64HLtoV128
,
30348 mkU64( 0xFFFFULL
) ),
30349 mkexpr( shift
) ) ),
30350 mkexpr( vD
) ) ) );
30354 case 0x38D: // vinsertw (Vector insert Word)
30356 UChar uim
= IFIELD( theInstr
, 16, 4 );
30357 IRTemp shift
= newTemp( Ity_I8
);
30358 IRTemp vD
= newTemp( Ity_V128
);
30360 DIP("vinsertw v%d,v%d,%d\n", vD_addr
, vB_addr
, uim
);
30362 assign( vD
, getVReg( vD_addr
) );
30364 assign( shift
, unop( Iop_32to8
,
30367 mkU32( 15 - ( uim
+ 3 ) ) ) ) );
30371 binop( Iop_ShlV128
,
30372 binop( Iop_AndV128
,
30373 binop( Iop_ShrV128
,
30375 mkU8( (3 - 1) * 32 ) ),
30376 binop( Iop_64HLtoV128
,
30378 mkU64( 0xFFFFFFFFULL
) ) ),
30380 binop( Iop_AndV128
,
30382 binop( Iop_ShlV128
,
30383 binop( Iop_64HLtoV128
,
30385 mkU64( 0xFFFFFFFFULL
) ),
30386 mkexpr( shift
) ) ),
30387 mkexpr( vD
) ) ) );
30391 case 0x3CD: // vinsertd (Vector insert Doubleword)
30393 UChar uim
= IFIELD( theInstr
, 16, 4 );
30394 IRTemp shift
= newTemp( Ity_I8
);
30395 IRTemp vD
= newTemp( Ity_V128
);
30397 DIP("vinsertd v%d,v%d,%d\n", vD_addr
, vB_addr
, uim
);
30399 assign( vD
, getVReg( vD_addr
) );
30401 assign( shift
, unop( Iop_32to8
,
30404 mkU32( 15 - ( uim
+ 7 ) ) ) ) );
30408 binop( Iop_ShlV128
,
30409 binop( Iop_AndV128
,
30410 binop( Iop_ShrV128
,
30412 mkU8( ( 1 - 0 ) * 64 ) ),
30413 binop( Iop_64HLtoV128
,
30415 mkU64( 0xFFFFFFFFFFFFFFFFULL
) ) ),
30417 binop( Iop_AndV128
,
30419 binop( Iop_ShlV128
,
30420 binop( Iop_64HLtoV128
,
30422 mkU64( 0xFFFFFFFFFFFFFFFFULL
) ),
30423 mkexpr( shift
) ) ),
30424 mkexpr( vD
) ) ) );
30429 case 0x20C: { // vspltb (Splat Byte, AV p245)
30430 /* vD = Dup8x16( vB[UIMM_5] ) */
30431 UChar sh_uimm
= (15 - (UIMM_5
& 15)) * 8;
30432 DIP("vspltb v%d,v%d,%d\n", vD_addr
, vB_addr
, UIMM_5
);
30433 putVReg( vD_addr
, unop(Iop_Dup8x16
,
30434 unop(Iop_32to8
, unop(Iop_V128to32
,
30435 binop(Iop_ShrV128
, mkexpr(vB
), mkU8(sh_uimm
))))) );
30438 case 0x24C: { // vsplth (Splat Half Word, AV p246)
30439 UChar sh_uimm
= (7 - (UIMM_5
& 7)) * 16;
30440 DIP("vsplth v%d,v%d,%d\n", vD_addr
, vB_addr
, UIMM_5
);
30441 putVReg( vD_addr
, unop(Iop_Dup16x8
,
30442 unop(Iop_32to16
, unop(Iop_V128to32
,
30443 binop(Iop_ShrV128
, mkexpr(vB
), mkU8(sh_uimm
))))) );
30446 case 0x28C: { // vspltw (Splat Word, AV p250)
30447 /* vD = Dup32x4( vB[UIMM_5] ) */
30448 UChar sh_uimm
= (3 - (UIMM_5
& 3)) * 32;
30449 DIP("vspltw v%d,v%d,%d\n", vD_addr
, vB_addr
, UIMM_5
);
30450 putVReg( vD_addr
, unop(Iop_Dup32x4
,
30452 binop(Iop_ShrV128
, mkexpr(vB
), mkU8(sh_uimm
)))) );
30455 case 0x30C: // vspltisb (Splat Immediate Signed B, AV p247)
30456 DIP("vspltisb v%d,%d\n", vD_addr
, (Char
)SIMM_8
);
30457 putVReg( vD_addr
, unop(Iop_Dup8x16
, mkU8(SIMM_8
)) );
30460 case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248)
30461 DIP("vspltish v%d,%d\n", vD_addr
, (Char
)SIMM_8
);
30463 unop(Iop_Dup16x8
, mkU16(extend_s_8to32(SIMM_8
))) );
30466 case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249)
30467 DIP("vspltisw v%d,%d\n", vD_addr
, (Char
)SIMM_8
);
30469 unop(Iop_Dup32x4
, mkU32(extend_s_8to32(SIMM_8
))) );
30472 case 0x68C: // vmrgow (Merge Odd Word)
30473 DIP("vmrgow v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
30480 binop(Iop_CatOddLanes32x4
, mkexpr(vA
), mkexpr(vB
) ) );
30483 case 0x78C: // vmrgew (Merge Even Word)
30484 DIP("vmrgew v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
30491 binop(Iop_CatEvenLanes32x4
, mkexpr(vA
), mkexpr(vB
) ) );
30495 vex_printf("dis_av_permute(ppc)(opc2)\n");
30502 Vector Integer Absolute Difference
30504 static Bool
dis_abs_diff ( UInt prefix
, UInt theInstr
)
30507 UChar opc1
= ifieldOPC( theInstr
);
30508 UChar vT_addr
= ifieldRegDS( theInstr
);
30509 UChar vA_addr
= ifieldRegA( theInstr
);
30510 UChar vB_addr
= ifieldRegB( theInstr
);
30511 UInt opc2
= IFIELD( theInstr
, 0, 11 );
30513 IRTemp vA
= newTemp( Ity_V128
);
30514 IRTemp vB
= newTemp( Ity_V128
);
30515 IRTemp vT
= newTemp( Ity_V128
);
30517 IRTemp vAminusB
= newTemp( Ity_V128
);
30518 IRTemp vBminusA
= newTemp( Ity_V128
);
30519 IRTemp vMask
= newTemp( Ity_V128
);
30521 /* There is no prefixed version of these instructions. */
30524 assign( vA
, getVReg( vA_addr
) );
30525 assign( vB
, getVReg( vB_addr
) );
30527 if ( opc1
!= 0x4 ) {
30528 vex_printf("dis_abs_diff(ppc)(instr)\n");
30533 case 0x403: // vabsdub Vector absolute difference Unsigned Byte
30535 DIP("vabsdub v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
30537 /* Determine which of the corresponding bytes is larger,
30538 * create mask with 1's in byte positions where vA[i] > vB[i]
30540 assign( vMask
, binop( Iop_CmpGT8Ux16
, mkexpr( vA
), mkexpr( vB
) ) );
30543 binop( Iop_AndV128
,
30544 binop( Iop_Sub8x16
, mkexpr( vA
), mkexpr( vB
) ),
30545 mkexpr( vMask
) ) );
30548 binop( Iop_AndV128
,
30549 binop( Iop_Sub8x16
, mkexpr( vB
), mkexpr( vA
) ),
30550 unop ( Iop_NotV128
, mkexpr( vMask
) ) ) );
30552 assign( vT
, binop( Iop_OrV128
,
30553 mkexpr( vAminusB
),
30554 mkexpr( vBminusA
) ) );
30558 case 0x443: // vabsduh Vector absolute difference Unsigned Halfword
30560 DIP("vabsduh v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
30562 /* Determine which of the corresponding halfwords is larger,
30563 * create mask with 1's in halfword positions where vA[i] > vB[i]
30565 assign( vMask
, binop( Iop_CmpGT16Ux8
, mkexpr( vA
), mkexpr( vB
) ) );
30568 binop( Iop_AndV128
,
30569 binop( Iop_Sub16x8
, mkexpr( vA
), mkexpr( vB
) ),
30570 mkexpr( vMask
) ) );
30573 binop( Iop_AndV128
,
30574 binop( Iop_Sub16x8
, mkexpr( vB
), mkexpr( vA
) ),
30575 unop ( Iop_NotV128
, mkexpr( vMask
) ) ) );
30577 assign( vT
, binop( Iop_OrV128
,
30578 mkexpr( vAminusB
),
30579 mkexpr( vBminusA
) ) );
30583 case 0x483: // vabsduw Vector absolute difference Unsigned Word
30585 DIP("vabsduw v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
30587 /* Determine which of the corresponding words is larger,
30588 * create mask with 1's in word positions where vA[i] > vB[i]
30590 assign( vMask
, binop( Iop_CmpGT32Ux4
, mkexpr( vA
), mkexpr( vB
) ) );
30593 binop( Iop_AndV128
,
30594 binop( Iop_Sub32x4
, mkexpr( vA
), mkexpr( vB
) ),
30595 mkexpr( vMask
) ) );
30598 binop( Iop_AndV128
,
30599 binop( Iop_Sub32x4
, mkexpr( vB
), mkexpr( vA
) ),
30600 unop ( Iop_NotV128
, mkexpr( vMask
) ) ) );
30602 assign( vT
, binop( Iop_OrV128
,
30603 mkexpr( vAminusB
),
30604 mkexpr( vBminusA
) ) );
30612 putVReg( vT_addr
, mkexpr( vT
) );
30618 AltiVec 128 bit integer multiply by 10 Instructions
30620 static Bool
dis_av_mult10 ( UInt prefix
, UInt theInstr
)
30623 UChar opc1
= ifieldOPC(theInstr
);
30624 UChar vT_addr
= ifieldRegDS(theInstr
);
30625 UChar vA_addr
= ifieldRegA(theInstr
);
30626 UChar vB_addr
= ifieldRegB(theInstr
);
30627 UInt opc2
= IFIELD( theInstr
, 0, 11 );
30629 IRTemp vA
= newTemp(Ity_V128
);
30631 /* There is no prefixed version of these instructions. */
30634 assign( vA
, getVReg(vA_addr
));
30637 vex_printf("dis_av_mult10(ppc)(instr)\n");
30641 case 0x001: { // vmul10cuq (Vector Multiply-by-10 and write carry
30642 DIP("vmul10cuq v%d,v%d\n", vT_addr
, vA_addr
);
30644 unop( Iop_MulI128by10Carry
, mkexpr( vA
) ) );
30647 case 0x041: { // vmul10uq (Vector Multiply-by-10 Extended and write carry
30648 // Unsigned Quadword VX form)
30649 IRTemp vB
= newTemp(Ity_V128
);
30650 assign( vB
, getVReg(vB_addr
));
30651 DIP("vmul10ecuq v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
30653 binop( Iop_MulI128by10ECarry
, mkexpr( vA
), mkexpr( vB
) ) );
30656 case 0x201: { // vmul10uq (Vector Multiply-by-10 Unsigned Quadword VX form)
30657 DIP("vmul10uq v%d,v%d\n", vT_addr
, vA_addr
);
30659 unop( Iop_MulI128by10
, mkexpr( vA
) ) );
30662 case 0x241: { // vmul10uq (Vector Multiply-by-10 Extended
30663 // Unsigned Quadword VX form)
30664 IRTemp vB
= newTemp(Ity_V128
);
30665 assign( vB
, getVReg(vB_addr
));
30666 DIP("vmul10euq v%d,v%d,v%d\n", vT_addr
, vA_addr
, vB_addr
);
30668 binop( Iop_MulI128by10E
, mkexpr( vA
), mkexpr( vB
) ) );
30672 vex_printf("dis_av_mult10(ppc)(opc2)\n");
30679 AltiVec Pack/Unpack Instructions
30681 static Bool
dis_av_pack ( UInt prefix
, UInt theInstr
)
30684 UChar opc1
= ifieldOPC(theInstr
);
30685 UChar vD_addr
= ifieldRegDS(theInstr
);
30686 UChar vA_addr
= ifieldRegA(theInstr
);
30687 UChar vB_addr
= ifieldRegB(theInstr
);
30688 UInt opc2
= IFIELD( theInstr
, 0, 11 );
30690 IRTemp signs
= IRTemp_INVALID
;
30691 IRTemp zeros
= IRTemp_INVALID
;
30692 IRTemp vA
= newTemp(Ity_V128
);
30693 IRTemp vB
= newTemp(Ity_V128
);
30695 /* There is no prefixed version of these instructions. */
30698 assign( vA
, getVReg(vA_addr
));
30699 assign( vB
, getVReg(vB_addr
));
30702 vex_printf("dis_av_pack(ppc)(instr)\n");
30707 case 0x00E: // vpkuhum (Pack Unsigned HW Unsigned Modulo, AV p224)
30708 DIP("vpkuhum v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
30710 binop(Iop_NarrowBin16to8x16
, mkexpr(vA
), mkexpr(vB
)) );
30713 case 0x04E: // vpkuwum (Pack Unsigned W Unsigned Modulo, AV p226)
30714 DIP("vpkuwum v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
30716 binop(Iop_NarrowBin32to16x8
, mkexpr(vA
), mkexpr(vB
)) );
30719 case 0x08E: // vpkuhus (Pack Unsigned HW Unsigned Saturate, AV p225)
30720 DIP("vpkuhus v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
30722 binop(Iop_QNarrowBin16Uto8Ux16
, mkexpr(vA
), mkexpr(vB
)) );
30723 // TODO: set VSCR[SAT]
30726 case 0x0CE: // vpkuwus (Pack Unsigned W Unsigned Saturate, AV p227)
30727 DIP("vpkuwus v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
30729 binop(Iop_QNarrowBin32Uto16Ux8
, mkexpr(vA
), mkexpr(vB
)) );
30730 // TODO: set VSCR[SAT]
30733 case 0x10E: { // vpkshus (Pack Signed HW Unsigned Saturate, AV p221)
30734 // This insn does a signed->unsigned saturating conversion.
30735 // Conversion done here, then uses unsigned->unsigned vpk insn:
30736 // => UnsignedSaturatingNarrow( x & ~ (x >>s 15) )
30737 IRTemp vA_tmp
= newTemp(Ity_V128
);
30738 IRTemp vB_tmp
= newTemp(Ity_V128
);
30739 DIP("vpkshus v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
30740 assign( vA_tmp
, binop(Iop_AndV128
, mkexpr(vA
),
30742 binop(Iop_SarN16x8
,
30743 mkexpr(vA
), mkU8(15)))) );
30744 assign( vB_tmp
, binop(Iop_AndV128
, mkexpr(vB
),
30746 binop(Iop_SarN16x8
,
30747 mkexpr(vB
), mkU8(15)))) );
30748 putVReg( vD_addr
, binop(Iop_QNarrowBin16Uto8Ux16
,
30749 mkexpr(vA_tmp
), mkexpr(vB_tmp
)) );
30750 // TODO: set VSCR[SAT]
30753 case 0x14E: { // vpkswus (Pack Signed W Unsigned Saturate, AV p223)
30754 // This insn does a signed->unsigned saturating conversion.
30755 // Conversion done here, then uses unsigned->unsigned vpk insn:
30756 // => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
30757 IRTemp vA_tmp
= newTemp(Ity_V128
);
30758 IRTemp vB_tmp
= newTemp(Ity_V128
);
30759 DIP("vpkswus v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
30760 assign( vA_tmp
, binop(Iop_AndV128
, mkexpr(vA
),
30762 binop(Iop_SarN32x4
,
30763 mkexpr(vA
), mkU8(31)))) );
30764 assign( vB_tmp
, binop(Iop_AndV128
, mkexpr(vB
),
30766 binop(Iop_SarN32x4
,
30767 mkexpr(vB
), mkU8(31)))) );
30768 putVReg( vD_addr
, binop(Iop_QNarrowBin32Uto16Ux8
,
30769 mkexpr(vA_tmp
), mkexpr(vB_tmp
)) );
30770 // TODO: set VSCR[SAT]
30773 case 0x18E: // vpkshss (Pack Signed HW Signed Saturate, AV p220)
30774 DIP("vpkshss v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
30776 binop(Iop_QNarrowBin16Sto8Sx16
, mkexpr(vA
), mkexpr(vB
)) );
30777 // TODO: set VSCR[SAT]
30780 case 0x1CE: // vpkswss (Pack Signed W Signed Saturate, AV p222)
30781 DIP("vpkswss v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
30783 binop(Iop_QNarrowBin32Sto16Sx8
, mkexpr(vA
), mkexpr(vB
)) );
30784 // TODO: set VSCR[SAT]
30787 case 0x30E: { // vpkpx (Pack Pixel, AV p219)
30788 /* CAB: Worth a new primop? */
30789 /* Using shifts to compact pixel elements, then packing them */
30790 IRTemp a1
= newTemp(Ity_V128
);
30791 IRTemp a2
= newTemp(Ity_V128
);
30792 IRTemp a3
= newTemp(Ity_V128
);
30793 IRTemp a_tmp
= newTemp(Ity_V128
);
30794 IRTemp b1
= newTemp(Ity_V128
);
30795 IRTemp b2
= newTemp(Ity_V128
);
30796 IRTemp b3
= newTemp(Ity_V128
);
30797 IRTemp b_tmp
= newTemp(Ity_V128
);
30798 DIP("vpkpx v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
30799 assign( a1
, binop(Iop_ShlN16x8
,
30800 binop(Iop_ShrN32x4
, mkexpr(vA
), mkU8(19)),
30802 assign( a2
, binop(Iop_ShlN16x8
,
30803 binop(Iop_ShrN16x8
, mkexpr(vA
), mkU8(11)),
30805 assign( a3
, binop(Iop_ShrN16x8
,
30806 binop(Iop_ShlN16x8
, mkexpr(vA
), mkU8(8)),
30808 assign( a_tmp
, binop(Iop_OrV128
, mkexpr(a1
),
30809 binop(Iop_OrV128
, mkexpr(a2
), mkexpr(a3
))) );
30811 assign( b1
, binop(Iop_ShlN16x8
,
30812 binop(Iop_ShrN32x4
, mkexpr(vB
), mkU8(19)),
30814 assign( b2
, binop(Iop_ShlN16x8
,
30815 binop(Iop_ShrN16x8
, mkexpr(vB
), mkU8(11)),
30817 assign( b3
, binop(Iop_ShrN16x8
,
30818 binop(Iop_ShlN16x8
, mkexpr(vB
), mkU8(8)),
30820 assign( b_tmp
, binop(Iop_OrV128
, mkexpr(b1
),
30821 binop(Iop_OrV128
, mkexpr(b2
), mkexpr(b3
))) );
30823 putVReg( vD_addr
, binop(Iop_NarrowBin32to16x8
,
30824 mkexpr(a_tmp
), mkexpr(b_tmp
)) );
30828 case 0x44E: // vpkudum (Pack Unsigned Double Word Unsigned Modulo)
30829 DIP("vpkudum v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
30831 binop(Iop_NarrowBin64to32x4
, mkexpr(vA
), mkexpr(vB
)) );
30834 case 0x4CE: // vpkudus (Pack Unsigned Double Word Unsigned Saturate)
30835 DIP("vpkudus v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
30837 binop(Iop_QNarrowBin64Uto32Ux4
, mkexpr(vA
), mkexpr(vB
)) );
30838 // TODO: set VSCR[SAT]
30841 case 0x54E: { // vpksdus (Pack Signed Double Word Unsigned Saturate)
30842 // This insn does a doubled signed->double unsigned saturating conversion
30843 // Conversion done here, then uses unsigned->unsigned vpk insn:
30844 // => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
30845 // This is similar to the technique used for vpkswus, except done
30846 // with double word integers versus word integers.
30847 IRTemp vA_tmp
= newTemp(Ity_V128
);
30848 IRTemp vB_tmp
= newTemp(Ity_V128
);
30849 DIP("vpksdus v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
30850 assign( vA_tmp
, binop(Iop_AndV128
, mkexpr(vA
),
30852 binop(Iop_SarN64x2
,
30853 mkexpr(vA
), mkU8(63)))) );
30854 assign( vB_tmp
, binop(Iop_AndV128
, mkexpr(vB
),
30856 binop(Iop_SarN64x2
,
30857 mkexpr(vB
), mkU8(63)))) );
30858 putVReg( vD_addr
, binop(Iop_QNarrowBin64Uto32Ux4
,
30859 mkexpr(vA_tmp
), mkexpr(vB_tmp
)) );
30860 // TODO: set VSCR[SAT]
30864 case 0x5CE: // vpksdss (Pack Signed double word Signed Saturate)
30865 DIP("vpksdss v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
30867 binop(Iop_QNarrowBin64Sto32Sx4
, mkexpr(vA
), mkexpr(vB
)) );
30868 // TODO: set VSCR[SAT]
30871 break; // Fall through...
30875 if (vA_addr
!= 0) {
30876 vex_printf("dis_av_pack(ppc)(vA_addr)\n");
30880 signs
= newTemp(Ity_V128
);
30881 zeros
= newTemp(Ity_V128
);
30882 assign( zeros
, unop(Iop_Dup32x4
, mkU32(0)) );
30886 case 0x20E: { // vupkhsb (Unpack High Signed B, AV p277)
30887 DIP("vupkhsb v%d,v%d\n", vD_addr
, vB_addr
);
30888 assign( signs
, binop(Iop_CmpGT8Sx16
, mkexpr(zeros
), mkexpr(vB
)) );
30890 binop(Iop_InterleaveHI8x16
, mkexpr(signs
), mkexpr(vB
)) );
30893 case 0x24E: { // vupkhsh (Unpack High Signed HW, AV p278)
30894 DIP("vupkhsh v%d,v%d\n", vD_addr
, vB_addr
);
30895 assign( signs
, binop(Iop_CmpGT16Sx8
, mkexpr(zeros
), mkexpr(vB
)) );
30897 binop(Iop_InterleaveHI16x8
, mkexpr(signs
), mkexpr(vB
)) );
30900 case 0x28E: { // vupklsb (Unpack Low Signed B, AV p280)
30901 DIP("vupklsb v%d,v%d\n", vD_addr
, vB_addr
);
30902 assign( signs
, binop(Iop_CmpGT8Sx16
, mkexpr(zeros
), mkexpr(vB
)) );
30904 binop(Iop_InterleaveLO8x16
, mkexpr(signs
), mkexpr(vB
)) );
30907 case 0x2CE: { // vupklsh (Unpack Low Signed HW, AV p281)
30908 DIP("vupklsh v%d,v%d\n", vD_addr
, vB_addr
);
30909 assign( signs
, binop(Iop_CmpGT16Sx8
, mkexpr(zeros
), mkexpr(vB
)) );
30911 binop(Iop_InterleaveLO16x8
, mkexpr(signs
), mkexpr(vB
)) );
30914 case 0x34E: { // vupkhpx (Unpack High Pixel16, AV p276)
30915 /* CAB: Worth a new primop? */
30916 /* Using shifts to isolate pixel elements, then expanding them */
30917 IRTemp z0
= newTemp(Ity_V128
);
30918 IRTemp z1
= newTemp(Ity_V128
);
30919 IRTemp z01
= newTemp(Ity_V128
);
30920 IRTemp z2
= newTemp(Ity_V128
);
30921 IRTemp z3
= newTemp(Ity_V128
);
30922 IRTemp z23
= newTemp(Ity_V128
);
30923 DIP("vupkhpx v%d,v%d\n", vD_addr
, vB_addr
);
30924 assign( z0
, binop(Iop_ShlN16x8
,
30925 binop(Iop_SarN16x8
, mkexpr(vB
), mkU8(15)),
30927 assign( z1
, binop(Iop_ShrN16x8
,
30928 binop(Iop_ShlN16x8
, mkexpr(vB
), mkU8(1)),
30930 assign( z01
, binop(Iop_InterleaveHI16x8
, mkexpr(zeros
),
30931 binop(Iop_OrV128
, mkexpr(z0
), mkexpr(z1
))) );
30932 assign( z2
, binop(Iop_ShrN16x8
,
30933 binop(Iop_ShlN16x8
,
30934 binop(Iop_ShrN16x8
, mkexpr(vB
), mkU8(5)),
30937 assign( z3
, binop(Iop_ShrN16x8
,
30938 binop(Iop_ShlN16x8
, mkexpr(vB
), mkU8(11)),
30940 assign( z23
, binop(Iop_InterleaveHI16x8
, mkexpr(zeros
),
30941 binop(Iop_OrV128
, mkexpr(z2
), mkexpr(z3
))) );
30944 binop(Iop_ShlN32x4
, mkexpr(z01
), mkU8(16)),
30948 case 0x3CE: { // vupklpx (Unpack Low Pixel16, AV p279)
30949 /* identical to vupkhpx, except interleaving LO */
30950 IRTemp z0
= newTemp(Ity_V128
);
30951 IRTemp z1
= newTemp(Ity_V128
);
30952 IRTemp z01
= newTemp(Ity_V128
);
30953 IRTemp z2
= newTemp(Ity_V128
);
30954 IRTemp z3
= newTemp(Ity_V128
);
30955 IRTemp z23
= newTemp(Ity_V128
);
30956 DIP("vupklpx v%d,v%d\n", vD_addr
, vB_addr
);
30957 assign( z0
, binop(Iop_ShlN16x8
,
30958 binop(Iop_SarN16x8
, mkexpr(vB
), mkU8(15)),
30960 assign( z1
, binop(Iop_ShrN16x8
,
30961 binop(Iop_ShlN16x8
, mkexpr(vB
), mkU8(1)),
30963 assign( z01
, binop(Iop_InterleaveLO16x8
, mkexpr(zeros
),
30964 binop(Iop_OrV128
, mkexpr(z0
), mkexpr(z1
))) );
30965 assign( z2
, binop(Iop_ShrN16x8
,
30966 binop(Iop_ShlN16x8
,
30967 binop(Iop_ShrN16x8
, mkexpr(vB
), mkU8(5)),
30970 assign( z3
, binop(Iop_ShrN16x8
,
30971 binop(Iop_ShlN16x8
, mkexpr(vB
), mkU8(11)),
30973 assign( z23
, binop(Iop_InterleaveLO16x8
, mkexpr(zeros
),
30974 binop(Iop_OrV128
, mkexpr(z2
), mkexpr(z3
))) );
30977 binop(Iop_ShlN32x4
, mkexpr(z01
), mkU8(16)),
30981 case 0x64E: { // vupkhsw (Unpack High Signed Word)
30982 DIP("vupkhsw v%d,v%d\n", vD_addr
, vB_addr
);
30983 assign( signs
, binop(Iop_CmpGT32Sx4
, mkexpr(zeros
), mkexpr(vB
)) );
30985 binop(Iop_InterleaveHI32x4
, mkexpr(signs
), mkexpr(vB
)) );
30988 case 0x6CE: { // vupklsw (Unpack Low Signed Word)
30989 DIP("vupklsw v%d,v%d\n", vD_addr
, vB_addr
);
30990 assign( signs
, binop(Iop_CmpGT32Sx4
, mkexpr(zeros
), mkexpr(vB
)) );
30992 binop(Iop_InterleaveLO32x4
, mkexpr(signs
), mkexpr(vB
)) );
30996 vex_printf("dis_av_pack(ppc)(opc2)\n");
31003 AltiVec Cipher Instructions
31005 static Bool
dis_av_cipher ( UInt prefix
, UInt theInstr
)
31008 UChar opc1
= ifieldOPC(theInstr
);
31009 UChar vD_addr
= ifieldRegDS(theInstr
);
31010 UChar vA_addr
= ifieldRegA(theInstr
);
31011 UChar vB_addr
= ifieldRegB(theInstr
);
31012 UInt opc2
= IFIELD( theInstr
, 0, 11 );
31014 IRTemp vA
= newTemp(Ity_V128
);
31015 IRTemp vB
= newTemp(Ity_V128
);
31017 /* There is no prefixed version of these instructions. */
31020 assign( vA
, getVReg(vA_addr
));
31021 assign( vB
, getVReg(vB_addr
));
31024 vex_printf("dis_av_cipher(ppc)(instr)\n");
31028 case 0x508: // vcipher (Vector Inverser Cipher)
31029 DIP("vcipher v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
31031 binop(Iop_CipherV128
, mkexpr(vA
), mkexpr(vB
)) );
31034 case 0x509: // vcipherlast (Vector Inverser Cipher Last)
31035 DIP("vcipherlast v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
31037 binop(Iop_CipherLV128
, mkexpr(vA
), mkexpr(vB
)) );
31040 case 0x548: // vncipher (Vector Inverser Cipher)
31041 DIP("vncipher v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
31043 binop(Iop_NCipherV128
, mkexpr(vA
), mkexpr(vB
)) );
31046 case 0x549: // vncipherlast (Vector Inverser Cipher Last)
31047 DIP("vncipherlast v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
31049 binop(Iop_NCipherLV128
, mkexpr(vA
), mkexpr(vB
)) );
31052 case 0x5C8: /* vsbox (Vector SubBytes, this does the cipher
31053 * subBytes transform)
31055 DIP("vsbox v%d,v%d\n", vD_addr
, vA_addr
);
31057 unop(Iop_CipherSV128
, mkexpr(vA
) ) );
31061 vex_printf("dis_av_cipher(ppc)(opc2)\n");
31068 AltiVec Secure Hash Instructions
31070 static Bool
dis_av_hash ( UInt prefix
, UInt theInstr
)
31073 UChar opc1
= ifieldOPC(theInstr
);
31074 UChar vRT_addr
= ifieldRegDS(theInstr
);
31075 UChar vRA_addr
= ifieldRegA(theInstr
);
31076 UChar s_field
= IFIELD( theInstr
, 11, 5 ); // st and six field
31077 UChar st
= IFIELD( theInstr
, 15, 1 ); // st
31078 UChar six
= IFIELD( theInstr
, 11, 4 ); // six field
31079 UInt opc2
= IFIELD( theInstr
, 0, 11 );
31081 IRTemp vA
= newTemp(Ity_V128
);
31082 IRTemp dst
= newTemp(Ity_V128
);
31084 /* There is no prefixed version of these instructions. */
31087 assign( vA
, getVReg(vRA_addr
));
31090 vex_printf("dis_av_hash(ppc)(instr)\n");
31095 case 0x682: // vshasigmaw
31096 DIP("vshasigmaw v%d,v%d,%u,%u\n", vRT_addr
, vRA_addr
, st
, six
);
31097 assign( dst
, binop( Iop_SHA256
, mkexpr( vA
), mkU8( s_field
) ) );
31098 putVReg( vRT_addr
, mkexpr(dst
));
31101 case 0x6C2: // vshasigmad,
31102 DIP("vshasigmad v%d,v%d,%u,%u\n", vRT_addr
, vRA_addr
, st
, six
);
31103 putVReg( vRT_addr
, binop( Iop_SHA512
, mkexpr( vA
), mkU8( s_field
) ) );
31107 vex_printf("dis_av_hash(ppc)(opc2)\n");
31114 * This function is used by the Vector add/subtract [extended] modulo/carry
31116 * - For the non-extended add instructions, the cin arg is set to zero.
31117 * - For the extended add instructions, cin is the integer value of
31119 * - For the non-extended subtract instructions, src1 is added to the one's
31120 * complement of src2 + 1. We re-use the cin argument to hold the '1'
31121 * value for this operation.
31122 * - For the extended subtract instructions, cin is the integer value of src3.bit[127].
31124 static IRTemp
_get_quad_modulo_or_carry(IRExpr
* vecA
, IRExpr
* vecB
,
31125 IRExpr
* cin
, Bool modulo
)
31127 IRTemp _vecA_32
= IRTemp_INVALID
;
31128 IRTemp _vecB_32
= IRTemp_INVALID
;
31129 IRTemp res_32
= IRTemp_INVALID
;
31130 IRTemp res_64
= IRTemp_INVALID
;
31131 IRTemp result
= IRTemp_INVALID
;
31132 IRTemp tmp_result
= IRTemp_INVALID
;
31133 IRTemp carry
= IRTemp_INVALID
;
31135 IRExpr
* _vecA_low64
= unop( Iop_V128to64
, vecA
);
31136 IRExpr
* _vecB_low64
= unop( Iop_V128to64
, vecB
);
31137 IRExpr
* _vecA_high64
= unop( Iop_V128HIto64
, vecA
);
31138 IRExpr
* _vecB_high64
= unop( Iop_V128HIto64
, vecB
);
31140 carry
= newTemp(Ity_I32
);
31141 assign( carry
, cin
);
31143 for (i
= 0; i
< 4; i
++) {
31144 _vecA_32
= newTemp(Ity_I32
);
31145 _vecB_32
= newTemp(Ity_I32
);
31146 res_32
= newTemp(Ity_I32
);
31147 res_64
= newTemp(Ity_I64
);
31151 assign(_vecA_32
, unop( Iop_64to32
, _vecA_low64
) );
31152 assign(_vecB_32
, unop( Iop_64to32
, _vecB_low64
) );
31155 assign(_vecA_32
, unop( Iop_64HIto32
, _vecA_low64
) );
31156 assign(_vecB_32
, unop( Iop_64HIto32
, _vecB_low64
) );
31159 assign(_vecA_32
, unop( Iop_64to32
, _vecA_high64
) );
31160 assign(_vecB_32
, unop( Iop_64to32
, _vecB_high64
) );
31163 assign(_vecA_32
, unop( Iop_64HIto32
, _vecA_high64
) );
31164 assign(_vecB_32
, unop( Iop_64HIto32
, _vecB_high64
) );
31168 assign( res_64
, binop( Iop_Add64
,
31170 binop( Iop_32HLto64
,
31172 mkexpr(_vecA_32
) ),
31173 binop( Iop_32HLto64
,
31175 mkexpr(_vecB_32
) ) ),
31176 binop( Iop_32HLto64
,
31178 mkexpr( carry
) ) ) );
31180 /* Calculate the carry to the next higher 32 bits. */
31181 carry
= newTemp(Ity_I32
);
31182 assign(carry
, unop( Iop_64HIto32
, mkexpr( res_64
) ) );
31184 /* result is the lower 32-bits */
31185 assign(res_32
, unop( Iop_64to32
, mkexpr( res_64
) ) );
31188 result
= newTemp(Ity_V128
);
31189 assign(result
, binop( Iop_OrV128
,
31190 (i
== 0) ? binop( Iop_64HLtoV128
,
31192 mkU64(0) ) : mkexpr(tmp_result
),
31193 binop( Iop_ShlV128
,
31194 binop( Iop_64HLtoV128
,
31196 binop( Iop_32HLto64
,
31198 mkexpr(res_32
) ) ),
31199 mkU8(i
* 32) ) ) );
31200 tmp_result
= newTemp(Ity_V128
);
31201 assign(tmp_result
, mkexpr(result
));
31210 static IRExpr
* copy_MSB_bit_fields ( IRExpr
*src
, UInt size
,
31211 const VexAbiInfo
* vbi
)
31213 IRTemp src_hi
= newTemp( Ity_I64
);
31214 IRTemp src_lo
= newTemp( Ity_I64
);
31215 IRTemp ones_hi
, ones_lo
;
31216 ULong extract_mask_hi
, extract_mask_lo
;
31219 ones_hi
= newTemp( Ity_I64
);
31220 ones_lo
= newTemp( Ity_I64
);
31222 /* Create 64-bit extract mask, with a 1 in the MSB for each vector element
31227 extract_mask_hi
= 0x8080808080808080ULL
;
31228 extract_mask_lo
= 0x8080808080808080ULL
;
31233 extract_mask_hi
= 0x8000800080008000ULL
;
31234 extract_mask_lo
= 0x8000800080008000ULL
;
31239 extract_mask_hi
= 0x8000000080000000ULL
;
31240 extract_mask_lo
= 0x8000000080000000ULL
;
31245 extract_mask_hi
= 0x8000000000000000ULL
;
31246 extract_mask_lo
= 0x8000000000000000ULL
;
31251 /* unsupported element size */
31255 assign( src_hi
, unop( Iop_V128HIto64
, src
) );
31256 assign( src_lo
, unop( Iop_V128to64
, src
) );
31258 assign( ones_hi
, extract_bits_under_mask ( vbi
, mkexpr( src_hi
),
31259 mkU64( extract_mask_hi
),
31261 assign( ones_lo
, extract_bits_under_mask ( vbi
, mkexpr( src_lo
),
31262 mkU64( extract_mask_lo
),
31265 /* Concatenate the extracted bits from ones_hi and ones_lo and
31266 store in GPR. Make sure the hi and low bits are left aligned per
31268 return binop( Iop_Or64
,
31271 mkU8( num_bits
) ),
31272 mkexpr( ones_lo
) );
31275 static Bool
dis_VSR_byte_mask ( UInt prefix
, UInt theInstr
,
31276 const VexAbiInfo
* vbi
)
31278 UChar RT_addr
= ifieldRegDS(theInstr
);
31279 UChar B_addr
= ifieldRegB(theInstr
);
31280 IRTemp src
= newTemp(Ity_I64
);
31282 UInt inst_select
= IFIELD( theInstr
, 16, 5);
31283 IRTemp vRT
= newTemp( Ity_V128
);
31285 ULong extract_mask
, shift_by
;
31288 /* The various instructions handled by this function use bits[11:15] to
31289 specify the instruction in addition to the opc1 (bits[0:5]) and opc2
31290 (bits21:31]). The exception is the mtvsrbmi which uses bits[11:15]
31291 for part of the immediate value. Assign mtvsrbmi a unique inst_select
31292 so it can be handled similarly to the other instructions. This helps
31293 simplify the code control flow. */
31294 if (IFIELD(theInstr
, 1, 5) == 0xA) //mtvsrbmi
31295 inst_select
= 0x9999;
31297 switch(inst_select
) {
31298 case 0x0: // vexpandbm
31299 DIP("vexpandbm v%u,r%u\n", RT_addr
, B_addr
);
31301 extract_mask
= 0x8080808080808080ULL
;
31302 shift_by
= 0x0707070707070707ULL
;
31304 /* Use extract mask to select the MSB from each byte field. Then
31305 use the arithmetic right shift to replicate the MSB into each
31306 bit of the element field. */
31308 binop( Iop_Sar8x16
,
31309 binop( Iop_AndV128
,
31311 binop( Iop_64HLtoV128
, mkU64( extract_mask
),
31312 mkU64( extract_mask
) ) ),
31313 binop( Iop_64HLtoV128
, mkU64( shift_by
),
31314 mkU64( shift_by
) ) ) );
31315 putVReg( RT_addr
, mkexpr( vRT
) );
31318 case 0x1: // vexpandhm
31319 DIP("vexpandhm v%u,r%u\n", RT_addr
, B_addr
);
31321 extract_mask
= 0x8000800080008000ULL
;
31322 shift_by
= 0x000F000F000F000FULL
;
31324 /* Use extract mask to select the MSB from each byte field. Then
31325 use the arithmetic right shift to replicate the MSB into each
31326 bit of the element field. */
31328 binop( Iop_Sar16x8
,
31329 binop( Iop_AndV128
,
31331 binop( Iop_64HLtoV128
, mkU64( extract_mask
),
31332 mkU64( extract_mask
) ) ),
31333 binop( Iop_64HLtoV128
, mkU64( shift_by
),
31334 mkU64( shift_by
) ) ) );
31335 putVReg( RT_addr
, mkexpr( vRT
) );
31338 case 0x2: // vexpandwm
31339 DIP("vexpandwm v%u,r%u\n", RT_addr
, B_addr
);
31341 extract_mask
= 0x8000000080000000ULL
;
31342 shift_by
= 0x0000001F0000001FULL
;
31344 /* Use extract mask to select the MSB from each byte field. Then
31345 use the arithmetic right shift to replicate the MSB into each
31346 bit of the element field. */
31348 binop( Iop_Sar32x4
,
31349 binop( Iop_AndV128
,
31351 binop( Iop_64HLtoV128
, mkU64( extract_mask
),
31352 mkU64( extract_mask
) ) ),
31353 binop( Iop_64HLtoV128
, mkU64( shift_by
),
31354 mkU64( shift_by
) ) ) );
31355 putVReg( RT_addr
, mkexpr( vRT
) );
31358 case 0x3: // vexpanddm
31359 DIP("vexpanddm v%u,r%u\n", RT_addr
, B_addr
);
31360 extract_mask
= 0x8000000080000000ULL
;
31361 shift_by
= 0x000003F000003FULL
;
31363 /* Use extract mask to select the MSB from each byte field. Then
31364 use the arithmetic right shift to replicate the MSB into each
31365 bit of the element field. */
31367 binop( Iop_Sar64x2
,
31368 binop( Iop_AndV128
,
31370 binop( Iop_64HLtoV128
, mkU64( extract_mask
),
31371 mkU64( extract_mask
) ) ),
31372 binop( Iop_64HLtoV128
, mkU64( shift_by
),
31373 mkU64( shift_by
) ) ) );
31374 putVReg( RT_addr
, mkexpr( vRT
) );
31377 case 0x4: // vexpandqm
31379 IRTemp ones
= newTemp( Ity_I64
);
31380 DIP("vexpandqm v%u,r%u\n", RT_addr
, B_addr
);
31382 assign( src
, binop( Iop_Shr64
,
31383 unop( Iop_V128HIto64
, getVReg( B_addr
) ),
31387 binop( Iop_CmpEQ64
,
31391 mkexpr( src
) ) ) ) );
31392 putVReg( RT_addr
, binop( Iop_64HLtoV128
,
31393 mkexpr( ones
), mkexpr( ones
) ) );
31397 case 0x8: // vextractbm
31398 DIP("vextractbm v%u,r%u\n", RT_addr
, B_addr
);
31400 putIReg( RT_addr
, copy_MSB_bit_fields( getVReg( B_addr
), size
, vbi
) );
31403 case 0x9: // vextracthm
31404 DIP("vextracthm v%u,r%u\n", RT_addr
, B_addr
);
31406 putIReg( RT_addr
, copy_MSB_bit_fields( getVReg( B_addr
), size
, vbi
) );
31409 case 0xA: // vextractwm
31410 DIP("vextractwm v%u,r%u\n", RT_addr
, B_addr
);
31412 putIReg( RT_addr
, copy_MSB_bit_fields( getVReg( B_addr
), size
, vbi
) );
31415 case 0xB: // vextractdm
31416 DIP("vextractdm v%u,r%u\n", RT_addr
, B_addr
);
31418 putIReg( RT_addr
, copy_MSB_bit_fields( getVReg( B_addr
), size
, vbi
) );
31421 case 0xC: // vextractqm
31422 DIP("vextractqm v%u,r%u\n", RT_addr
, B_addr
);
31423 putIReg( RT_addr
, binop( Iop_Shr64
,
31424 unop( Iop_V128HIto64
, getVReg( B_addr
) ),
31428 case 0x10: // mtvsrbm
31430 IRTemp src_upper
= newTemp(Ity_I32
);
31431 IRTemp src_upper2
= newTemp(Ity_I32
);
31432 IRTemp src_upper4
= newTemp(Ity_I32
);
31433 IRTemp src_lower
= newTemp(Ity_I32
);
31434 IRTemp src_lower2
= newTemp(Ity_I32
);
31435 IRTemp src_lower4
= newTemp(Ity_I32
);
31436 IRTemp tmp128
= newTemp(Ity_V128
);
31438 DIP("mtvsrbm v%u,r%u\n", RT_addr
, B_addr
);
31440 /* Copy the lower 8-bits of the 16 bit mask to lower 8 byte elements
31441 and copy the upper 8-bits of the 16 bit mask to the upper 8 byte
31443 assign( src_upper
, binop( Iop_Shr32
,
31444 binop( Iop_And32
, mkU32( 0xFF00 ),
31446 getIReg( B_addr
) ) ),
31448 assign( src_lower
, binop( Iop_And32
, mkU32( 0xFF ),
31450 getIReg( B_addr
) ) ) );
31452 assign( src_upper2
,
31453 binop( Iop_Or32
, mkexpr( src_upper
),
31454 binop( Iop_Shl32
, mkexpr( src_upper
), mkU8( 8 ) ) ) );
31456 assign( src_upper4
,
31457 binop( Iop_Or32
, mkexpr( src_upper2
),
31458 binop( Iop_Shl32
, mkexpr( src_upper2
),
31461 assign( src_lower2
,
31462 binop( Iop_Or32
, mkexpr( src_lower
),
31463 binop( Iop_Shl32
, mkexpr( src_lower
), mkU8( 8 ) ) ) );
31465 assign( src_lower4
,
31466 binop( Iop_Or32
, mkexpr( src_lower2
),
31467 binop( Iop_Shl32
, mkexpr( src_lower2
),
31470 /* Shift the bits in each element so the bit corresponding to the
31471 element position is in the MSB. */
31472 assign( tmp128
, binop( Iop_Shl8x16
,
31473 binop( Iop_64HLtoV128
,
31474 binop( Iop_32HLto64
,
31475 mkexpr( src_upper4
),
31476 mkexpr( src_upper4
) ),
31477 binop( Iop_32HLto64
,
31478 mkexpr( src_lower4
),
31479 mkexpr( src_lower4
) ) ),
31480 binop( Iop_64HLtoV128
,
31481 mkU64( 0x0001020304050607ULL
),
31482 mkU64( 0x0001020304050607ULL
) ) ) );
31483 /* Do an arithmetic shift to replicate MSB to all bit positions. */
31484 assign( vRT
, binop( Iop_Sar8x16
, mkexpr( tmp128
),
31485 binop( Iop_64HLtoV128
,
31486 mkU64( 0x0707070707070707ULL
),
31487 mkU64( 0x0707070707070707ULL
) ) ) );
31488 putVReg( RT_addr
, mkexpr( vRT
) );
31492 case 0x9999: // mtvsrbmi
31494 ULong immediate16
, immediate16_hi
, immediate16_lo
;
31495 ULong immediate64_hi
, immediate64_lo
;
31496 IRTemp tmp128
= newTemp(Ity_V128
);
31498 DIP("mtvsrbmi v%u,r%u\n", RT_addr
, B_addr
);
31500 /* Replicate the immediate fields b0|b1|b2 to all 16 vector
31502 immediate16
= (IFIELD(theInstr
, 0, 1) ) | //b2 bits[31]
31503 (IFIELD(theInstr
, 16, 5) << 1) | //b1 bits[11:15]
31504 (IFIELD(theInstr
, 6, 10) << 6 ); //b0 bits[16:25]
31506 immediate16_hi
= (immediate16
>> 8) & 0xFF;
31507 immediate16_lo
= immediate16
& 0xFF;
31509 immediate64_hi
= ((immediate16_hi
<< 32) | (immediate16_hi
<< 56) |
31510 (immediate16_hi
<< 48) | (immediate16_hi
<< 40) |
31511 (immediate16_hi
<< 32) | (immediate16_hi
<< 16) |
31512 (immediate16_hi
<< 8) | immediate16_hi
);
31514 immediate64_lo
= ((immediate16_lo
<< 32) | (immediate16_lo
<< 56) |
31515 (immediate16_lo
<< 48) | (immediate16_lo
<< 40) |
31516 (immediate16_lo
<< 32) | (immediate16_lo
<< 16) |
31517 (immediate16_lo
<< 8) | immediate16_lo
);
31519 /* Shift the bits in each element so the bit corresponding to the
31520 element position is in the MSB. */
31521 assign( tmp128
, binop( Iop_Shl8x16
,
31522 binop( Iop_64HLtoV128
,
31523 mkU64( immediate64_hi
),
31524 mkU64( immediate64_lo
) ),
31525 binop( Iop_64HLtoV128
,
31526 mkU64( 0x0001020304050607ULL
),
31527 mkU64( 0x0001020304050607ULL
) ) ) );
31528 /* Do an arithmetic shift to replicate MSB to all bit positions. */
31529 assign( vRT
, binop( Iop_Sar8x16
, mkexpr( tmp128
),
31530 binop( Iop_64HLtoV128
,
31531 mkU64( 0x0707070707070707ULL
),
31532 mkU64( 0x0707070707070707ULL
) ) ) );
31533 putVReg( RT_addr
, mkexpr( vRT
) );
31537 case 0x11: // mtvsrhm
31539 DIP("mtvsrhm v%u,r%u\n", RT_addr
, B_addr
);
31541 IRTemp src2
= newTemp(Ity_I32
);
31542 IRTemp tmp128
= newTemp(Ity_V128
);
31544 /* Copy the 16 bit mask to all eight of the 16-bit elements. */
31545 assign( src
, binop( Iop_And32
, mkU32( 0xFFFF ),
31547 getIReg( B_addr
) ) ) );
31550 binop( Iop_Or32
, mkexpr( src
),
31551 binop( Iop_Shl32
, mkexpr( src
), mkU8( 16 ) ) ) );
31553 /* Shift the bits in each element so the bit corresponding to the
31554 element position is in the MSB. */
31555 assign( tmp128
, binop( Iop_Shl16x8
,
31556 binop( Iop_64HLtoV128
,
31557 binop( Iop_32HLto64
,
31560 binop( Iop_32HLto64
,
31562 mkexpr( src2
) ) ),
31563 binop( Iop_64HLtoV128
,
31564 mkU64( 0x0000000100020003ULL
),
31565 mkU64( 0x0004000500060007ULL
) ) ) );
31566 /* Do an arithmetic shift to replicate MSB to all bit positions. */
31567 assign( vRT
, binop( Iop_Sar16x8
, mkexpr( tmp128
),
31568 binop( Iop_64HLtoV128
,
31569 mkU64( 0x000F000F000F000FULL
),
31570 mkU64( 0x000F000F000F000FULL
) ) ) );
31571 putVReg( RT_addr
, mkexpr( vRT
) );
31575 case 0x12: // mtvsrwm
31577 IRTemp tmp128
= newTemp(Ity_V128
);
31578 IRTemp src32
= newTemp(Ity_I32
);
31580 DIP("mtvsrwm v%u,r%u\n", RT_addr
, B_addr
);
31582 /* Copy the 32 bit mask to all four of the 32-bit elements. */
31583 assign( src32
, binop( Iop_Shl32
,
31584 unop ( Iop_64to32
, getIReg( B_addr
) ),
31587 /* Shift the bits in each element so the bit corresponding to the
31588 element position is in the MSB. */
31589 assign( tmp128
, binop( Iop_Shl32x4
,
31590 binop( Iop_64HLtoV128
,
31591 binop( Iop_32HLto64
,
31594 binop( Iop_32HLto64
,
31596 mkexpr( src32
) ) ),
31597 binop( Iop_64HLtoV128
,
31598 mkU64( 0x0000000000000001ULL
),
31599 mkU64( 0x0000000200000003ULL
) ) ) );
31601 /* Do an arithmetic shift to replicate MSB to all bit positions. */
31602 assign( vRT
, binop( Iop_Sar32x4
, mkexpr( tmp128
),
31603 binop( Iop_64HLtoV128
,
31604 mkU64( 0x0000001F0000001FULL
),
31605 mkU64( 0x0000001F0000001FULL
) ) ) );
31606 putVReg( RT_addr
, mkexpr( vRT
) );
31610 case 0x13: // mtvsrdm
31612 IRTemp tmp128
= newTemp(Ity_V128
);
31614 DIP("mtvsrdm v%u,r%u\n", RT_addr
, B_addr
);
31616 /* Copy the 64 bit mask to both of the 64-bit elements. */
31617 assign( src
, binop( Iop_Shl64
,
31621 /* Shift the bits in each element so the bit corresponding to the
31622 element position is in the MSB. */
31623 assign( tmp128
, binop( Iop_Shl64x2
,
31624 binop( Iop_64HLtoV128
,
31627 binop( Iop_64HLtoV128
,
31628 mkU64( 0x0000000000000000ULL
),
31629 mkU64( 0x0000000000000001ULL
) ) ) );
31631 /* Do an arithmetic shift to replicate MSB to all bit positions. */
31632 assign( vRT
, binop( Iop_Sar64x2
, mkexpr( tmp128
),
31633 binop( Iop_64HLtoV128
,
31634 mkU64( 0x000000000000003FULL
),
31635 mkU64( 0x000000000000003FULL
) ) ) );
31636 putVReg( RT_addr
, mkexpr( vRT
) );
31640 case 0x14: // mtvsrqm
31642 IRTemp ones
= newTemp( Ity_I64
);
31643 DIP("mtvsrqm v%u,r%u\n", RT_addr
, B_addr
);
31645 assign( src
, getIReg( B_addr
) );
31648 binop( Iop_CmpEQ64
,
31652 mkexpr( src
) ) ) ) );
31653 putVReg( RT_addr
, binop( Iop_64HLtoV128
,
31654 mkexpr( ones
), mkexpr( ones
) ) );
31658 case 0x18: // vcntmbb MP=0
31659 case 0x19: // vcntmbb MP=1
31661 UInt MP
= IFIELD(theInstr
, 16, 1); // bits[15] IBM numbering
31662 IRTemp bit_mask
= newTemp(Ity_I64
);
31663 IRTemp bit_cnt
= newTemp(Ity_I64
);
31665 DIP("vcntmbb r%u,v%u,%u\n", RT_addr
, B_addr
, MP
);
31668 assign( bit_mask
, copy_MSB_bit_fields( getVReg( B_addr
), size
,
31672 assign( bit_cnt
, binop( Iop_Shl64
,
31673 popcnt64( vbi
, mkexpr( bit_mask
) ),
31677 /* Need to complement the bit mask then count the ones. */
31684 mkexpr( bit_mask
) ) ) ),
31687 putIReg( RT_addr
, mkexpr( bit_cnt
) );
31691 case 0x1A: // vcntmbh MP=0
31692 case 0x1B: // vcntmbh MP=1
31694 UInt MP
= IFIELD(theInstr
, 16, 1); // bits[15] IBM numbering
31695 IRTemp bit_mask
= newTemp(Ity_I64
);
31696 IRTemp bit_cnt
= newTemp(Ity_I64
);
31698 DIP("vcntmbh r%u,v%u,%u\n", RT_addr
, B_addr
, MP
);
31701 assign( bit_mask
, copy_MSB_bit_fields( getVReg( B_addr
), size
,
31704 /* Result is in IBM bits [0:6] */
31708 popcnt64( vbi
, mkexpr( bit_mask
) ),
31712 /* Need to complement the bit mask then count the ones. */
31719 mkexpr( bit_mask
) ) ) ),
31722 putIReg( RT_addr
, mkexpr( bit_cnt
) );
31726 case 0x1C: // vcntmbw MP=0
31727 case 0x1D: // vcntmbw MP=1
31729 UInt MP
= IFIELD(theInstr
, 16, 1); // bits[15] IBM numbering
31730 IRTemp bit_mask
= newTemp(Ity_I64
);
31731 IRTemp bit_cnt
= newTemp(Ity_I64
);
31733 DIP("vcntmbw r%u,v%u,%u\n", RT_addr
, B_addr
, MP
);
31736 assign( bit_mask
, copy_MSB_bit_fields( getVReg( B_addr
), size
,
31742 popcnt64( vbi
, mkexpr( bit_mask
) ),
31746 /* Need to complement the bit mask then count the ones. */
31753 mkexpr( bit_mask
) ) ) ),
31756 putIReg( RT_addr
, mkexpr( bit_cnt
) );
31760 case 0x1E: // vcntmbd MP=0
31761 case 0x1F: // vcntmbd MP=1
31763 UInt MP
= IFIELD(theInstr
, 16, 1); // bits[15] IBM numbering
31764 IRTemp bit_mask
= newTemp(Ity_I64
);
31765 IRTemp bit_cnt
= newTemp(Ity_I64
);
31767 DIP("vcntmbd r%u,v%u,%u\n", RT_addr
, B_addr
, MP
);
31770 assign( bit_mask
, copy_MSB_bit_fields( getVReg( B_addr
), size
,
31773 /* Result is in IBM bits [0:4] */
31777 popcnt64( vbi
, mkexpr( bit_mask
) ),
31781 /* Need to complement the bit mask then count the ones. */
31788 mkexpr( bit_mask
) ) ) ),
31791 putIReg( RT_addr
, mkexpr( bit_cnt
) );
31796 /* Unkown opc2 value for the dis_VSR_byte_mask function. */
31801 static Bool
dis_av_quad ( UInt prefix
, UInt theInstr
, const VexAbiInfo
* vbi
)
31804 UChar opc1
= ifieldOPC(theInstr
);
31805 UChar vRT_addr
= ifieldRegDS(theInstr
);
31806 UChar vRA_addr
= ifieldRegA(theInstr
);
31807 UChar vRB_addr
= ifieldRegB(theInstr
);
31809 UInt opc2
= IFIELD( theInstr
, 0, 11 );
31811 IRTemp vA
= newTemp(Ity_V128
);
31812 IRTemp vB
= newTemp(Ity_V128
);
31813 IRTemp vC
= IRTemp_INVALID
;
31814 IRTemp cin
= IRTemp_INVALID
;
31816 /* There is no prefixed version of these instructions. */
31819 assign( vA
, getVReg(vRA_addr
));
31820 assign( vB
, getVReg(vRB_addr
));
31823 vex_printf("dis_av_quad(ppc)(instr)\n");
31828 case 0x140: // vaddcuq
31829 DIP("vaddcuq v%d,v%d,v%d\n", vRT_addr
, vRA_addr
, vRB_addr
);
31830 putVReg( vRT_addr
, unop( Iop_32UtoV128
,
31831 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA
),
31833 mkU32(0), False
) ) ) );
31835 case 0x100: // vadduqm
31836 DIP("vadduqm v%d,v%d,v%d\n", vRT_addr
, vRA_addr
, vRB_addr
);
31837 putVReg( vRT_addr
, mkexpr(_get_quad_modulo_or_carry(mkexpr(vA
),
31838 mkexpr(vB
), mkU32(0), True
) ) );
31840 case 0x540: // vsubcuq
31841 DIP("vsubcuq v%d,v%d,v%d\n", vRT_addr
, vRA_addr
, vRB_addr
);
31843 unop( Iop_32UtoV128
,
31844 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA
),
31847 mkU32(1), False
) ) ) );
31849 case 0x500: // vsubuqm
31850 DIP("vsubuqm v%d,v%d,v%d\n", vRT_addr
, vRA_addr
, vRB_addr
);
31852 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA
),
31853 unop( Iop_NotV128
, mkexpr(vB
) ),
31854 mkU32(1), True
) ) );
31856 case 0x054C: // vbpermq
31858 /* The original supports was done with Iops but it caused the internal
31859 temorary storage to be exhausted if there were three or more vbpermq
31860 instructions in a row. Changed to a clean helper on 3/24/2022. For
31861 Powerpc 32-bit support, passing two 128-bit arguments doesn't work.
31862 Hence, the helper is called twice to calculate the result for the
31863 upper and lower 64-bit vB register indicies. */
31864 IRTemp res_hi
= newTemp( Ity_I64
);
31865 IRTemp res_0
= newTemp( Ity_I32
);
31866 IRTemp res_1
= newTemp( Ity_I32
);
31867 IRExpr
* res_low
= mkU64(0);
31869 mkIRExprCCall( Ity_I32
, 0 /*regparms*/,
31870 "vbpermq_clean_helper",
31871 fnptr_to_fnentry( vbi
,
31872 &vbpermq_clean_helper
),
31873 mkIRExprVec_3( unop( Iop_V128HIto64
,
31875 unop( Iop_V128to64
,
31877 unop( Iop_V128HIto64
,
31878 mkexpr(vB
) ) ) ) );
31880 mkIRExprCCall( Ity_I32
, 0 /*regparms*/,
31881 "vbpermq_clean_helper",
31882 fnptr_to_fnentry( vbi
,
31883 &vbpermq_clean_helper
),
31884 mkIRExprVec_3( unop( Iop_V128HIto64
,
31886 unop( Iop_V128to64
,
31888 unop( Iop_V128to64
,
31889 mkexpr(vB
) ) ) ) );
31890 assign( res_hi
, binop( Iop_32HLto64
,
31893 binop( Iop_Shl32
, mkexpr( res_0
),
31895 mkexpr( res_1
) ) ) );
31897 putVReg( vRT_addr
, binop( Iop_64HLtoV128
, mkexpr( res_hi
), res_low
) );
31902 break; // fall through
31905 opc2
= IFIELD( theInstr
, 0, 6 );
31906 vRC_addr
= ifieldRegC(theInstr
);
31907 vC
= newTemp(Ity_V128
);
31908 cin
= newTemp(Ity_I32
);
31910 case 0x3D: // vaddecuq
31911 assign( vC
, getVReg(vRC_addr
));
31912 DIP("vaddecuq v%d,v%d,v%d,v%d\n", vRT_addr
, vRA_addr
, vRB_addr
,
31914 assign(cin
, binop( Iop_And32
,
31916 unop( Iop_V128to64
, mkexpr(vC
) ) ),
31919 unop( Iop_32UtoV128
,
31920 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA
), mkexpr(vB
),
31924 case 0x3C: // vaddeuqm
31925 assign( vC
, getVReg(vRC_addr
));
31926 DIP("vaddeuqm v%d,v%d,v%d,v%d\n", vRT_addr
, vRA_addr
, vRB_addr
,
31928 assign(cin
, binop( Iop_And32
,
31930 unop( Iop_V128to64
, mkexpr(vC
) ) ),
31933 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA
), mkexpr(vB
),
31937 case 0x3F: // vsubecuq
31938 assign( vC
, getVReg(vRC_addr
));
31939 DIP("vsubecuq v%d,v%d,v%d,v%d\n", vRT_addr
, vRA_addr
, vRB_addr
,
31941 assign(cin
, binop( Iop_And32
,
31943 unop( Iop_V128to64
, mkexpr(vC
) ) ),
31946 unop( Iop_32UtoV128
,
31947 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA
),
31953 case 0x3E: // vsubeuqm
31954 assign( vC
, getVReg(vRC_addr
));
31955 DIP("vsubeuqm v%d,v%d,v%d,v%d\n", vRT_addr
, vRA_addr
, vRB_addr
,
31957 assign(cin
, binop( Iop_And32
,
31959 unop( Iop_V128to64
, mkexpr(vC
) ) ),
31962 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA
),
31963 unop( Iop_NotV128
, mkexpr(vB
) ),
31968 vex_printf("dis_av_quad(ppc)(opc2.2)\n");
31975 static IRExpr
* bcd_sign_code_adjust( UInt ps
, IRExpr
* tmp
)
31977 /* The Iop_BCDAdd and Iop_BCDSub will result in the corresponding Power PC
31978 * instruction being issued with ps = 0. If ps = 1, the sign code, which
31979 * is in the least significant four bits of the result, needs to be updated
31982 * If PS=0, the sign code of the result is set to 0b1100.
31983 * If PS=1, the sign code of the result is set to 0b1111.
31985 * Note, the ps value is NOT being passed down to the instruction issue
31986 * because passing a constant via triop() breaks the vbit-test test. The
31987 * vbit-tester assumes it can set non-zero shadow bits for the triop()
31988 * arguments. Thus they have to be expressions not a constant.
31989 * Use 32-bit compare instructions as 64-bit compares are not supported
31992 IRTemp mask
= newTemp(Ity_I64
);
31996 /* sign code is correct, just return it. */
32000 /* Check if lower four bits are 0b1100, if so, change to 0b1111 */
32001 /* Make this work in 32-bit mode using only 32-bit compares */
32002 assign( mask
, unop( Iop_1Sto64
,
32003 binop( Iop_CmpEQ32
, mkU32( 0xC ),
32004 binop( Iop_And32
, mkU32( 0xF ),
32006 unop( Iop_V128to64
, tmp
)
32008 rtn
= binop( Iop_64HLtoV128
,
32009 unop( Iop_V128HIto64
, tmp
),
32011 binop( Iop_And64
, mkU64( 0xF ), mkexpr( mask
) ),
32012 unop( Iop_V128to64
, tmp
) ) );
32019 AltiVec BCD Arithmetic instructions.
32020 These instructions modify CR6 for various conditions in the result,
32021 including when an overflow occurs. We could easily detect all conditions
32022 except when an overflow occurs. But since we can't be 100% accurate
32023 in our emulation of CR6, it seems best to just not support it all.
32025 static Bool
dis_av_bcd_misc ( UInt prefix
, UInt theInstr
, const VexAbiInfo
* vbi
)
32027 UChar opc1
= ifieldOPC(theInstr
);
32028 UChar vRT_addr
= ifieldRegDS(theInstr
);
32029 UChar vRA_addr
= ifieldRegA(theInstr
);
32030 UChar vRB_addr
= ifieldRegB(theInstr
);
32031 IRTemp vA
= newTemp(Ity_V128
);
32032 IRTemp vB
= newTemp(Ity_V128
);
32033 UInt opc2
= IFIELD( theInstr
, 0, 11 );
32034 IRExpr
*pos
, *neg
, *valid
, *zero
, *sign
;
32035 IRTemp eq_lt_gt
= newTemp( Ity_I32
);
32037 /* There is no prefixed version of these instructions. */
32040 assign( vA
, getVReg(vRA_addr
));
32041 assign( vB
, getVReg(vRB_addr
));
32044 vex_printf("dis_av_bcd_misc(ppc)(instr)\n");
32049 case 0x341: // bcdcpsgn. Decimal Copy Sign VX-form
32051 IRExpr
*sign_vb
, *value_va
;
32052 DIP("bcdcpsgn. v%d,v%d,v%d\n", vRT_addr
, vRA_addr
, vRB_addr
);
32055 BCDstring_zero( binop( Iop_AndV128
,
32056 binop( Iop_64HLtoV128
,
32057 mkU64( 0xFFFFFFFFFFFFFFFF ),
32058 mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
32061 /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
32062 * codes 0xB and 0xD are negative.
32064 sign
= binop( Iop_And64
, mkU64( 0xF ),
32065 unop( Iop_V128to64
, mkexpr( vB
) ) );
32067 neg
= mkOR1( binop( Iop_CmpEQ64
,
32070 binop( Iop_CmpEQ64
,
32074 pos
= mkNOT1( neg
);
32076 /* invalid if vA or vB is not valid */
32080 is_BCDstring128( vbi
,
32081 /*Signed*/True
, mkexpr( vA
) ),
32082 is_BCDstring128( vbi
,
32083 /*Signed*/True
, mkexpr( vB
) ) ) );
32085 sign_vb
= binop( Iop_AndV128
,
32086 binop( Iop_64HLtoV128
,
32091 value_va
= binop( Iop_AndV128
,
32092 binop( Iop_64HLtoV128
,
32093 mkU64( 0xFFFFFFFFFFFFFFFF ),
32094 mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
32096 putVReg( vRT_addr
, binop( Iop_OrV128
, sign_vb
, value_va
) );
32101 vex_printf("dis_av_bcd_misc(ppc)(opc2)\n");
32105 /* set CR field 6 to:
32106 * 0b1000 if vB less then 0, i.e. vB is neg and not zero,
32107 * 0b0100 if vB greter then 0, i.e. vB is pos and not zero,
32108 * 0b1000 if vB equals 0,
32109 * 0b0001 if vB is invalid over rules lt, gt, eq
32116 mkNOT1( zero
) ) ),
32122 mkNOT1( zero
) ) ),
32125 unop( Iop_1Uto32
, zero
),
32128 IRTemp valid_mask
= newTemp( Ity_I32
);
32130 assign( valid_mask
, unop( Iop_1Sto32
, unop( Iop_32to1
, valid
) ) );
32132 putGST_field( PPC_GST_CR
,
32135 mkexpr( valid_mask
),
32136 mkexpr( eq_lt_gt
) ),
32138 unop( Iop_Not32
, mkexpr( valid_mask
) ),
32144 static Bool
dis_av_bcd ( UInt prefix
, UInt theInstr
, const VexAbiInfo
* vbi
)
32147 UChar opc1
= ifieldOPC(theInstr
);
32148 UChar vRT_addr
= ifieldRegDS(theInstr
);
32149 UChar vRA_addr
= ifieldRegA(theInstr
);
32150 UChar vRB_addr
= ifieldRegB(theInstr
);
32151 UChar ps
= IFIELD( theInstr
, 9, 1 );
32152 UInt opc2
= IFIELD( theInstr
, 0, 9 );
32153 IRTemp vA
= newTemp(Ity_V128
);
32154 IRTemp vB
= newTemp(Ity_V128
);
32155 IRTemp dst
= newTemp(Ity_V128
);
32156 IRExpr
*pos
, *neg
, *valid
, *zero
, *sign_digit
, *in_range
;
32157 IRTemp eq_lt_gt
= newTemp( Ity_I32
);
32158 IRExpr
*overflow
, *value
;
32160 /* There is no prefixed version of these instructions. */
32163 assign( vA
, getVReg(vRA_addr
));
32164 assign( vB
, getVReg(vRB_addr
));
32167 vex_printf("dis_av_bcd(ppc)(instr)\n");
32172 case 0x1: // bcdadd.
32173 case 0x41: // bcdsub.
32175 /* NOTE 64 bit compares are not supported in 32-bit mode. Use
32176 * 32-bit compares only.
32179 IRExpr
*sign
, *res_smaller
;
32180 IRExpr
*signA
, *signB
, *sign_digitA
, *sign_digitB
;
32181 IRExpr
*zeroA
, *zeroB
, *posA
, *posB
, *negA
, *negB
;
32183 if ( opc2
== 0x1 ) {
32184 DIP("bcdadd. v%d,v%d,v%d,%u\n", vRT_addr
, vRA_addr
, vRB_addr
, ps
);
32185 assign( dst
, bcd_sign_code_adjust( ps
,
32188 mkexpr( vB
) ) ) );
32190 DIP("bcdsub. v%d,v%d,v%d,%u\n", vRT_addr
, vRA_addr
, vRB_addr
, ps
);
32191 assign( dst
, bcd_sign_code_adjust( ps
,
32194 mkexpr( vB
) ) ) );
32197 putVReg( vRT_addr
, mkexpr( dst
) );
32198 /* set CR field 6 */
32200 zero
= BCDstring_zero( binop( Iop_AndV128
,
32201 binop( Iop_64HLtoV128
,
32202 mkU64( 0xFFFFFFFFFFFFFFFF ),
32203 mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
32204 mkexpr(dst
) ) ); // ignore sign
32206 sign_digit
= binop( Iop_And32
, mkU32( 0xF ),
32208 unop( Iop_V128to64
, mkexpr( dst
) ) ) );
32210 sign
= mkOR1( binop( Iop_CmpEQ32
,
32213 binop( Iop_CmpEQ32
,
32216 neg
= mkAND1( sign
, mkNOT1( zero
) );
32218 /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */
32219 pos
= mkAND1( mkNOT1( sign
), mkNOT1( zero
) );
32220 valid
= unop( Iop_64to32
,
32222 is_BCDstring128( vbi
,
32223 /*Signed*/True
, mkexpr( vA
) ),
32224 is_BCDstring128( vbi
,
32225 /*Signed*/True
, mkexpr( vB
) )
32229 zeroA
= BCDstring_zero( binop( Iop_AndV128
,
32230 binop( Iop_64HLtoV128
,
32231 mkU64( 0xFFFFFFFFFFFFFFFF ),
32232 mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
32233 mkexpr( vA
) ) ); // ignore sign
32234 sign_digitA
= binop( Iop_And32
, mkU32( 0xF ),
32236 unop( Iop_V128to64
, mkexpr( vA
) ) ) );
32238 signA
= mkOR1( binop( Iop_CmpEQ32
,
32241 binop( Iop_CmpEQ32
,
32244 negA
= mkAND1( signA
, mkNOT1( zeroA
) );
32245 /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */
32246 posA
= mkAND1( mkNOT1( signA
), mkNOT1( zeroA
) );
32249 zeroB
= BCDstring_zero( binop( Iop_AndV128
,
32250 binop( Iop_64HLtoV128
,
32251 mkU64( 0xFFFFFFFFFFFFFFFF ),
32252 mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
32253 mkexpr( vB
) ) ); // ignore sign
32254 sign_digitB
= binop( Iop_And32
, mkU32( 0xF ),
32256 unop( Iop_V128to64
, mkexpr( vB
) ) ) );
32258 signB
= mkOR1( binop( Iop_CmpEQ32
,
32261 binop( Iop_CmpEQ32
,
32264 negB
= mkAND1( signB
, mkNOT1( zeroB
) );
32267 /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */
32268 posB
= mkAND1( mkNOT1( signB
), mkNOT1( zeroB
) );
32272 res_smaller
= mkAND1( CmpGT128U( mkexpr( vA
), mkexpr( dst
) ),
32273 CmpGT128U( mkexpr( vB
), mkexpr( dst
) ) );
32276 /* Have to do this with 32-bit compares, expensive */
32277 res_smaller
= mkAND1( UNSIGNED_CMP_GT_V128( mkexpr( vA
),
32279 UNSIGNED_CMP_GT_V128( mkexpr( vB
),
32283 if ( opc2
== 0x1) {
32284 /* Overflow for Add can only occur if the signs of the operands
32285 * are the same and the two operands are non-zero. On overflow,
32286 * the PPC hardware produces a result consisting of just the lower
32287 * digits of the result. So, if the result is less then both
32288 * operands and the sign of the operands are the same overflow
32291 overflow
= mkOR1( mkAND1( res_smaller
, mkAND1( negA
, negB
) ),
32292 mkAND1( res_smaller
, mkAND1( posA
, posB
) ) );
32294 /* Overflow for Add can only occur if the signs of the operands
32295 * are the different and the two operands are non-zero. On overflow,
32296 * the PPC hardware produces a result consisting of just the lower
32297 * digits of the result. So, if the result is less then both
32298 * operands and the sign of the operands are different overflow
32301 overflow
= mkOR1( mkAND1( res_smaller
, mkAND1( negA
, posB
) ),
32302 mkAND1( res_smaller
, mkAND1( posA
, negB
) ) );
32307 case 0x081: // bcdus. Decimal Unsigned Shift VX-form
32308 case 0x0C1: // bcds. Decimal Shift VX-form
32309 case 0x1C1: // bcdsr. Decimal Shift and Round VX-form
32312 IRExpr
*shift_mask
, *result
, *new_sign_val
, *sign
;
32313 IRExpr
*not_excess_shift
, *not_excess_shift_mask
;
32314 IRTemp shift_dir_mask
= newTemp( Ity_I64
);
32315 IRTemp shift_by
= newTemp( Ity_I64
);
32316 IRTemp shift_field
= newTemp( Ity_I64
);
32317 IRTemp shifted_out
= newTemp( Ity_V128
);
32318 IRTemp value_shl
= newTemp( Ity_V128
);
32319 IRTemp value_shr
= newTemp( Ity_V128
);
32320 IRTemp round
= newTemp( Ity_I32
);
32322 ULong value_mask_low
= 0;
32323 UInt max_shift
= 0;
32325 if (opc2
== 0x0C1) {
32326 DIP("bcds. v%d,v%d,v%d,%d\n", vRT_addr
, vRA_addr
, vRB_addr
, ps
);
32327 value_mask_low
= 0xFFFFFFFFFFFFFFF0;
32328 max_shift
= 30 * 4; /* maximum without shifting all digits out */
32330 } else if (opc2
== 0x1C1) {
32331 DIP("bcdsr. v%d,v%d,v%d,%d\n", vRT_addr
, vRA_addr
, vRB_addr
, ps
);
32333 value_mask_low
= 0xFFFFFFFFFFFFFFF0;
32334 max_shift
= 30 * 4; /* maximum without shifting all digits out */
32337 DIP("bcdus. v%d,v%d,v%d,%d\n", vRT_addr
, vRA_addr
,
32339 value_mask_low
= 0xFFFFFFFFFFFFFFFF;
32340 max_shift
= 31 * 4; /* maximum without shifting all digits out */
32343 value
= binop( Iop_AndV128
,
32344 binop( Iop_64HLtoV128
,
32345 mkU64( 0xFFFFFFFFFFFFFFFF ),
32346 mkU64( value_mask_low
) ),
32349 zero
= BCDstring_zero( value
);
32351 /* Shift field is 2's complement value */
32352 assign( shift_field
, unop( Iop_V128to64
,
32353 binop( Iop_ShrV128
,
32354 binop( Iop_AndV128
,
32355 binop( Iop_64HLtoV128
,
32361 /* if shift_dir = 0 shift left, otherwise shift right */
32362 shift_dir
= binop( Iop_CmpEQ64
,
32364 mkexpr( shift_field
),
32368 assign( shift_dir_mask
, unop( Iop_1Sto64
, shift_dir
) );
32370 /* Shift field is stored in 2's complement form */
32376 mkexpr( shift_dir_mask
) ),
32377 mkexpr( shift_field
) ),
32379 mkexpr( shift_dir_mask
),
32384 mkexpr( shift_field
) ) ),
32385 mkU64( 0xFF ) ) ) ),
32388 /* If the shift exceeds 128 bits, we need to force the result
32389 * to zero because Valgrind shift amount is only 7-bits. Otherwise,
32390 * we get a shift amount of mod(shift_by, 127)
32392 not_excess_shift
= unop( Iop_1Sto64
,
32393 binop( Iop_CmpLE64U
,
32394 mkexpr( shift_by
),
32395 mkU64( max_shift
) ) );
32397 not_excess_shift_mask
= binop( Iop_64HLtoV128
,
32399 not_excess_shift
);
32402 binop( Iop_ShlV128
, value
, unop( Iop_64to8
,
32403 mkexpr( shift_by
) ) ) );
32405 binop( Iop_AndV128
,
32406 binop( Iop_64HLtoV128
,
32407 mkU64( 0xFFFFFFFFFFFFFFFF ),
32408 mkU64( value_mask_low
) ),
32409 binop( Iop_ShrV128
,
32412 mkexpr( shift_by
) ) ) ) );
32414 /* Overflow occurs if the shift amount is greater than zero, the
32415 * operation is a left shift and any non-zero digits are left
32418 assign( shifted_out
,
32420 binop( Iop_ShrV128
,
32425 mkexpr( shift_by
) ) ) ),
32426 binop( Iop_AndV128
,
32428 not_excess_shift_mask
),
32431 overflow
= mkAND1( mkNOT1( BCDstring_zero( mkexpr( shifted_out
) ) ),
32432 mkAND1( mkNOT1( shift_dir
),
32433 binop( Iop_CmpNE64
,
32434 mkexpr( shift_by
),
32437 if ((opc2
== 0xC1) || (opc2
== 0x1C1)) {
32438 /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
32439 * codes 0xB and 0xD are negative.
32441 sign_digit
= binop( Iop_And64
, mkU64( 0xF ),
32442 unop( Iop_V128to64
, mkexpr( vB
) ) );
32444 sign
= mkOR1( binop( Iop_CmpEQ64
,
32447 binop( Iop_CmpEQ64
,
32450 neg
= mkAND1( sign
, mkNOT1( zero
) );
32452 /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */
32453 pos
= mkAND1( mkNOT1( sign
), mkNOT1( zero
) );
32457 is_BCDstring128( vbi
, /* Signed */True
, mkexpr( vB
) ) );
32460 /* string is an unsigned BCD value */
32467 is_BCDstring128( vbi
, /* Unsigned */False
,
32472 vB positive, sign is C
32473 vB negative, sign is D
32475 vB positive, sign is F
32476 vB negative, sign is D
32477 Note can't use pos or neg here since they are ANDed with zero,
32481 new_sign_val
= binop( Iop_Or64
,
32482 unop( Iop_1Uto64
, sign
),
32486 new_sign_val
= binop( Iop_Xor64
,
32488 unop( Iop_1Uto64
, sign
),
32493 shift_mask
= binop( Iop_64HLtoV128
,
32494 unop( Iop_1Sto64
, shift_dir
),
32495 unop( Iop_1Sto64
, shift_dir
) );
32497 result
= binop( Iop_OrV128
,
32498 binop( Iop_AndV128
, mkexpr( value_shr
), shift_mask
),
32499 binop( Iop_AndV128
,
32500 mkexpr( value_shl
),
32501 unop( Iop_NotV128
, shift_mask
) ) );
32503 if (opc2
== 0xC1) { // bcds.
32504 putVReg( vRT_addr
, binop( Iop_OrV128
,
32505 binop( Iop_64HLtoV128
,
32508 binop( Iop_AndV128
,
32509 not_excess_shift_mask
,
32511 } else if (opc2
== 0x1C1) { //bcdsr.
32512 /* If shifting right, need to round up if needed */
32513 assign( round
, unop( Iop_1Uto32
,
32515 check_BCD_round( value
,
32520 binop( Iop_64HLtoV128
,
32523 binop( Iop_AndV128
,
32524 not_excess_shift_mask
,
32525 mkexpr( increment_BCDstring( vbi
, result
,
32529 putVReg( vRT_addr
, binop( Iop_AndV128
,
32530 not_excess_shift_mask
,
32536 case 0x101: // bcdtrunc. Decimal Truncate VX-form
32537 case 0x141: // bcdutrunc. Decimal Unsigned Truncate VX-form
32539 IRTemp length
= newTemp( Ity_I64
);
32540 IRTemp masked_out
= newTemp( Ity_V128
);
32541 IRExpr
*new_sign_val
, *result
, *shift
;
32542 IRExpr
*length_neq_128
, *sign
;
32543 ULong value_mask_low
;
32546 if ( opc2
== 0x101) { // bcdtrunc.
32547 value_mask_low
= 0xFFFFFFFFFFFFFFF0;
32550 value_mask_low
= 0xFFFFFFFFFFFFFFFF;
32554 assign( length
, binop( Iop_And64
,
32555 unop( Iop_V128HIto64
,
32557 mkU64( 0xFFFF ) ) );
32558 shift
= unop( Iop_64to8
,
32561 mkU64( max_digits
),
32562 mkexpr( length
) ),
32565 /* Note ShrV128 gets masked by 127 so a shift of 128 results in
32566 * the value not being shifted. A shift of 128 sets the register
32567 * zero. So if length+1 = 128, just set the value to 0.
32569 length_neq_128
= mkNOT1( binop( Iop_CmpEQ64
,
32573 assign( masked_out
,
32574 binop( Iop_AndV128
,
32575 binop( Iop_64HLtoV128
,
32576 unop( Iop_1Sto64
, length_neq_128
),
32577 unop( Iop_1Sto64
, length_neq_128
) ),
32578 binop( Iop_ShrV128
,
32585 mkexpr( length
) ) ) ) )
32588 /* Overflow occurs if any of the left most 31-length digits of vB
32591 overflow
= mkNOT1( BCDstring_zero( mkexpr( masked_out
) ) );
32593 value
= binop( Iop_AndV128
,
32594 binop( Iop_64HLtoV128
,
32595 mkU64( 0xFFFFFFFFFFFFFFFF ),
32596 mkU64( value_mask_low
) ),
32600 if ( opc2
== 0x101 ) { // bcdtrunc.
32601 /* Check if all of the non-sign digits are zero */
32602 zero
= BCDstring_zero( binop( Iop_AndV128
,
32603 binop( Iop_64HLtoV128
,
32604 mkU64( 0xFFFFFFFFFFFFFFFF ),
32605 mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
32608 /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
32609 * codes 0xB and 0xD are negative.
32611 sign_digit
= binop( Iop_And64
, mkU64( 0xF ),
32612 unop( Iop_V128to64
, mkexpr( vB
) ) );
32614 sign
= mkOR1( binop( Iop_CmpEQ64
,
32617 binop( Iop_CmpEQ64
,
32620 neg
= mkAND1( sign
, mkNOT1( zero
) );
32622 /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */
32623 pos
= mkAND1( mkNOT1( sign
), mkNOT1( zero
) );
32625 /* Note can't use pos or neg here since they are ANDed with zero,
32629 new_sign_val
= binop( Iop_Or64
,
32630 unop( Iop_1Uto64
, sign
),
32633 new_sign_val
= binop( Iop_Xor64
,
32635 unop( Iop_1Uto64
, sign
),
32641 is_BCDstring128( vbi
, /* Signed */True
, mkexpr( vB
) ) );
32643 } else { // bcdutrunc.
32644 /* Check if all of the digits are zero */
32645 zero
= BCDstring_zero( value
);
32647 /* unsigned value, need to make CC code happy */
32650 /* Pos position AKA gt = 1 if (not eq zero) */
32651 pos
= mkNOT1( zero
);
32654 is_BCDstring128( vbi
, /* Unsigned */False
,
32658 /* If vB is not valid, the result is undefined, but we need to
32659 * match the hardware so the output of the test suite will match.
32660 * Hardware sets result to 0x0.
32662 result
= binop( Iop_AndV128
,
32664 binop( Iop_ShrV128
,
32665 binop( Iop_ShlV128
, value
, shift
),
32668 if ( opc2
== 0x101) { // bcdtrunc.
32669 putVReg( vRT_addr
, binop( Iop_OrV128
,
32670 binop( Iop_64HLtoV128
,
32675 putVReg( vRT_addr
, result
);
32680 case 0x181: // bcdctz., bcdctn., bcdcfz., bcdcfn., bcdsetsgn.,
32681 // bcdcfsq., bcdctsq.
32683 UInt inst_select
= IFIELD( theInstr
, 16, 5);
32685 switch (inst_select
) {
32686 case 0: // bcdctsq. (Decimal Convert to Signed Quadword VX-form)
32690 /* The instruction takes a 32-bit integer in a vector source
32691 * register and returns the signed packed decimal number
32692 * in a vector register. The source integer needs to be moved
32693 * from the V128 to an I32 for the Iop.
32696 DIP("bcdctsq v%d, v%d\n", vRT_addr
, vRB_addr
);
32698 putVReg( vRT_addr
, unop( Iop_BCD128toI128S
, mkexpr( vB
) ) );
32700 sign
= binop( Iop_And64
,
32701 unop( Iop_V128to64
, mkexpr( vB
) ),
32703 zero
= mkAND1( binop( Iop_CmpEQ64
,
32704 unop( Iop_V128HIto64
, mkexpr( vB
) ),
32706 binop( Iop_CmpEQ64
,
32708 unop( Iop_V128to64
, mkexpr( vB
) ),
32709 mkU64( 0xFFFFFFF0 ) ),
32711 pos
= mkAND1( mkNOT1( zero
),
32712 mkOR1( mkOR1( binop( Iop_CmpEQ64
,
32713 sign
, mkU64( 0xA ) ),
32714 binop( Iop_CmpEQ64
,
32715 sign
, mkU64( 0xC ) ) ),
32716 mkOR1( binop( Iop_CmpEQ64
,
32717 sign
, mkU64( 0xE ) ),
32718 binop( Iop_CmpEQ64
,
32719 sign
, mkU64( 0xF ) ) ) ) );
32720 neg
= mkAND1( mkNOT1( zero
),
32721 mkOR1( binop( Iop_CmpEQ64
, sign
, mkU64( 0xB ) ),
32722 binop( Iop_CmpEQ64
, sign
, mkU64( 0xD ) ) ) );
32724 /* Check each of the nibbles for a valid digit 0 to 9 */
32727 is_BCDstring128( vbi
, /* Signed */True
,
32729 overflow
= mkU1( 0 ); // not used
32733 case 2: // bcdcfsq. (Decimal Convert from Signed Quadword VX-form)
32735 IRExpr
*pos_upper_gt
, *pos_upper_eq
, *pos_lower_gt
;
32736 IRExpr
*neg_upper_lt
, *neg_upper_eq
, *neg_lower_lt
;
32738 DIP("bcdcfsq v%d, v%d, %d\n", vRT_addr
, vRB_addr
, ps
);
32740 /* The instruction takes a signed packed decimal number and
32741 * returns the integer value in the vector register. The Iop
32742 * returns an I32 which needs to be moved to the destination
32746 binop( Iop_I128StoBCD128
, mkexpr( vB
), mkU8( ps
) ) );
32748 zero
= mkAND1( binop( Iop_CmpEQ64
, mkU64( 0 ),
32749 unop( Iop_V128to64
, mkexpr( vB
) ) ),
32750 binop( Iop_CmpEQ64
, mkU64( 0 ),
32751 unop( Iop_V128HIto64
, mkexpr( vB
) ) ) );
32752 pos
= mkAND1( mkNOT1 ( zero
),
32753 binop( Iop_CmpEQ64
, mkU64( 0 ),
32755 unop( Iop_V128HIto64
,
32757 mkU64( 0x8000000000000000UL
) ) ) );
32758 neg
= mkAND1( mkNOT1 ( zero
),
32759 binop( Iop_CmpEQ64
, mkU64( 0x8000000000000000UL
),
32761 unop( Iop_V128HIto64
,
32763 mkU64( 0x8000000000000000UL
) ) ) );
32765 /* Overflow occurs if: vB > 10^31-1 OR vB < -10^31-1
32766 * do not have a 128 bit compare. Will have to compare the
32767 * upper 64 bit and athe lower 64 bits. If the upper 64-bits
32768 * are equal then overflow if the lower 64 bits of vB is greater
32769 * otherwise if the upper bits of vB is greater then the max
32770 * for the upper 64-bits then overflow
32772 * 10^31-1 = 0x7E37BE2022C0914B267FFFFFFF
32774 pos_upper_gt
= binop( Iop_CmpLT64U
,
32775 mkU64( 0x7E37BE2022 ),
32776 unop( Iop_V128HIto64
, mkexpr( vB
) ) );
32777 pos_upper_eq
= binop( Iop_CmpEQ64
,
32778 unop( Iop_V128HIto64
, mkexpr( vB
) ),
32779 mkU64( 0x7E37BE2022 ) );
32780 pos_lower_gt
= binop( Iop_CmpLT64U
,
32781 mkU64( 0x0914B267FFFFFFF ),
32782 unop( Iop_V128to64
, mkexpr( vB
) ) );
32783 /* -10^31-1 = 0X81C841DFDD3F6EB4D97FFFFFFF */
32784 neg_upper_lt
= binop( Iop_CmpLT64U
,
32785 mkU64( 0X81C841DFDD ),
32786 unop( Iop_V128HIto64
, mkexpr( vB
) ) );
32787 neg_upper_eq
= binop( Iop_CmpEQ64
,
32788 unop( Iop_V128HIto64
, mkexpr( vB
) ),
32789 mkU64( 0X81C841DFDD ) );
32790 neg_lower_lt
= binop( Iop_CmpLT64U
,
32791 mkU64( 0x3F6EB4D97FFFFFFF ),
32792 unop( Iop_V128to64
, mkexpr( vB
) ) );
32794 /* calculate overflow, masking for positive and negative */
32795 overflow
= mkOR1( mkAND1( pos
,
32796 mkOR1( pos_upper_gt
,
32797 mkAND1( pos_upper_eq
,
32798 pos_lower_gt
) ) ),
32800 mkOR1( neg_upper_lt
,
32801 mkAND1( neg_upper_eq
,
32804 valid
= mkU32( 1 );
32808 case 4: // bcdctz. (Decimal Convert to Zoned VX-form)
32810 IRExpr
*ox_flag
, *sign
, *vrb_nibble30
;
32812 unsigned int upper_byte
, sign_byte
;
32813 IRTemp tmp
= newTemp( Ity_V128
);
32815 DIP("bcdctz. v%d,v%d,%d\n", vRT_addr
, vRB_addr
, ps
);
32820 neg_bit_shift
= 4+2; /* sign byte is in bits [7:4] */
32824 neg_bit_shift
= 4+0;
32827 /* Grab vB bits[7:4]. It goes into bits [3:0] of the
32830 vrb_nibble30
= binop( Iop_Shr64
,
32832 unop( Iop_V128to64
, mkexpr( vB
) ),
32836 /* Upper 24 hex digits of VB, i.e. hex digits vB[0:23],
32837 * must be zero for the value to be zero. This goes
32838 * in the overflow position of the condition code register.
32840 ox_flag
= binop( Iop_CmpEQ64
,
32842 unop( Iop_V128to64
, mkexpr( vB
) ),
32843 mkU64( 0xFFFFFFFFFFFFFFFF ) ),
32846 /* zero is the same as eq_flag */
32847 zero
= mkAND1( binop( Iop_CmpEQ64
,
32849 unop( Iop_V128HIto64
, mkexpr( vB
) ),
32850 mkU64( 0xFFFFFFFFFFFFFFFF ) ),
32852 binop( Iop_CmpEQ64
,
32854 unop( Iop_V128to64
, mkexpr( vB
) ),
32855 mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
32858 /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
32859 * codes 0xB and 0xD are negative.
32861 sign_digit
= binop( Iop_And64
, mkU64( 0xF ),
32862 unop( Iop_V128to64
, mkexpr( vB
) ) );
32864 /* The negative value goes in the LT bit position of the
32865 * condition code register. Set neg if the sign of vB
32866 * is negative and zero is true.
32868 sign
= mkOR1( binop( Iop_CmpEQ64
,
32871 binop( Iop_CmpEQ64
,
32874 neg
= mkAND1( sign
, mkNOT1( zero
) );
32876 /* The positive value goes in the LT bit position of the
32877 * condition code register. Set positive if the sign of the
32878 * value is not negative.
32880 pos
= mkAND1( mkNOT1( sign
), mkNOT1( zero
) );
32883 convert_to_zoned( vbi
, mkexpr( vB
),
32884 mkU64( upper_byte
) ) );
32886 /* Insert the sign based on ps and sign of vB
32887 * in the lower byte.
32891 binop( Iop_64HLtoV128
,
32896 binop( Iop_64HLtoV128
,
32899 mkU64( sign_byte
),
32903 mkU8( neg_bit_shift
)
32906 /* A valid number must have a value that is less then or
32907 * equal to 10^16 - 1. This is checked by making sure
32908 * bytes [31:16] of vB are zero.
32910 in_range
= binop( Iop_CmpEQ64
,
32912 mkU64( 0xFFFFFFFFFFFFFFF0 ),
32913 unop( Iop_V128HIto64
, mkexpr( vB
) ) ),
32916 /* overflow is set if ox_flag or not in_inrange. Setting is
32917 * ORed with the other condition code values.
32919 overflow
= mkOR1( ox_flag
, mkNOT1( in_range
) );
32921 /* The sign code must be between 0xA and 0xF and all digits are
32922 * between 0x0 and 0x9. The vB must be in range to be valid.
32923 * If not valid, condition code set to 0x0001.
32927 is_BCDstring128( vbi
, /* Signed */True
,
32932 case 5: // bcdctn. (Decimal Convert to National VX-form)
32934 IRExpr
*ox_flag
, *sign
;
32935 IRTemp tmp
= newTemp( Ity_V128
);;
32937 DIP("bcdctn. v%d,v%d\n", vRT_addr
, vRB_addr
);
32939 value
= binop( Iop_And64
,
32940 mkU64( 0xFFFFFFFF ),
32941 unop( Iop_V128to64
, mkexpr( vB
) ) );
32943 /* A valid number must have a value that is less then or
32944 * equal to 10^7 - 1. This is checked by making sure
32945 * bytes [31:8] of vB are zero.
32947 in_range
= mkAND1( binop( Iop_CmpEQ64
,
32948 unop( Iop_V128HIto64
, mkexpr( vB
) ),
32950 binop( Iop_CmpEQ64
,
32952 unop( Iop_V128to64
,
32957 /* The sign code must be between 0xA and 0xF and all digits are
32958 * between 0x0 and 0x9.
32962 is_BCDstring128( vbi
, /* Signed */True
,
32965 /* Upper 24 hex digits of VB, i.e. hex ditgits vB[0:23],
32966 * must be zero for the ox_flag to be zero. This goes
32967 * in the LSB position (variable overflow) of the
32968 * condition code register.
32971 mkNOT1( mkAND1( binop( Iop_CmpEQ64
,
32973 unop( Iop_V128HIto64
,
32975 mkU64( 0xFFFFFFFFFFFFFFFF ) ),
32977 binop( Iop_CmpEQ64
,
32979 unop( Iop_V128to64
,
32981 mkU64( 0xFFFFFFFF00000000 ) ),
32984 /* Set zero to 1 if all of the bytes in vB are zero. This is
32985 * used when setting the lt_flag (variable neg) and the gt_flag
32988 zero
= mkAND1( binop( Iop_CmpEQ64
,
32990 unop( Iop_V128HIto64
,
32992 mkU64( 0xFFFFFFFFFFFFFFFF ) ),
32994 binop( Iop_CmpEQ64
,
32996 unop( Iop_V128to64
, mkexpr( vB
) ),
32997 mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
33000 /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
33001 * codes 0xB and 0xD are negative.
33003 sign_digit
= binop( Iop_And64
, mkU64( 0xF ), value
);
33005 /* The negative value goes in the LT bit position of the
33006 * condition code register. Set neg if the sign of the
33007 * value is negative and the value is zero.
33009 sign
= mkOR1( binop( Iop_CmpEQ64
,
33012 binop( Iop_CmpEQ64
,
33015 neg
= mkAND1( sign
, mkNOT1( zero
) );
33017 /* The positive value goes in the LT bit position of the
33018 * condition code register. Set neg if the sign of the
33019 * value is not negative and the value is zero.
33021 pos
= mkAND1( mkNOT1( sign
), mkNOT1( zero
) );
33024 convert_to_national( vbi
, mkexpr( vB
) ) );
33026 /* If vB is positive insert sign value 0x002B, otherwise
33027 * insert 0x002D for negative. Have to use sign not neg
33028 * because neg has been ANDed with zero. This is 0x29
33029 * OR'd with (sign << 1 | NOT sign) << 1.
33030 * sign = 1 if vB is negative.
33035 binop( Iop_64HLtoV128
,
33051 /* The sign code must be between 0xA and 0xF and all digits are
33052 * between 0x0 and 0x9. The vB must be in range to be valid.
33056 is_BCDstring128( vbi
, /* Signed */True
,
33059 overflow
= ox_flag
;
33063 case 6: // bcdcfz. (Decimal Convert From Zoned VX-form)
33066 IRTemp tmp
= newTemp( Ity_V128
);;
33068 DIP("bcdcfz. v%d,v%d,%d\n", vRT_addr
, vRB_addr
, ps
);
33070 valid
= unop( Iop_1Uto32
, is_Zoned_decimal( vB
, ps
) );
33073 convert_from_zoned( vbi
, mkexpr( vB
) ) );
33075 /* If the result of checking the lower 4 bits of each 8-bit
33076 * value is zero, then the "number" was zero.
33079 binop( Iop_CmpEQ64
,
33082 unop( Iop_V128to64
, mkexpr( vB
) ),
33083 mkU64( 0x0F0F0F0F0F0F0F0FULL
) ),
33085 unop( Iop_V128to64
, mkexpr( vB
) ),
33086 mkU64( 0x0F0F0F0F0F0F0F0FULL
) ) ),
33089 /* Sign bit is in bit 6 of vB. */
33090 sign_digit
= binop( Iop_And64
, mkU64( 0xF0 ),
33091 unop( Iop_V128to64
, mkexpr( vB
) ) );
33094 /* sign will be equal to 0 for positive number */
33095 sign
= binop( Iop_CmpEQ64
,
33102 binop( Iop_CmpEQ64
, sign_digit
, mkU64( 0xB0 ) ),
33103 binop( Iop_CmpEQ64
, sign_digit
, mkU64( 0xD0 ) ) );
33106 /* The negative value goes in the LT bit position of the
33107 * condition code register. Set neg if the sign of the
33108 * value is negative and the value is zero.
33110 neg
= mkAND1( sign
, mkNOT1( zero
) );
33112 /* The positive value goes in the GT bit position of the
33113 * condition code register. Set neg if the sign of the
33114 * value is not negative and the value is zero.
33116 pos
= mkAND1( mkNOT1( sign
), mkNOT1( zero
) );
33118 /* sign of the result is 0xC for positive, 0xD for negative */
33122 binop( Iop_64HLtoV128
,
33126 unop( Iop_1Uto64
, sign
)
33128 /* For this instructions the LSB position in the CC
33129 * field, the overflow position in the other instructions,
33130 * is given by 0. There is nothing to or with LT, EQ or GT.
33132 overflow
= mkU1( 0 );
33136 case 7: // bcdcfn. (Decimal Convert From National VX-form)
33138 IRTemp hword_7
= newTemp( Ity_I64
);
33140 IRTemp tmp
= newTemp( Ity_I64
);;
33142 DIP("bcdcfn. v%d,v%d,%d\n", vRT_addr
, vRB_addr
, ps
);
33144 /* check that the value is valid */
33145 valid
= unop( Iop_1Uto32
, is_National_decimal( vB
) );
33147 assign( hword_7
, binop( Iop_And64
,
33148 unop( Iop_V128to64
, mkexpr( vB
) ),
33149 mkU64( 0xFFF ) ) );
33150 /* sign = 1 if vB is negative */
33151 sign
= binop( Iop_CmpEQ64
, mkexpr( hword_7
), mkU64( 0x002D ) );
33153 assign( tmp
, convert_from_national( vbi
, mkexpr( vB
) ) );
33155 /* If the result of checking the lower 4 bits of each 16-bit
33156 * value is zero, then the "number" was zero.
33159 binop( Iop_CmpEQ64
,
33162 unop( Iop_V128HIto64
, mkexpr( vB
) ),
33163 mkU64( 0x000F000F000F000FULL
) ),
33165 unop( Iop_V128to64
, mkexpr( vB
) ),
33166 mkU64( 0x000F000F000F0000ULL
) ) ),
33170 /* The negative value goes in the LT bit position of the
33171 * condition code register. Set neg if the sign of the
33172 * value is negative and the value is zero.
33174 neg
= mkAND1( sign
, mkNOT1( zero
) );
33176 /* The positive value goes in the GT bit position of the
33177 * condition code register. Set neg if the sign of the
33178 * value is not negative and the value is zero.
33180 pos
= mkAND1( mkNOT1( sign
), mkNOT1( zero
) );
33182 /* For this instructions the LSB position in the CC
33183 * field, the overflow position in the other instructions,
33184 * is given by invalid. There is nothing to OR with the valid
33187 overflow
= mkU1( 0 );
33189 /* sign of the result is:
33190 ( 0b1100 OR neg) OR (ps OR (ps AND pos) << 1 )
33194 binop( Iop_64HLtoV128
,
33208 unop( Iop_1Uto64
, sign
) ),
33209 mkexpr( tmp
) ) ) ) );
33214 case 31: // bcdsetsgn. (BCD set sign)
33216 IRExpr
*new_sign_val
, *sign
;
33218 DIP("bcdsetsgn. v%d,v%d,%d\n", vRT_addr
, vRB_addr
, ps
);
33220 value
= binop( Iop_AndV128
,
33221 binop( Iop_64HLtoV128
,
33222 mkU64( 0xFFFFFFFFFFFFFFFF ),
33223 mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
33225 zero
= BCDstring_zero( value
);
33227 /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
33228 * codes 0xB and 0xD are negative.
33230 sign_digit
= binop( Iop_And64
, mkU64( 0xF ),
33231 unop( Iop_V128to64
, mkexpr( vB
) ) );
33233 sign
= mkOR1( binop( Iop_CmpEQ64
,
33236 binop( Iop_CmpEQ64
,
33239 neg
= mkAND1( sign
, mkNOT1( zero
) );
33241 pos
= mkAND1( mkNOT1( sign
), mkNOT1( zero
) );
33245 is_BCDstring128( vbi
, /* Signed */True
,
33249 vB positive, sign is C
33250 vB negative, sign is D
33252 vB positive, sign is F
33253 vB negative, sign is D
33254 Note can't use pos or neg here since they are ANDed with
33255 zero, use sign instead.
33258 new_sign_val
= binop( Iop_Or64
,
33259 unop( Iop_1Uto64
, sign
),
33263 new_sign_val
= binop( Iop_Xor64
,
33265 unop( Iop_1Uto64
, sign
),
33270 putVReg( vRT_addr
, binop( Iop_OrV128
,
33271 binop( Iop_64HLtoV128
,
33275 /* For this instructions the LSB position in the CC
33276 * field, the overflow position in the other instructions,
33277 * is given by invalid.
33279 overflow
= unop( Iop_32to1
, unop( Iop_Not32
, valid
) );
33284 vex_printf("dis_av_bcd(ppc)(invalid inst_select)\n");
33291 vex_printf("dis_av_bcd(ppc)(opc2)\n");
33295 IRTemp valid_mask
= newTemp( Ity_I32
);
33297 assign( valid_mask
, unop( Iop_1Sto32
, unop( Iop_32to1
, valid
) ) );
33299 /* set CR field 6 to:
33300 * 0b1000 if vB less then 0, i.e. vB is neg and not zero,
33301 * 0b0100 if vB greter then 0, i.e. vB is pos and not zero,
33302 * 0b0010 if vB equals 0,
33303 * 0b0001 if vB is invalid over rules lt, gt, eq
33308 unop( Iop_1Uto32
, neg
),
33312 unop( Iop_1Uto32
, pos
),
33315 unop( Iop_1Uto32
, zero
),
33317 /* valid is 1 if it is a valid number, complement and put in the
33318 * invalid bit location, overriding ls, eq, gt, overflow.
33320 putGST_field( PPC_GST_CR
,
33323 mkexpr( valid_mask
),
33325 mkexpr( eq_lt_gt
),
33326 unop( Iop_1Uto32
, overflow
) ) ),
33328 unop( Iop_Not32
, mkexpr( valid_mask
) ),
33335 AltiVec Floating Point Arithmetic Instructions
33337 static Bool
dis_av_fp_arith ( UInt prefix
, UInt theInstr
)
33340 UChar opc1
= ifieldOPC(theInstr
);
33341 UChar vD_addr
= ifieldRegDS(theInstr
);
33342 UChar vA_addr
= ifieldRegA(theInstr
);
33343 UChar vB_addr
= ifieldRegB(theInstr
);
33344 UChar vC_addr
= ifieldRegC(theInstr
);
33347 IRTemp vA
= newTemp(Ity_V128
);
33348 IRTemp vB
= newTemp(Ity_V128
);
33349 IRTemp vC
= newTemp(Ity_V128
);
33351 /* There is no prefixed version of these instructions. */
33354 assign( vA
, getVReg(vA_addr
));
33355 assign( vB
, getVReg(vB_addr
));
33356 assign( vC
, getVReg(vC_addr
));
33359 vex_printf("dis_av_fp_arith(ppc)(instr)\n");
33363 IRTemp rm
= newTemp(Ity_I32
);
33364 assign(rm
, get_IR_roundingmode());
33366 opc2
= IFIELD( theInstr
, 0, 6 );
33368 case 0x2E: // vmaddfp (Multiply Add FP, AV p177)
33369 DIP("vmaddfp v%d,v%d,v%d,v%d\n",
33370 vD_addr
, vA_addr
, vC_addr
, vB_addr
);
33373 triop( Iop_Add32Fx4
,
33374 mkU32( Irrm_NEAREST
),
33375 dnorm_adj_Vector( mkexpr( vB
) ),
33376 dnorm_adj_Vector( triop( Iop_Mul32Fx4
,
33377 mkU32( Irrm_NEAREST
),
33378 dnorm_adj_Vector( mkexpr( vA
) ),
33379 dnorm_adj_Vector( mkexpr( vC
) ) )
33383 case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215)
33384 DIP("vnmsubfp v%d,v%d,v%d,v%d\n",
33385 vD_addr
, vA_addr
, vC_addr
, vB_addr
);
33387 negate_Vector( Ity_I32
,
33389 triop( Iop_Sub32Fx4
,
33390 mkU32( Irrm_NEAREST
),
33392 triop( Iop_Mul32Fx4
,
33393 mkU32( Irrm_NEAREST
),
33394 dnorm_adj_Vector( mkexpr( vA
) ),
33395 dnorm_adj_Vector( mkexpr( vC
) ) ) ),
33396 dnorm_adj_Vector( mkexpr( vB
) ) ) ) ) );
33401 break; // Fall through...
33404 opc2
= IFIELD( theInstr
, 0, 11 );
33406 case 0x00A: // vaddfp (Add FP, AV p137)
33407 DIP("vaddfp v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
33409 dnorm_adj_Vector( triop( Iop_Add32Fx4
, mkU32( Irrm_NEAREST
),
33410 dnorm_adj_Vector( mkexpr( vA
) ),
33411 dnorm_adj_Vector( mkexpr( vB
) ) ) ) );
33414 case 0x04A: // vsubfp (Subtract FP, AV p261)
33415 DIP("vsubfp v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
33417 dnorm_adj_Vector( triop( Iop_Sub32Fx4
, mkU32( Irrm_NEAREST
),
33418 dnorm_adj_Vector( mkexpr( vA
) ),
33419 dnorm_adj_Vector( mkexpr( vB
) ) ) ) );
33422 case 0x40A: // vmaxfp (Maximum FP, AV p178)
33423 DIP("vmaxfp v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
33425 dnorm_adj_Vector( binop( Iop_Max32Fx4
,
33426 mkexpr( vA
), mkexpr( vB
) ) ) );
33429 case 0x44A: // vminfp (Minimum FP, AV p187)
33430 DIP("vminfp v%d,v%d,v%d\n", vD_addr
, vA_addr
, vB_addr
);
33432 dnorm_adj_Vector( binop( Iop_Min32Fx4
,
33433 mkexpr( vA
), mkexpr( vB
) ) ) );
33437 break; // Fall through...
33441 if (vA_addr
!= 0) {
33442 vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n");
33447 case 0x10A: // vrefp (Reciprocal Esimate FP, AV p228)
33448 DIP("vrefp v%d,v%d\n", vD_addr
, vB_addr
);
33449 putVReg( vD_addr
, dnorm_adj_Vector( unop( Iop_RecipEst32Fx4
,
33450 dnorm_adj_Vector( mkexpr( vB
) ) ) ) );
33453 case 0x14A: // vrsqrtefp (Reciprocal Sqrt Estimate FP, AV p237)
33454 DIP("vrsqrtefp v%d,v%d\n", vD_addr
, vB_addr
);
33455 putVReg( vD_addr
, dnorm_adj_Vector( unop( Iop_RSqrtEst32Fx4
,
33456 dnorm_adj_Vector( mkexpr( vB
) ) ) ) );
33459 case 0x18A: // vexptefp (2 Raised to the Exp Est FP, AV p173)
33460 DIP("vexptefp v%d,v%d\n", vD_addr
, vB_addr
);
33461 /* NOTE, need to address dnormalized value handling when this is
33464 dnorm_adj_Vector( unop( Iop_Exp2_32Fx4
,
33465 dnorm_adj_Vector( mkexpr( vB
) ) ) ) );
33468 case 0x1CA: // vlogefp (Log2 Estimate FP, AV p175)
33469 DIP("vlogefp v%d,v%d\n", vD_addr
, vB_addr
);
33470 /* NOTE, need to address dnormalized value handling when this is
33473 dnorm_adj_Vector( unop( Iop_Log2_32Fx4
,
33474 dnorm_adj_Vector( mkexpr( vB
) ) ) ) );
33478 vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2
);
33485 AltiVec Floating Point Compare Instructions
33487 static Bool
dis_av_fp_cmp ( UInt prefix
, UInt theInstr
)
33490 UChar opc1
= ifieldOPC(theInstr
);
33491 UChar vD_addr
= ifieldRegDS(theInstr
);
33492 UChar vA_addr
= ifieldRegA(theInstr
);
33493 UChar vB_addr
= ifieldRegB(theInstr
);
33494 UChar flag_rC
= ifieldBIT10(theInstr
);
33495 UInt opc2
= IFIELD( theInstr
, 0, 10 );
33497 Bool cmp_bounds
= False
;
33499 IRTemp vA
= newTemp(Ity_V128
);
33500 IRTemp vB
= newTemp(Ity_V128
);
33501 IRTemp vD
= newTemp(Ity_V128
);
33503 /* There is no prefixed version of these instructions. */
33506 assign( vA
, getVReg(vA_addr
));
33507 assign( vB
, getVReg(vB_addr
));
33510 vex_printf("dis_av_fp_cmp(ppc)(instr)\n");
33515 case 0x0C6: // vcmpeqfp (Compare Equal-to FP, AV p159)
33516 DIP("vcmpeqfp%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
33517 vD_addr
, vA_addr
, vB_addr
);
33518 assign( vD
, binop( Iop_CmpEQ32Fx4
,
33519 dnorm_adj_Vector( mkexpr( vA
) ),
33520 dnorm_adj_Vector( mkexpr( vB
) ) ) );
33523 case 0x1C6: // vcmpgefp (Compare Greater-than-or-Equal-to, AV p163)
33524 DIP("vcmpgefp%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
33525 vD_addr
, vA_addr
, vB_addr
);
33526 assign( vD
, binop( Iop_CmpGE32Fx4
,
33527 dnorm_adj_Vector( mkexpr( vA
) ),
33528 dnorm_adj_Vector( mkexpr( vB
) ) ) );
33531 case 0x2C6: // vcmpgtfp (Compare Greater-than FP, AV p164)
33532 DIP("vcmpgtfp%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
33533 vD_addr
, vA_addr
, vB_addr
);
33534 assign( vD
, binop( Iop_CmpGT32Fx4
,
33535 dnorm_adj_Vector( mkexpr( vA
) ),
33536 dnorm_adj_Vector( mkexpr( vB
) ) ) );
33539 case 0x3C6: { // vcmpbfp (Compare Bounds FP, AV p157)
33540 IRTemp gt
= newTemp(Ity_V128
);
33541 IRTemp lt
= newTemp(Ity_V128
);
33542 IRTemp zeros
= newTemp(Ity_V128
);
33543 IRTemp srcA
= newTemp(Ity_V128
);
33544 IRTemp srcB
= newTemp(Ity_V128
);
33546 DIP("vcmpbfp%s v%d,v%d,v%d\n", (flag_rC
? ".":""),
33547 vD_addr
, vA_addr
, vB_addr
);
33549 assign( zeros
, unop(Iop_Dup32x4
, mkU32(0)) );
33551 /* Note: making use of fact that the ppc backend for compare insns
33552 return zero'd lanes if either of the corresponding arg lanes is
33555 Perhaps better to have an irop Iop_isNan32Fx4, but then we'd
33556 need this for the other compares too (vcmpeqfp etc)...
33557 Better still, tighten down the spec for compare irops.
33559 assign ( srcA
, dnorm_adj_Vector( mkexpr( vA
) ) );
33560 assign ( srcB
, dnorm_adj_Vector( mkexpr( vB
) ) );
33562 assign( gt
, unop( Iop_NotV128
,
33563 binop( Iop_CmpLE32Fx4
, mkexpr( srcA
),
33564 mkexpr( srcB
) ) ) );
33565 assign( lt
, unop( Iop_NotV128
,
33566 binop( Iop_CmpGE32Fx4
, mkexpr( srcA
),
33567 triop( Iop_Sub32Fx4
, mkU32( Irrm_NEAREST
),
33569 mkexpr( srcB
) ) ) ) );
33571 // finally, just shift gt,lt to correct position
33572 assign( vD
, binop(Iop_ShlN32x4
,
33574 binop(Iop_AndV128
, mkexpr(gt
),
33575 unop(Iop_Dup32x4
, mkU32(0x2))),
33576 binop(Iop_AndV128
, mkexpr(lt
),
33577 unop(Iop_Dup32x4
, mkU32(0x1)))),
33583 vex_printf("dis_av_fp_cmp(ppc)(opc2)\n");
33587 putVReg( vD_addr
, mkexpr(vD
) );
33590 set_AV_CR6( mkexpr(vD
), !cmp_bounds
);
33596 AltiVec Floating Point Convert/Round Instructions
33598 static Bool
dis_av_fp_convert ( UInt prefix
, UInt theInstr
)
33601 UChar opc1
= ifieldOPC(theInstr
);
33602 UChar vD_addr
= ifieldRegDS(theInstr
);
33603 UChar UIMM_5
= ifieldRegA(theInstr
);
33604 UChar vB_addr
= ifieldRegB(theInstr
);
33605 UInt opc2
= IFIELD( theInstr
, 0, 11 );
33607 IRTemp vB
= newTemp(Ity_V128
);
33608 IRTemp vScale
= newTemp(Ity_V128
);
33609 IRTemp vInvScale
= newTemp(Ity_V128
);
33611 float scale
, inv_scale
;
33613 /* There is no prefixed version of these instructions. */
33616 assign( vB
, getVReg(vB_addr
));
33618 /* scale = 2^UIMM, cast to float, reinterpreted as uint */
33619 scale
= (float)( (unsigned int) 1<<UIMM_5
);
33620 assign( vScale
, unop(Iop_Dup32x4
, mkU32( float_to_bits(scale
) )) );
33621 inv_scale
= 1/scale
;
33623 unop(Iop_Dup32x4
, mkU32( float_to_bits(inv_scale
) )) );
33626 vex_printf("dis_av_fp_convert(ppc)(instr)\n");
33631 case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156)
33632 DIP("vcfux v%d,v%d,%d\n", vD_addr
, vB_addr
, UIMM_5
);
33633 putVReg( vD_addr
, triop(Iop_Mul32Fx4
, mkU32(Irrm_NEAREST
),
33634 unop(Iop_I32UtoF32x4_DEP
, mkexpr(vB
)),
33635 mkexpr(vInvScale
)) );
33638 case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155)
33639 DIP("vcfsx v%d,v%d,%d\n", vD_addr
, vB_addr
, UIMM_5
);
33641 putVReg( vD_addr
, triop(Iop_Mul32Fx4
, mkU32(Irrm_NEAREST
),
33642 unop(Iop_I32StoF32x4_DEP
, mkexpr(vB
)),
33643 mkexpr(vInvScale
)) );
33646 case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172)
33647 DIP("vctuxs v%d,v%d,%d\n", vD_addr
, vB_addr
, UIMM_5
);
33649 unop(Iop_QF32toI32Ux4_RZ
,
33650 triop(Iop_Mul32Fx4
, mkU32(Irrm_NEAREST
),
33651 mkexpr(vB
), mkexpr(vScale
))) );
33654 case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171)
33655 DIP("vctsxs v%d,v%d,%d\n", vD_addr
, vB_addr
, UIMM_5
);
33657 unop(Iop_QF32toI32Sx4_RZ
,
33658 triop(Iop_Mul32Fx4
, mkU32(Irrm_NEAREST
),
33659 mkexpr(vB
), mkexpr(vScale
))) );
33663 break; // Fall through...
33667 vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n");
33672 case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231)
33673 DIP("vrfin v%d,v%d\n", vD_addr
, vB_addr
);
33674 putVReg( vD_addr
, unop(Iop_RoundF32x4_RN
,
33675 dnorm_adj_Vector( mkexpr( vB
) ) ) );
33678 case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233)
33679 DIP("vrfiz v%d,v%d\n", vD_addr
, vB_addr
);
33680 putVReg( vD_addr
, unop(Iop_RoundF32x4_RZ
,
33681 dnorm_adj_Vector( mkexpr( vB
) ) ) );
33684 case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232)
33685 DIP("vrfip v%d,v%d\n", vD_addr
, vB_addr
);
33686 putVReg( vD_addr
, unop(Iop_RoundF32x4_RP
,
33687 dnorm_adj_Vector( mkexpr( vB
) ) ) );
33690 case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230)
33691 DIP("vrfim v%d,v%d\n", vD_addr
, vB_addr
);
33692 putVReg( vD_addr
, unop(Iop_RoundF32x4_RM
,
33693 dnorm_adj_Vector( mkexpr(vB
) ) ) );
33697 vex_printf("dis_av_fp_convert(ppc)(opc2)\n");
33703 static Bool
dis_transactional_memory ( UInt prefix
, UInt theInstr
, UInt nextInstr
,
33704 const VexAbiInfo
* vbi
,
33705 /*OUT*/DisResult
* dres
)
33707 UInt opc2
= IFIELD( theInstr
, 1, 10 );
33709 /* There is no prefixed version of these instructions. */
33713 case 0x28E: { //tbegin.
33714 /* The current implementation is to just fail the tbegin and execute
33715 * the failure path. The failure path is assumed to be functionaly
33716 * equivalent to the transactional path with the needed data locking
33717 * to ensure correctness. The tend is just a noop and shouldn't
33718 * actually get executed.
33719 * 1) set cr0 to 0x2
33720 * 2) Initialize TFHAR to CIA+4
33721 * 3) Initialize TEXASR
33722 * 4) Initialize TFIAR (probably to CIA, ie, the address of tbegin.)
33723 * 5) Continue executing at the next instruction.
33725 UInt R
= IFIELD( theInstr
, 21, 1 );
33728 UInt failure_code
= 0; /* Forcing failure, will not be due to tabort
33731 UInt persistant
= 1; /* set persistant since we are always failing
33734 UInt nest_overflow
= 1; /* Alowed nesting depth overflow, we use this
33735 as the reason for failing the trasaction */
33736 UInt tm_exact
= 1; /* have exact address for failure */
33738 DIP("tbegin. %u\n", R
);
33740 /* Set the CR0 field to indicate the tbegin failed. Then let
33741 * the code do the branch to the failure path.
33743 * 000 || 0 Transaction initiation successful,
33744 * unnested (Transaction state of
33745 * Non-transactional prior to tbegin.)
33746 * 010 || 0 Transaction initiation successful, nested
33747 * (Transaction state of Transactional
33748 * prior to tbegin.)
33749 * 001 || 0 Transaction initiation unsuccessful,
33750 * (Transaction state of Suspended prior
33753 putCR321( 0, mkU8( 0x2 ) );
33755 tm_reason
= generate_TMreason( failure_code
, persistant
,
33756 nest_overflow
, tm_exact
);
33758 storeTMfailure( guest_CIA_curr_instr
, tm_reason
,
33759 guest_CIA_curr_instr
+4 );
33766 case 0x2AE: { //tend.
33767 /* The tend. is just a noop. Do nothing */
33768 UInt A
= IFIELD( theInstr
, 25, 1 );
33770 DIP("tend. %u\n", A
);
33774 case 0x2EE: { //tsr.
33775 /* The tsr. is just a noop. Do nothing */
33776 UInt L
= IFIELD( theInstr
, 21, 1 );
33778 DIP("tsr. %u\n", L
);
33782 case 0x2CE: { //tcheck.
33783 /* The tcheck. is just a noop. Do nothing */
33784 UInt BF
= IFIELD( theInstr
, 25, 1 );
33786 DIP("tcheck. %u\n", BF
);
33790 case 0x30E: { //tbortwc.
33791 /* The tabortwc. is just a noop. Do nothing */
33792 UInt TO
= IFIELD( theInstr
, 25, 1 );
33793 UInt RA
= IFIELD( theInstr
, 16, 5 );
33794 UInt RB
= IFIELD( theInstr
, 11, 5 );
33796 DIP("tabortwc. %u,%u,%u\n", TO
, RA
, RB
);
33800 case 0x32E: { //tbortdc.
33801 /* The tabortdc. is just a noop. Do nothing */
33802 UInt TO
= IFIELD( theInstr
, 25, 1 );
33803 UInt RA
= IFIELD( theInstr
, 16, 5 );
33804 UInt RB
= IFIELD( theInstr
, 11, 5 );
33806 DIP("tabortdc. %u,%u,%u\n", TO
, RA
, RB
);
33810 case 0x34E: { //tbortwci.
33811 /* The tabortwci. is just a noop. Do nothing */
33812 UInt TO
= IFIELD( theInstr
, 25, 1 );
33813 UInt RA
= IFIELD( theInstr
, 16, 5 );
33814 UInt SI
= IFIELD( theInstr
, 11, 5 );
33816 DIP("tabortwci. %u,%u,%u\n", TO
, RA
, SI
);
33820 case 0x36E: { //tbortdci.
33821 /* The tabortdci. is just a noop. Do nothing */
33822 UInt TO
= IFIELD( theInstr
, 25, 1 );
33823 UInt RA
= IFIELD( theInstr
, 16, 5 );
33824 UInt SI
= IFIELD( theInstr
, 11, 5 );
33826 DIP("tabortdci. %u,%u,%u\n", TO
, RA
, SI
);
33830 case 0x38E: { //tbort.
33831 /* The tabort. is just a noop. Do nothing */
33832 UInt RA
= IFIELD( theInstr
, 16, 5 );
33834 DIP("tabort. %u\n", RA
);
33838 case 0x3AE: { //treclaim.
33839 /* The treclaim. is just a noop. Do nothing */
33840 UInt RA
= IFIELD( theInstr
, 16, 5 );
33842 DIP("treclaim. %u\n", RA
);
33846 case 0x3EE: { //trechkpt.
33847 /* The trechkpt. is just a noop. Do nothing */
33848 DIP("trechkpt.\n");
33853 vex_printf("dis_transactional_memory(ppc): unrecognized instruction\n");
33861 /* The 0x3C primary opcode (VSX category) uses several different forms of
33862 * extended opcodes:
33864 * - [10:2] (IBM notation [21:29])
33865 * o XX3-form variants:
33866 * - variant 1: [10:3] (IBM notation [21:28])
33867 * - variant 2: [9:3] (IBM notation [22:28])
33868 * - variant 3: [7:3] (IBM notation [24:28])
33870 * - [10:6] (IBM notation [21:25])
33872 * The XX2-form needs bit 0 masked from the standard extended opcode
33873 * as returned by ifieldOPClo10; the XX3-form needs bits 0 and 1 masked;
33874 * and the XX4-form needs bits 0, 1, and 2 masked. Additionally, the
33875 * XX4 and XX3 (variants 2 and 3) forms need certain bits masked on the
33876 * front end since their encoding does not begin at bit 21 like the standard
33879 * The get_VSX60_opc2() function uses the vsx_insn array below to obtain the
33880 * secondary opcode for such VSX instructions.
33887 const HChar
* name
;
33890 // ATTENTION: Keep this array sorted on the opcocde!!!
33891 static struct vsx_insn vsx_xx2
[] = {
33892 { 0x14, "xsrsqrtesp" },
33893 { 0x16, "xssqrtsp" },
33895 { 0x34, "xsresp" },
33896 { 0x90, "xscvdpuxws" },
33897 { 0x92, "xsrdpi" },
33898 { 0x94, "xsrsqrtedp" },
33899 { 0x96, "xssqrtdp" },
33900 { 0xb0, "xscvdpsxws" },
33901 { 0xb2, "xsrdpiz" },
33902 { 0xb4, "xsredp" },
33903 { 0xd2, "xsrdpip" },
33904 { 0xd4, "xstsqrtdp" },
33905 { 0xd6, "xsrdpic" },
33906 { 0xf2, "xsrdpim" },
33907 { 0x112, "xvrspi" },
33908 { 0x116, "xvsqrtsp" },
33909 { 0x130, "xvcvspsxws" },
33910 { 0x132, "xvrspiz" },
33911 { 0x134, "xvresp" },
33912 { 0x148, "xxspltw" },
33913 { 0x14A, "xxextractuw" },
33914 { 0x150, "xvcvuxwsp" },
33915 { 0x152, "xvrspip" },
33916 { 0x154, "xvtsqrtsp" },
33917 { 0x156, "xvrspic" },
33918 { 0x16A, "xxinsertw" },
33919 { 0x170, "xvcvsxwsp" },
33920 { 0x172, "xvrspim" },
33921 { 0x190, "xvcvdpuxws" },
33922 { 0x192, "xvrdpi" },
33923 { 0x194, "xvrsqrtedp" },
33924 { 0x196, "xvsqrtdp" },
33925 { 0x1b0, "xvcvdpsxws" },
33926 { 0x1b2, "xvrdpiz" },
33927 { 0x1b4, "xvredp" },
33928 { 0x1d0, "xvcvuxwdp" },
33929 { 0x1d2, "xvrdpip" },
33930 { 0x1d4, "xvtsqrtdp" },
33931 { 0x1d6, "xvrdpic" },
33932 { 0x1f0, "xvcvsxwdp" },
33933 { 0x1f2, "xvrdpim" },
33934 { 0x212, "xscvdpsp" },
33935 { 0x216, "xscvdpspn" },
33936 { 0x232, "xxrsp" },
33937 { 0x250, "xscvuxdsp" },
33938 { 0x254, "xststdcsp" },
33939 { 0x270, "xscvsxdsp" },
33940 { 0x290, "xscvdpuxds" },
33941 { 0x292, "xscvspdp" },
33942 { 0x296, "xscvspdpn" },
33943 { 0x2b0, "xscvdpsxds" },
33944 { 0x2b2, "xsabsdp" },
33945 { 0x2b6, "xsxexpdp_xsxigdp" },
33946 { 0x2d0, "xscvuxddp" },
33947 { 0x2d2, "xsnabsdp" },
33948 { 0x2d4, "xststdcdp" },
33949 { 0x2e4, "xsnmsubmdp" },
33950 { 0x2f0, "xscvsxddp" },
33951 { 0x2f2, "xsnegdp" },
33952 { 0x310, "xvcvspuxds" },
33953 { 0x312, "xvcvdpsp" },
33954 { 0x330, "xvcvspsxds" },
33955 { 0x332, "xvabssp" },
33956 { 0x350, "xvcvuxdsp" },
33957 { 0x352, "xvnabssp" },
33958 { 0x370, "xvcvsxdsp" },
33959 { 0x372, "xvnegsp" },
33960 { 0x390, "xvcvdpuxds" },
33961 { 0x392, "xvcvspdp" },
33962 { 0x3b0, "xvcvdpsxds" },
33963 { 0x3b2, "xvabsdp" },
33964 { 0x3b6, "xxbr[h|w|d|q]|xvxexpdp|xvxexpsp|xvxsigdp|xvxsigsp|xvcvhpsp|xvcvsphp|xscvdphp|xscvhpdp|xvcvbf16spn|xvcvspbf16" },
33965 { 0x3d0, "xvcvuxddp" },
33966 { 0x3d2, "xvnabsdp" },
33967 { 0x3f2, "xvnegdp" }
33969 #define VSX_XX2_LEN (sizeof vsx_xx2 / sizeof *vsx_xx2)
33971 // ATTENTION: Keep this array sorted on the opcocde!!!
33972 static struct vsx_insn vsx_xx3
[] = {
33973 { 0x0, "xsaddsp" },
33974 { 0x4, "xsmaddasp" },
33975 { 0x9, "xsmaddmsp" },
33976 { 0xC, "xscmpeqdp" },
33977 { 0x20, "xssubsp" },
33978 { 0x24, "xsmaddmsp" },
33979 { 0x2C, "xscmpgtdp" },
33980 { 0x3A, "xxpermr" },
33981 { 0x40, "xsmulsp" },
33982 { 0x44, "xsmsubasp" },
33983 { 0x48, "xxmrghw" },
33984 { 0x4C, "xscmpgedp" },
33985 { 0x60, "xsdivsp" },
33986 { 0x64, "xsmsubmsp" },
33987 { 0x68, "xxperm" },
33988 { 0x80, "xsadddp" },
33989 { 0x84, "xsmaddadp" },
33990 { 0x8c, "xscmpudp" },
33991 { 0xa0, "xssubdp" },
33992 { 0xa4, "xsmaddmdp" },
33993 { 0xac, "xscmpodp" },
33994 { 0xc0, "xsmuldp" },
33995 { 0xc4, "xsmsubadp" },
33996 { 0xc8, "xxmrglw" },
33997 { 0xd4, "xstsqrtdp" },
33998 { 0xe0, "xsdivdp" },
33999 { 0xe4, "xsmsubmdp" },
34000 { 0xe8, "xxpermr" },
34001 { 0xeC, "xscmpexpdp" },
34002 { 0xf4, "xstdivdp" },
34003 { 0x100, "xvaddsp" },
34004 { 0x104, "xvmaddasp" },
34005 { 0x10C, "xvcmpeqsp" },
34006 { 0x110, "xvcvspuxws" },
34007 { 0x114, "xvrsqrtesp" },
34008 { 0x120, "xvsubsp" },
34009 { 0x124, "xvmaddmsp" },
34010 { 0x130, "xvcvspsxws" },
34011 { 0x140, "xvmulsp" },
34012 { 0x144, "xvmsubasp" },
34013 { 0x14C, "xvcmpgesp", },
34014 { 0x160, "xvdivsp" },
34015 { 0x164, "xvmsubmsp" },
34016 { 0x174, "xvtdivsp" },
34017 { 0x180, "xvadddp" },
34018 { 0x184, "xvmaddadp" },
34019 { 0x18C, "xvcmpeqdp" },
34020 { 0x1a0, "xvsubdp" },
34021 { 0x1a4, "xvmaddmdp" },
34022 { 0x1aC, "xvcmpgtdp" },
34023 { 0x1c0, "xvmuldp" },
34024 { 0x1c4, "xvmsubadp" },
34025 { 0x1cc, "xvcmpgedp" },
34026 { 0x1e0, "xvdivdp" },
34027 { 0x1e4, "xvmsubmdp" },
34028 { 0x1f4, "xvtdivdp" },
34029 { 0x200, "xsmaxcdp" },
34030 { 0x204, "xsnmaddasp" },
34031 { 0x208, "xxland" },
34032 { 0x220, "xsmincdp" },
34033 { 0x224, "xsnmaddmsp" },
34034 { 0x228, "xxlandc" },
34035 { 0x244, "xsnmsubasp" },
34036 { 0x248, "xxlor" },
34037 { 0x264, "xsnmsubmsp" },
34038 { 0x268, "xxlxor" },
34039 { 0x280, "xsmaxdp" },
34040 { 0x284, "xsnmaddadp" },
34041 { 0x288, "xxlnor" },
34042 { 0x2a0, "xsmindp" },
34043 { 0x2a4, "xsnmaddmdp" },
34044 { 0x2a8, "xxlorc" },
34045 { 0x2c0, "xscpsgndp" },
34046 { 0x2c4, "xsnmsubadp" },
34047 { 0x2c8, "xxlnand" },
34048 { 0x2e4, "xsnmsubmdp" },
34049 { 0x2e8, "xxleqv" },
34050 { 0x300, "xvmaxsp" },
34051 { 0x304, "xvnmaddasp" },
34052 { 0x320, "xvminsp" },
34053 { 0x324, "xvnmaddmsp" },
34054 { 0x340, "xvcpsgnsp" },
34055 { 0x344, "xvnmsubasp" },
34056 { 0x360, "xviexpsp" },
34057 { 0x364, "xvnmsubmsp" },
34058 { 0x380, "xvmaxdp" },
34059 { 0x384, "xvnmaddadp" },
34060 { 0x3a0, "xvmindp" },
34061 { 0x3a4, "xvnmaddmdp" },
34062 { 0x3c0, "xvcpsgndp" },
34063 { 0x3c4, "xvnmsubadp" },
34064 { 0x3e0, "xviexpdp" },
34065 { 0x3e4, "xvnmsubmdp" },
34066 { 0x3f0, "xvcvsxddp" },
34068 #define VSX_XX3_LEN (sizeof vsx_xx3 / sizeof *vsx_xx3)
34071 /* ATTENTION: These search functions assumes vsx_xx2 and vsx_xx3 arrays
34074 static Int
findVSXextOpCode_xx2(UInt opcode
)
34076 Int low
, mid
, high
;
34078 high
= VSX_XX2_LEN
- 1;
34079 while (low
<= high
) {
34080 mid
= (low
+ high
)/2;
34081 if (opcode
< vsx_xx2
[mid
].opcode
)
34083 else if (opcode
> vsx_xx2
[mid
].opcode
)
34091 static Int
findVSXextOpCode_xx3(UInt opcode
)
34093 Int low
, mid
, high
;
34095 high
= VSX_XX3_LEN
- 1;
34096 while (low
<= high
) {
34097 mid
= (low
+ high
)/2;
34098 if (opcode
< vsx_xx3
[mid
].opcode
)
34100 else if (opcode
> vsx_xx3
[mid
].opcode
)
34109 /* The full 10-bit extended opcode retrieved via ifieldOPClo10 is
34110 * passed, and we then try to match it up with one of the VSX forms
34113 static UInt
get_VSX60_opc2(UInt opc2_full
, UInt theInstr
)
34115 #define XX2_1_MASK 0x000003FF // xsiexpdp specific
34116 #define XX2_2_MASK 0x000003FE
34117 #define XX3_1_MASK 0x000003FC
34118 #define XX3_2_MASK 0x000001FC
34119 #define XX3_4_MASK 0x0000027C
34120 #define XX3_5_MASK 0x000003DC
34121 #define XX4_MASK 0x00000018
34124 UInt vsxExtOpcode
= 0;
34126 if (( ret
= findVSXextOpCode_xx2(opc2_full
& XX2_2_MASK
)) >= 0)
34127 return vsx_xx2
[ret
].opcode
;
34128 else if ((opc2_full
& XX2_1_MASK
) == 0x396 ) // xsiexpdp
34130 else if (( ret
= findVSXextOpCode_xx3(opc2_full
& XX3_1_MASK
)) >= 0)
34131 return vsx_xx3
[ret
].opcode
;
34134 /* There are only a few codes in each of these cases it is
34135 * probably faster to check for the codes then do the array lookups.
34137 vsxExtOpcode
= opc2_full
& XX3_2_MASK
;
34139 switch (vsxExtOpcode
) {
34140 case 0x10C: return vsxExtOpcode
; // xvcmpeqsp
34141 case 0x12C: return vsxExtOpcode
; // xvcmpgtsp, xvcmpgtsp.
34142 case 0x14C: return vsxExtOpcode
; // xvcmpgesp, xvcmpgesp.
34143 case 0x18C: return vsxExtOpcode
; // xvcmpeqdp, xvcmpeqdp.
34144 case 0x1AC: return vsxExtOpcode
; // xvcmpgtdp, xvcmpgtdp.
34145 case 0x1CC: return vsxExtOpcode
; // xvcmpgedp, xvcmpgedp.
34149 vsxExtOpcode
= opc2_full
& XX3_4_MASK
;
34151 switch (vsxExtOpcode
) {
34152 case 0x8: return vsxExtOpcode
; // xxsldwi
34153 case 0x28: return vsxExtOpcode
; // xxpermdi
34157 vsxExtOpcode
= opc2_full
& XX3_5_MASK
;
34159 switch (vsxExtOpcode
) {
34160 case 0x354: return vsxExtOpcode
; // xvtstdcsp
34161 case 0x3D4: return vsxExtOpcode
; // xvtstdcdp
34165 if (( opc2_full
& XX4_MASK
) == XX4_MASK
) { // xxsel
34166 vsxExtOpcode
= 0x18;
34167 return vsxExtOpcode
;
34171 vex_printf( "Error: undefined opcode 0x %x, the instruction = 0x %x\n",
34172 opc2_full
, theInstr
);
34173 vpanic( "ERROR: get_VSX60_opc2()\n" );
34177 static Bool
dis_vec_extract_insert ( UInt prefix
, UInt theInstr
)
34180 UChar VRT
= ifieldRegDS(theInstr
);
34181 UChar VRA
= ifieldRegA(theInstr
);
34182 UChar VRB
= ifieldRegB(theInstr
);
34183 UChar rC_addr
= ifieldRegC(theInstr
);
34184 UChar opc2
= toUChar( IFIELD( theInstr
, 0, 6 ) );
34185 UChar vT_addr
= VRT
+ 32;
34186 UChar vA_addr
= VRA
+ 32;
34187 UChar vB_addr
= VRB
+ 32;
34189 IRTemp vA
= newTemp(Ity_V128
);
34190 IRTemp vB
= newTemp(Ity_V128
);
34191 IRTemp rC
= newTemp(Ity_I64
);
34192 IRTemp res_tmp
= newTemp(Ity_I64
);
34193 IRTemp byte_index
= newTemp(Ity_I64
);
34194 IRTemp index0
= newTemp(Ity_I64
);
34196 UInt index_mask
= 0x1F;
34197 UInt max_index_in_src
= 31; /* src is vrA | vrB which is 32-bytes */
34199 assign( vA
, getVSReg( vA_addr
) );
34200 assign( vB
, getVSReg( vB_addr
) );
34201 assign( rC
, getIReg( rC_addr
) );
34203 /* Get index of the element to extract */
34204 assign( byte_index
, binop( Iop_And64
,
34206 mkU64( index_mask
) ) );
34210 // vextdubvlx, Vector Extract Double Unsigned Byte Left-indexed
34211 DIP("vextdubvlx v%u,v%u,v%u,%u\n", VRT
, VRA
, VRB
, rC_addr
);
34213 /* extractBytefromV256() assumes Right-index ordering */
34216 mkU64( max_index_in_src
), mkexpr( byte_index
) ) );
34217 assign( res_tmp
, extractBytefromV256( vA
, vB
, index0
) );
34221 // vextdubvrx, Vector Extract Double Unsigned Byte Right-indexed
34222 DIP("vextdubvrx v%u,v%u,v%u,%u\n", vT_addr
, vA_addr
, vB_addr
, rC_addr
);
34224 assign( res_tmp
, extractBytefromV256( vA
, vB
, byte_index
) );
34229 IRTemp index1
= newTemp(Ity_I64
);
34231 // vextduhvlx, Vector Extract Double Unsigned Half-word Left-indexed
34232 DIP("vextduhvlx v%u,v%u,v%u,%u\n",
34233 vT_addr
, vA_addr
, vB_addr
, rC_addr
);
34235 /* extractBytefromV256() assumes Right-index ordering */
34238 mkU64( max_index_in_src
), mkexpr( byte_index
) ) );
34239 assign( index1
, binop( Iop_Sub64
, mkexpr( index0
), mkU64( 1 ) ) );
34242 extractBytefromV256( vA
, vB
, index1
),
34244 extractBytefromV256( vA
, vB
, index0
),
34251 IRTemp index1
= newTemp(Ity_I64
);
34253 // vextduhvrx, Vector Extract Double Unsigned Half-word Right-indexed
34254 DIP("vextduhvrx v%u,v%u,v%u,%u\n",
34255 vT_addr
, vA_addr
, vB_addr
, rC_addr
);
34257 assign( index0
, mkexpr( byte_index
) );
34258 assign( index1
, binop( Iop_Add64
, mkU64( 1 ), mkexpr( index0
) ) );
34261 extractBytefromV256( vA
, vB
, index0
),
34263 extractBytefromV256( vA
, vB
, index1
),
34270 IRTemp index1
= newTemp(Ity_I64
);
34271 IRTemp index2
= newTemp(Ity_I64
);
34272 IRTemp index3
= newTemp(Ity_I64
);
34274 // vextduwvlx, Vector Extract Double Unsigned Word Left-indexed
34275 DIP("vextduwvlx v%u,v%u,v%u,%u\n",
34276 vT_addr
, vA_addr
, vB_addr
, rC_addr
);
34278 /* extractBytefromV256() assumes Right-index ordering */
34281 mkU64( max_index_in_src
), mkexpr( byte_index
) ) );
34282 assign( index1
, binop( Iop_Sub64
, mkexpr( index0
), mkU64( 1 ) ) );
34283 assign( index2
, binop( Iop_Sub64
, mkexpr( index1
), mkU64( 1 ) ) );
34284 assign( index3
, binop( Iop_Sub64
, mkexpr( index2
), mkU64( 1 ) ) );
34288 extractBytefromV256( vA
, vB
, index3
),
34290 extractBytefromV256( vA
, vB
, index2
),
34294 extractBytefromV256( vA
, vB
, index1
),
34297 extractBytefromV256( vA
, vB
, index0
),
34298 mkU8( 24 ) ) ) ) );
34304 IRTemp index1
= newTemp(Ity_I64
);
34305 IRTemp index2
= newTemp(Ity_I64
);
34306 IRTemp index3
= newTemp(Ity_I64
);
34308 // vextduwvrx, Vector Extract Double Unsigned Word Right-indexed
34309 DIP("vextduwvrx v%u,v%u,v%u,%u\n",
34310 vT_addr
, vA_addr
, vB_addr
, rC_addr
);
34312 assign( index0
, mkexpr( byte_index
) );
34313 assign( index1
, binop( Iop_Add64
, mkexpr( index0
), mkU64( 1 ) ) );
34314 assign( index2
, binop( Iop_Add64
, mkexpr( index1
), mkU64( 1 ) ) );
34315 assign( index3
, binop( Iop_Add64
, mkexpr( index2
), mkU64( 1 ) ) );
34319 extractBytefromV256( vA
, vB
, index0
),
34321 extractBytefromV256( vA
, vB
, index1
),
34325 extractBytefromV256( vA
, vB
, index2
),
34328 extractBytefromV256( vA
, vB
, index3
),
34329 mkU8( 24 ) ) ) ) );
34334 IRTemp index1
= newTemp(Ity_I64
);
34335 IRTemp index2
= newTemp(Ity_I64
);
34336 IRTemp index3
= newTemp(Ity_I64
);
34337 IRTemp index4
= newTemp(Ity_I64
);
34338 IRTemp index5
= newTemp(Ity_I64
);
34339 IRTemp index6
= newTemp(Ity_I64
);
34340 IRTemp index7
= newTemp(Ity_I64
);
34342 // vextddvlx, Vector Extract Double Double-Word Left-indexed
34343 DIP("vextddvlx v%u,v%u,v%u,%u\n",
34344 vT_addr
, vA_addr
, vB_addr
, rC_addr
);
34346 /* extractBytefromV256() assumes Right-index ordering */
34349 mkU64( max_index_in_src
), mkexpr( byte_index
) ) );
34350 assign( index1
, binop( Iop_Sub64
, mkexpr( index0
), mkU64( 1 ) ) );
34351 assign( index2
, binop( Iop_Sub64
, mkexpr( index1
), mkU64( 1 ) ) );
34352 assign( index3
, binop( Iop_Sub64
, mkexpr( index2
), mkU64( 1 ) ) );
34353 assign( index4
, binop( Iop_Sub64
, mkexpr( index3
), mkU64( 1 ) ) );
34354 assign( index5
, binop( Iop_Sub64
, mkexpr( index4
), mkU64( 1 ) ) );
34355 assign( index6
, binop( Iop_Sub64
, mkexpr( index5
), mkU64( 1 ) ) );
34356 assign( index7
, binop( Iop_Sub64
, mkexpr( index6
), mkU64( 1 ) ) );
34361 extractBytefromV256( vA
, vB
, index7
),
34363 extractBytefromV256( vA
, vB
,
34368 extractBytefromV256( vA
, vB
,
34372 extractBytefromV256( vA
, vB
,
34378 extractBytefromV256( vA
, vB
,
34382 extractBytefromV256( vA
, vB
,
34387 extractBytefromV256( vA
, vB
,
34391 extractBytefromV256( vA
, vB
,
34393 mkU8( 56 ) ) ) ) ) );
34399 IRTemp index1
= newTemp(Ity_I64
);
34400 IRTemp index2
= newTemp(Ity_I64
);
34401 IRTemp index3
= newTemp(Ity_I64
);
34402 IRTemp index4
= newTemp(Ity_I64
);
34403 IRTemp index5
= newTemp(Ity_I64
);
34404 IRTemp index6
= newTemp(Ity_I64
);
34405 IRTemp index7
= newTemp(Ity_I64
);
34407 // vextddvrx, Vector Extract Double Doubleword Right-indexed
34408 DIP("vextddvrx v%u,v%u,v%u,%u\n",
34409 vT_addr
, vA_addr
, vB_addr
, rC_addr
);
34411 assign( index0
, mkexpr( byte_index
) );
34412 assign( index1
, binop( Iop_Add64
, mkexpr( index0
), mkU64( 1 ) ) );
34413 assign( index2
, binop( Iop_Add64
, mkexpr( index1
), mkU64( 1 ) ) );
34414 assign( index3
, binop( Iop_Add64
, mkexpr( index2
), mkU64( 1 ) ) );
34415 assign( index4
, binop( Iop_Add64
, mkexpr( index3
), mkU64( 1 ) ) );
34416 assign( index5
, binop( Iop_Add64
, mkexpr( index4
), mkU64( 1 ) ) );
34417 assign( index6
, binop( Iop_Add64
, mkexpr( index5
), mkU64( 1 ) ) );
34418 assign( index7
, binop( Iop_Add64
, mkexpr( index6
), mkU64( 1 ) ) );
34423 extractBytefromV256( vA
, vB
, index0
),
34425 extractBytefromV256( vA
, vB
,
34430 extractBytefromV256( vA
, vB
,
34434 extractBytefromV256( vA
, vB
,
34440 extractBytefromV256( vA
, vB
,
34444 extractBytefromV256( vA
, vB
,
34449 extractBytefromV256( vA
, vB
,
34453 extractBytefromV256( vA
, vB
,
34455 mkU8( 56 ) ) ) ) ) );
34460 vex_printf("dis_vec_extract_insert\n");
34464 putVSReg( vT_addr
, binop( Iop_64HLtoV128
,
34471 static Bool
dis_string_isolate ( UInt prefix
, UInt theInstr
)
34473 UChar vT_addr
= ifieldRegDS(theInstr
);
34474 UChar vA_addr
= ifieldRegA(theInstr
);
34475 UChar vB_addr
= ifieldRegB(theInstr
);
34477 IRTemp vT
= newTemp(Ity_V128
);
34478 IRTemp index
= newTemp(Ity_I32
);
34479 IRTemp sh_index
= newTemp(Ity_I32
);
34480 IRTemp mask
= newTemp(Ity_V128
);
34481 IRTemp cc
= newTemp(Ity_I32
);
34484 UInt Rc
= IFIELD( theInstr
, (31-21), 1 );
34486 UInt opc2
= IFIELD( theInstr
, 0, 11 );
34487 Int inst_sel
= IFIELD(theInstr
, 16, 5);
34488 Int dir
= 0; // 0 - index from left, 1 - index from right
34489 IROp shift_first
, shift_second
;
34491 assign( mask
, binop( Iop_64HLtoV128
,
34492 mkU64( 0xFFFFFFFFFFFFFFFF ),
34493 mkU64( 0xFFFFFFFFFFFFFFFF ) ) );
34498 else if (opc2
== 0x1CD)
34502 case 0x0: // vstribl[.]
34503 case 0x1: // vstribr[.]
34505 IRTemp vB
= newTemp(Ity_V128
);
34507 if (inst_sel
== 0) {
34508 DIP("vstribl%s v%u,v%u\n", Rc
? ".":"", vT_addr
, vB_addr
);
34509 shift_first
= Iop_ShlV128
;
34513 DIP("vstribr%s v%u,v%u\n", Rc
? ".":"", vT_addr
, vB_addr
);
34514 shift_first
= Iop_ShrV128
;
34518 /* Get index of match of first byte from the left that matches zero.
34519 Index will be equal to max elements in vector if there is no match.
34520 If index is equal to the max, which is 16 in this case, set index
34521 to zero so the data mask will select all of the bits.
34523 assign( vB
, getVReg( vB_addr
) );
34524 assign( index
, unop( Iop_8Uto32
,
34525 locate_vector_ele_eq( vB
, mkU64( 0 ), dir
,
34530 binop( Iop_CmpLE32U
,
34535 mkexpr( index
) ) ) );
34537 /* Shift mask to select the bytes up to the match with zero */
34538 assign( vT
, binop( Iop_AndV128
,
34539 // binop( Iop_ShlV128,
34540 binop( shift_first
,
34545 mkexpr( sh_index
) ) ) ),
34549 /* The returned index was between 1 and 16 if a null was found. */
34550 assign( cc
, binop( Iop_Shl32
,
34552 binop( Iop_CmpLE32U
,
34553 mkexpr( index
), mkU32( 16 ) ) ),
34558 case 0x2: // vstrihl[.]
34559 case 0x3: // vstrihr[.]
34561 IRTemp vB
= newTemp(Ity_V128
);
34563 if (inst_sel
== 2) {
34564 DIP("vstrihl%s v%u,v%u\n", Rc
? ".":"", vT_addr
, vB_addr
);
34565 shift_first
= Iop_ShlV128
;
34569 DIP("vstrihr%s v%u,v%u\n", Rc
? ".":"", vT_addr
, vB_addr
);
34570 shift_first
= Iop_ShrV128
;
34574 assign( vB
, getVReg( vB_addr
) );
34575 assign( index
, unop( Iop_8Uto32
,
34576 locate_vector_ele_eq( vB
, mkU64( 0 ), dir
,
34578 /* Get index of match of first half word from specified direction
34579 that matches zero. Index will be equal to max elements in vector
34580 if there is no match. If index is equal to the max, which is 8
34581 in this case, set index to zero so the data mask will select all
34587 binop( Iop_CmpLE32U
,
34592 mkexpr( index
) ) ) );
34594 /* Shift mask left to select the bytes up to the match with zero */
34595 assign( vT
, binop( Iop_AndV128
,
34596 // binop( Iop_ShlV128,
34597 binop( shift_first
,
34602 mkexpr( sh_index
) ) ) ),
34606 /* The returned index was between 1 and 16 if a null was found. */
34607 assign( cc
, binop( Iop_Shl32
,
34609 binop( Iop_CmpLE32U
,
34610 mkexpr( index
), mkU32( 8 ) ) ),
34615 case 0x18D: // vclrlb
34616 case 0x1CD: // vclrrb
34618 IRTemp rB
= newTemp(Ity_I64
);
34619 IRTemp vA
= newTemp(Ity_V128
);
34620 IRTemp shift
= newTemp(Ity_I8
);
34621 IRTemp clear_result
= newTemp(Ity_I64
);
34623 /* Note vB_addr actually refers to a GPR in this inst. */
34624 if (inst_sel
== 0x18D) {
34625 DIP("vclrlb v%u,v%u,%u\n", vT_addr
, vA_addr
, vB_addr
);
34626 shift_first
= Iop_ShlV128
;
34627 shift_second
= Iop_ShrV128
;
34630 DIP("vclrrb v%u,v%u,%u\n", vT_addr
, vA_addr
, vB_addr
);
34631 shift_first
= Iop_ShrV128
;
34632 shift_second
= Iop_ShlV128
;
34635 assign( vA
, getVReg( vA_addr
) );
34636 assign( rB
, getIReg( vB_addr
) );
34638 /* Clear left 16-rB bytes, if rb > 16, set shift to 0
34639 and clear_result to all 1's. */
34648 mkexpr( rB
) ) ) ),
34651 binop( Iop_CmpLT32S
,
34654 mkexpr( rB
) ) ) ) )
34657 /* Clear all bits if rB > 16 */
34658 assign( clear_result
,
34661 binop( Iop_CmpLE32S
,
34662 unop( Iop_8Uto32
, mkexpr( shift
) ),
34665 binop( Iop_CmpLT32S
,
34668 mkexpr( rB
) ) ) ) ) );
34670 /* Clear bits by shifting mask, then shifting back by index. If
34671 * shift is >= 127, need to mask out result as underlying shift only
34672 * supports shifts up to 127 bits.
34675 binop( Iop_AndV128
,
34676 binop( Iop_AndV128
,
34677 binop( shift_second
,
34678 binop( shift_first
,
34683 binop( Iop_64HLtoV128
, mkexpr( clear_result
),
34684 mkexpr( clear_result
) ) ) );
34689 vex_printf("dis_string_isolate(isnt_sel = %d)\n", inst_sel
);
34694 putGST_field( PPC_GST_CR
, mkexpr( cc
), cc_field
);
34696 putVReg( vT_addr
, mkexpr( vT
) );
34700 static Bool
dis_test_LSB_by_bit ( UInt prefix
, UInt theInstr
)
34702 #define MAX_FIELDS 16
34703 UChar vB_addr
= ifieldRegXB(theInstr
);
34704 IRTemp vB
= newTemp( Ity_V128
);
34705 UChar opc1
= ifieldOPC(theInstr
);
34706 UInt opc2
= IFIELD(theInstr
, (31-29), 9); // bits[21:29]
34707 UInt inst_select
= IFIELD( theInstr
, (31-15), 5); // bits[11:15]
34708 UInt BF
= IFIELD( theInstr
, (31-8), 3); // bits[6:8]
34710 IRTemp all_true
[MAX_FIELDS
+1];
34711 IRTemp all_false
[MAX_FIELDS
+1];
34712 IRTemp tmp128
[MAX_FIELDS
];
34713 IRTemp cc
= newTemp(Ity_I32
);
34715 if (!((opc1
== 0x3C) && (opc2
== 0x1DB) && (inst_select
== 2)))
34718 DIP("xvtlsbb %u,v%u\n", BF
, vB_addr
);
34720 assign( vB
, getVSReg( vB_addr
) );
34721 all_true
[0] = newTemp( Ity_I1
);
34722 all_false
[0] = newTemp( Ity_I1
);
34723 assign( all_true
[0], mkU1( 1 ) );
34724 assign( all_false
[0], mkU1( 1 ) );
34726 for (i
= 0; i
< MAX_FIELDS
; i
++) {
34727 tmp128
[i
] = newTemp( Ity_I64
);
34728 all_true
[i
+1] = newTemp( Ity_I1
);
34729 all_false
[i
+1] = newTemp( Ity_I1
);
34731 assign( tmp128
[i
], binop( Iop_And64
,
34733 unop( Iop_V128to64
,
34734 binop( Iop_ShrV128
,
34735 mkexpr( vB
), mkU8( i
*8 ) ) ) ) );
34736 assign( all_true
[i
+1], mkAND1 ( mkexpr( all_true
[i
] ),
34737 binop( Iop_CmpEQ64
,
34739 mkexpr( tmp128
[i
] ) ) ) );
34740 assign( all_false
[i
+1], mkAND1 ( mkexpr( all_false
[i
] ),
34741 binop( Iop_CmpEQ64
,
34743 mkexpr( tmp128
[i
] ) ) ) );
34746 assign( cc
, binop( Iop_Or32
,
34749 mkexpr( all_true
[MAX_FIELDS
] ) ),
34753 mkexpr( all_false
[MAX_FIELDS
] ) ),
34756 putGST_field( PPC_GST_CR
, mkexpr( cc
), BF
);
34761 static Bool
dis_vsx_accumulator_prefix ( UInt prefix
, UInt theInstr
,
34762 const VexAbiInfo
* vbi
,
34763 Bool ACC_mapped_on_VSR
)
34765 UChar opc1
= ifieldOPC(theInstr
);
34766 UChar opc2
= IFIELD( theInstr
, 1, 10);
34767 UInt bit11_15
= IFIELD( theInstr
, (31-15), 5);
34768 UChar AT
= ifieldAT(theInstr
);
34769 Bool is_prefix
= prefix_instruction( prefix
);
34770 UChar rA_addr
= ifieldRegA( theInstr
);
34771 UChar rB_addr
= ifieldRegB( theInstr
);
34773 /* Note, not all of the instructions supported by this function are
34774 prefix instructions. */
34775 if ((opc1
== 0x3b)&& !is_prefix
) {
34776 // Note these are not prefix instructions
34777 UInt XO
= IFIELD( theInstr
, 3, 8);
34778 UInt inst_prefix
= 0;
34780 /* Note vsx_matrix_4bit_ger writes result to ACC register file. */
34783 DIP("xvi4ger8 %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
34784 vsx_matrix_ger( vbi
, MATRIX_4BIT_INT_GER
,
34785 getVSReg( rA_addr
), getVSReg( rB_addr
),
34786 AT
, ( ( inst_prefix
<< 8 ) | XO
),
34787 ACC_mapped_on_VSR
);
34790 DIP("xvi4ger8pp %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
34791 vsx_matrix_ger( vbi
, MATRIX_4BIT_INT_GER
,
34792 getVSReg( rA_addr
), getVSReg( rB_addr
),
34793 AT
, ( ( inst_prefix
<< 8 ) | XO
),
34794 ACC_mapped_on_VSR
);
34797 DIP("xvi8ger4 %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
34798 vsx_matrix_ger( vbi
, MATRIX_8BIT_INT_GER
,
34799 getVSReg( rA_addr
), getVSReg( rB_addr
),
34800 AT
, ( ( inst_prefix
<< 8 ) | XO
),
34801 ACC_mapped_on_VSR
);
34804 DIP("xvi8ger4pp %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
34805 vsx_matrix_ger( vbi
, MATRIX_8BIT_INT_GER
,
34806 getVSReg( rA_addr
), getVSReg( rB_addr
),
34807 AT
, ( ( inst_prefix
<< 8 ) | XO
),
34808 ACC_mapped_on_VSR
);
34811 DIP("xvi8ger4spp %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
34812 vsx_matrix_ger( vbi
, MATRIX_8BIT_INT_GER
,
34813 getVSReg( rA_addr
), getVSReg( rB_addr
),
34814 AT
, ( ( inst_prefix
<< 8 ) | XO
),
34815 ACC_mapped_on_VSR
);
34818 DIP("xvi16ger2s %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
34819 vsx_matrix_ger( vbi
, MATRIX_16BIT_INT_GER
,
34820 getVSReg( rA_addr
), getVSReg( rB_addr
),
34821 AT
, ( ( inst_prefix
<< 8 ) | XO
),
34822 ACC_mapped_on_VSR
);
34825 DIP("xvi16ger2pps %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
34826 vsx_matrix_ger( vbi
, MATRIX_16BIT_INT_GER
,
34827 getVSReg( rA_addr
), getVSReg( rB_addr
),
34828 AT
, ( ( inst_prefix
<< 8 ) | XO
),
34829 ACC_mapped_on_VSR
);
34832 DIP("xvi16ger2 %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
34833 vsx_matrix_ger( vbi
, MATRIX_16BIT_INT_GER
,
34834 getVSReg( rA_addr
), getVSReg( rB_addr
),
34835 AT
, ( ( inst_prefix
<< 8 ) | XO
),
34836 ACC_mapped_on_VSR
);
34839 DIP("xvi16ger2pp %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
34840 vsx_matrix_ger( vbi
, MATRIX_16BIT_INT_GER
,
34841 getVSReg( rA_addr
), getVSReg( rB_addr
),
34842 AT
, ( ( inst_prefix
<< 8 ) | XO
),
34843 ACC_mapped_on_VSR
);
34847 DIP("xvf16ger2 %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
34848 vsx_matrix_ger( vbi
, MATRIX_16BIT_FLOAT_GER
,
34849 getVSReg( rA_addr
),
34850 getVSReg( rB_addr
), AT
,
34851 ( ( inst_prefix
<< 8 ) | XO
),
34852 ACC_mapped_on_VSR
);
34855 DIP("xvf16ger2pp %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
34856 vsx_matrix_ger( vbi
, MATRIX_16BIT_FLOAT_GER
,
34857 getVSReg( rA_addr
),
34858 getVSReg( rB_addr
), AT
,
34859 ( ( inst_prefix
<< 8 ) | XO
),
34860 ACC_mapped_on_VSR
);
34863 DIP("xvf16ger2pn %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
34864 vsx_matrix_ger( vbi
, MATRIX_16BIT_FLOAT_GER
,
34865 getVSReg( rA_addr
),
34866 getVSReg( rB_addr
), AT
,
34867 ( ( inst_prefix
<< 8 ) | XO
),
34868 ACC_mapped_on_VSR
);
34871 DIP("xvf16ger2np %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
34872 vsx_matrix_ger( vbi
, MATRIX_16BIT_FLOAT_GER
,
34873 getVSReg( rA_addr
),
34874 getVSReg( rB_addr
), AT
,
34875 ( ( inst_prefix
<< 8 ) | XO
),
34876 ACC_mapped_on_VSR
);
34879 DIP("xvf16ger2nn %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
34880 vsx_matrix_ger( vbi
, MATRIX_16BIT_FLOAT_GER
,
34881 getVSReg( rA_addr
),
34882 getVSReg( rB_addr
), AT
,
34883 ( ( inst_prefix
<< 8 ) | XO
),
34884 ACC_mapped_on_VSR
);
34887 DIP("xvbf16ger2 %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
34888 vsx_matrix_ger( vbi
, MATRIX_16BIT_FLOAT_GER
,
34889 getVSReg( rA_addr
),
34890 getVSReg( rB_addr
), AT
,
34891 ( ( inst_prefix
<< 8 ) | XO
),
34892 ACC_mapped_on_VSR
);
34895 DIP("xvbf16ger2pp %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
34896 vsx_matrix_ger( vbi
, MATRIX_16BIT_FLOAT_GER
,
34897 getVSReg( rA_addr
),
34898 getVSReg( rB_addr
), AT
,
34899 ( ( inst_prefix
<< 8 ) | XO
),
34900 ACC_mapped_on_VSR
);
34903 DIP("xvbf16ger2pn %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
34904 vsx_matrix_ger( vbi
, MATRIX_16BIT_FLOAT_GER
,
34905 getVSReg( rA_addr
),
34906 getVSReg( rB_addr
), AT
,
34907 ( ( inst_prefix
<< 8 ) | XO
),
34908 ACC_mapped_on_VSR
);
34911 DIP("xvbf16ger2np %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
34912 vsx_matrix_ger( vbi
, MATRIX_16BIT_FLOAT_GER
,
34913 getVSReg( rA_addr
),
34914 getVSReg( rB_addr
), AT
,
34915 ( ( inst_prefix
<< 8 ) | XO
),
34916 ACC_mapped_on_VSR
);
34919 DIP("xvbf16ger2nn %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
34920 vsx_matrix_ger( vbi
, MATRIX_16BIT_FLOAT_GER
,
34921 getVSReg( rA_addr
),
34922 getVSReg( rB_addr
), AT
,
34923 ( ( inst_prefix
<< 8 ) | XO
),
34924 ACC_mapped_on_VSR
);
34927 DIP("xvf32ger %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
34928 vsx_matrix_ger( vbi
, MATRIX_32BIT_FLOAT_GER
,
34929 getVSReg( rA_addr
),
34930 getVSReg( rB_addr
), AT
,
34931 ( ( inst_prefix
<< 8 ) | XO
),
34932 ACC_mapped_on_VSR
);
34935 DIP("xvf32gerpp %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
34936 vsx_matrix_ger( vbi
, MATRIX_32BIT_FLOAT_GER
,
34937 getVSReg( rA_addr
),
34938 getVSReg( rB_addr
), AT
,
34939 ( ( inst_prefix
<< 8 ) | XO
),
34940 ACC_mapped_on_VSR
);
34943 DIP("xvf32gerpn %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
34944 vsx_matrix_ger( vbi
, MATRIX_32BIT_FLOAT_GER
,
34945 getVSReg( rA_addr
),
34946 getVSReg( rB_addr
), AT
,
34947 ( ( inst_prefix
<< 8 ) | XO
),
34948 ACC_mapped_on_VSR
);
34951 DIP("xvf32gernp %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
34952 vsx_matrix_ger( vbi
, MATRIX_32BIT_FLOAT_GER
,
34953 getVSReg( rA_addr
),
34954 getVSReg( rB_addr
), AT
,
34955 ( ( inst_prefix
<< 8 ) | XO
),
34956 ACC_mapped_on_VSR
);
34959 DIP("xvf32gernn %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
34960 vsx_matrix_ger( vbi
, MATRIX_32BIT_FLOAT_GER
,
34961 getVSReg( rA_addr
),
34962 getVSReg( rB_addr
), AT
,
34963 ( ( inst_prefix
<< 8 ) | XO
),
34964 ACC_mapped_on_VSR
);
34967 DIP("xvf64ger %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
34968 vsx_matrix_64bit_float_ger( vbi
, getVSReg( rA_addr
),
34969 getVSReg( rA_addr
+1 ),
34970 getVSReg( rB_addr
), AT
,
34971 ( ( inst_prefix
<< 8 ) | XO
),
34972 ACC_mapped_on_VSR
);
34975 DIP("xvfd642gerpp %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
34976 vsx_matrix_64bit_float_ger( vbi
, getVSReg( rA_addr
),
34977 getVSReg( rA_addr
+1 ),
34978 getVSReg( rB_addr
), AT
,
34979 ( ( inst_prefix
<< 8 ) | XO
),
34980 ACC_mapped_on_VSR
);
34983 DIP("xvf64gerpn %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
34984 vsx_matrix_64bit_float_ger( vbi
, getVSReg( rA_addr
),
34985 getVSReg( rA_addr
+1 ),
34986 getVSReg( rB_addr
), AT
,
34987 ( ( inst_prefix
<< 8 ) | XO
),
34988 ACC_mapped_on_VSR
);
34991 DIP("xvf64gernp %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
34992 vsx_matrix_64bit_float_ger( vbi
, getVSReg( rA_addr
),
34993 getVSReg( rA_addr
+1 ),
34994 getVSReg( rB_addr
), AT
,
34995 ( ( inst_prefix
<< 8 ) | XO
),
34996 ACC_mapped_on_VSR
);
34999 DIP("xvf64gernn %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
35000 vsx_matrix_64bit_float_ger( vbi
, getVSReg( rA_addr
),
35001 getVSReg( rA_addr
+1 ),
35002 getVSReg( rB_addr
), AT
,
35003 ( ( inst_prefix
<< 8 ) | XO
),
35004 ACC_mapped_on_VSR
);
35007 vex_printf("ERROR, dis_vsx_accumulator_prefix, Unknown X0 = 0x%x value.\n", XO
);
35011 } else if ((opc1
== 0x3b) && prefix
) {
35012 // Note these are prefix instructions
35013 UInt XO
= IFIELD( theInstr
, 3, 8);
35014 UInt PMSK
, XMSK
, YMSK
, MASKS
;
35015 UInt inst_prefix
= 0x1;
35016 MASKS
= IFIELD( prefix
, 0, 16);
35020 PMSK
= IFIELD( prefix
, 8, 8);
35021 XMSK
= IFIELD( prefix
, 4, 4);
35022 YMSK
= IFIELD( prefix
, 0, 4);
35024 DIP("pmxvi4ger8 %u,r%u, r%u,%u,%u,%u\n",
35025 AT
, rA_addr
, rB_addr
, XMSK
, YMSK
, PMSK
);
35026 vsx_matrix_ger( vbi
, MATRIX_4BIT_INT_GER
,
35027 getVSReg( rA_addr
), getVSReg( rB_addr
),
35029 ( (MASKS
<< 9 ) | ( inst_prefix
<< 8 ) | XO
),
35030 ACC_mapped_on_VSR
);
35033 PMSK
= IFIELD( prefix
, 8, 8);
35034 XMSK
= IFIELD( prefix
, 4, 4);
35035 YMSK
= IFIELD( prefix
, 0, 4);
35036 DIP("pmxvi4ger8pp %u,r%u, r%u,%u,%u,%u\n",
35037 AT
, rA_addr
, rB_addr
, XMSK
, YMSK
, PMSK
);
35038 vsx_matrix_ger( vbi
, MATRIX_4BIT_INT_GER
,
35039 getVSReg( rA_addr
), getVSReg( rB_addr
),
35041 ( (MASKS
<< 9 ) | ( inst_prefix
<< 8 ) | XO
),
35042 ACC_mapped_on_VSR
);
35045 PMSK
= IFIELD( prefix
, 12, 4);
35046 XMSK
= IFIELD( prefix
, 4, 4);
35047 YMSK
= IFIELD( prefix
, 0, 4);
35048 DIP("pmxvi8ger4 %u,r%u, r%u,%u,%u,%u\n",
35049 AT
, rA_addr
, rB_addr
, XMSK
, YMSK
, PMSK
);
35050 vsx_matrix_ger( vbi
, MATRIX_8BIT_INT_GER
,
35051 getVSReg( rA_addr
), getVSReg( rB_addr
),
35053 ( (MASKS
<< 9 ) | ( inst_prefix
<< 8 ) | XO
),
35054 ACC_mapped_on_VSR
);
35057 PMSK
= IFIELD( prefix
, 12, 4);
35058 XMSK
= IFIELD( prefix
, 4, 4);
35059 YMSK
= IFIELD( prefix
, 0, 4);
35060 DIP("pmxvi8ger4pp %u,r%u, r%u,%u,%u,%u\n",
35061 AT
, rA_addr
, rB_addr
, XMSK
, YMSK
, PMSK
);
35062 vsx_matrix_ger( vbi
, MATRIX_8BIT_INT_GER
,
35063 getVSReg( rA_addr
), getVSReg( rB_addr
),
35065 ( (MASKS
<< 9 ) | ( inst_prefix
<< 8 ) | XO
),
35066 ACC_mapped_on_VSR
);
35069 PMSK
= IFIELD( prefix
, 12, 4);
35070 XMSK
= IFIELD( prefix
, 4, 4);
35071 YMSK
= IFIELD( prefix
, 0, 4);
35072 DIP("pmxvi8ger4spp %u,r%u, r%u,%u,%u,%u\n",
35073 AT
, rA_addr
, rB_addr
, XMSK
, YMSK
, PMSK
);
35074 vsx_matrix_ger( vbi
, MATRIX_8BIT_INT_GER
,
35075 getVSReg( rA_addr
), getVSReg( rB_addr
),
35077 ( (MASKS
<< 9 ) | ( inst_prefix
<< 8 ) | XO
),
35078 ACC_mapped_on_VSR
);
35081 PMSK
= IFIELD( prefix
, 12, 4);
35082 XMSK
= IFIELD( prefix
, 4, 4);
35083 YMSK
= IFIELD( prefix
, 0, 4);
35084 DIP("pmxvi16ger2 %u,r%u, r%u,%u,%u,%u\n",
35085 AT
, rA_addr
, rB_addr
, XMSK
, YMSK
, PMSK
);
35086 vsx_matrix_ger( vbi
, MATRIX_16BIT_INT_GER
,
35087 getVSReg( rA_addr
), getVSReg( rB_addr
),
35089 ( (MASKS
<< 9 ) | ( inst_prefix
<< 8 ) | XO
),
35090 ACC_mapped_on_VSR
);
35093 PMSK
= IFIELD( prefix
, 12, 4);
35094 XMSK
= IFIELD( prefix
, 4, 4);
35095 YMSK
= IFIELD( prefix
, 0, 4);
35096 DIP("pmxvi16ger2pp %u,r%u, r%u,%u,%u,%u\n",
35097 AT
, rA_addr
, rB_addr
, XMSK
, YMSK
, PMSK
);
35098 vsx_matrix_ger( vbi
, MATRIX_16BIT_INT_GER
,
35099 getVSReg( rA_addr
), getVSReg( rB_addr
),
35101 ( (MASKS
<< 9 ) | ( inst_prefix
<< 8 ) | XO
),
35102 ACC_mapped_on_VSR
);
35105 PMSK
= IFIELD( prefix
, 14, 2);
35106 XMSK
= IFIELD( prefix
, 4, 4);
35107 YMSK
= IFIELD( prefix
, 0, 4);
35108 DIP("pmxvi16ger2s %u,r%u, r%u,%u,%u,%u\n",
35109 AT
, rA_addr
, rB_addr
, XMSK
, YMSK
, PMSK
);
35110 vsx_matrix_ger( vbi
, MATRIX_16BIT_INT_GER
,
35111 getVSReg( rA_addr
), getVSReg( rB_addr
),
35113 ( (MASKS
<< 9 ) | ( inst_prefix
<< 8 ) | XO
),
35114 ACC_mapped_on_VSR
);
35117 PMSK
= IFIELD( prefix
, 14, 2);
35118 XMSK
= IFIELD( prefix
, 4, 4);
35119 YMSK
= IFIELD( prefix
, 0, 4);
35120 DIP("pmxvi16ger2pps %u,r%u, r%u,%u,%u,%u\n",
35121 AT
, rA_addr
, rB_addr
, XMSK
, YMSK
, PMSK
);
35122 vsx_matrix_ger( vbi
, MATRIX_16BIT_INT_GER
,
35123 getVSReg( rA_addr
), getVSReg( rB_addr
),
35125 ( (MASKS
<< 9 ) | ( inst_prefix
<< 8 ) | XO
),
35126 ACC_mapped_on_VSR
);
35129 PMSK
= IFIELD( prefix
, 14, 2);
35130 XMSK
= IFIELD( prefix
, 4, 4);
35131 YMSK
= IFIELD( prefix
, 0, 4);
35132 DIP("pmxvbf16ger2 %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
35133 vsx_matrix_ger( vbi
, MATRIX_16BIT_FLOAT_GER
,
35134 getVSReg( rA_addr
),
35135 getVSReg( rB_addr
),
35136 AT
, ( (MASKS
<< 9 )
35137 | ( inst_prefix
<< 8 ) | XO
),
35138 ACC_mapped_on_VSR
);
35141 PMSK
= IFIELD( prefix
, 14, 2);
35142 XMSK
= IFIELD( prefix
, 4, 4);
35143 YMSK
= IFIELD( prefix
, 0, 4);
35144 DIP("pmxvbf16ger2pp %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
35145 vsx_matrix_ger( vbi
, MATRIX_16BIT_FLOAT_GER
,
35146 getVSReg( rA_addr
),
35147 getVSReg( rB_addr
),
35148 AT
, ( (MASKS
<< 9 )
35149 | ( inst_prefix
<< 8 ) | XO
),
35150 ACC_mapped_on_VSR
);
35153 PMSK
= IFIELD( prefix
, 14, 2);
35154 XMSK
= IFIELD( prefix
, 4, 4);
35155 YMSK
= IFIELD( prefix
, 0, 4);
35156 DIP("pmxvbf16ger2pn %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
35157 vsx_matrix_ger( vbi
, MATRIX_16BIT_FLOAT_GER
,
35158 getVSReg( rA_addr
),
35159 getVSReg( rB_addr
),
35160 AT
, ( (MASKS
<< 9 )
35161 | ( inst_prefix
<< 8 ) | XO
),
35162 ACC_mapped_on_VSR
);
35165 PMSK
= IFIELD( prefix
, 14, 2);
35166 XMSK
= IFIELD( prefix
, 4, 4);
35167 YMSK
= IFIELD( prefix
, 0, 4);
35168 DIP("pmxvbf16ger2np %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
35169 vsx_matrix_ger( vbi
, MATRIX_16BIT_FLOAT_GER
,
35170 getVSReg( rA_addr
),
35171 getVSReg( rB_addr
),
35172 AT
, ( (MASKS
<< 9 )
35173 | ( inst_prefix
<< 8 ) | XO
),
35174 ACC_mapped_on_VSR
);
35177 PMSK
= IFIELD( prefix
, 14, 2);
35178 XMSK
= IFIELD( prefix
, 4, 4);
35179 YMSK
= IFIELD( prefix
, 0, 4);
35180 DIP("pmxvbf16ger2nn %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
35181 vsx_matrix_ger( vbi
, MATRIX_16BIT_FLOAT_GER
,
35182 getVSReg( rA_addr
),
35183 getVSReg( rB_addr
),
35184 AT
, ( (MASKS
<< 9 )
35185 | ( inst_prefix
<< 8 ) | XO
),
35186 ACC_mapped_on_VSR
);
35189 PMSK
= IFIELD( prefix
, 14, 2);
35190 XMSK
= IFIELD( prefix
, 4, 4);
35191 YMSK
= IFIELD( prefix
, 0, 4);
35192 DIP("pmxvf16ger2 %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
35193 vsx_matrix_ger( vbi
, MATRIX_16BIT_FLOAT_GER
,
35194 getVSReg( rA_addr
),
35195 getVSReg( rB_addr
),
35196 AT
, ( (MASKS
<< 9 )
35197 | ( inst_prefix
<< 8 ) | XO
),
35198 ACC_mapped_on_VSR
);
35201 PMSK
= IFIELD( prefix
, 14, 2);
35202 XMSK
= IFIELD( prefix
, 4, 4);
35203 YMSK
= IFIELD( prefix
, 0, 4);
35204 DIP("pmxvf16ger2pp %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
35205 vsx_matrix_ger( vbi
, MATRIX_16BIT_FLOAT_GER
,
35206 getVSReg( rA_addr
),
35207 getVSReg( rB_addr
),
35208 AT
, ( (MASKS
<< 9 )
35209 | ( inst_prefix
<< 8 ) | XO
),
35210 ACC_mapped_on_VSR
);
35213 PMSK
= IFIELD( prefix
, 14, 2);
35214 XMSK
= IFIELD( prefix
, 4, 4);
35215 YMSK
= IFIELD( prefix
, 0, 4);
35216 DIP("pmxvf16ger2pn %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
35217 vsx_matrix_ger( vbi
, MATRIX_16BIT_FLOAT_GER
,
35218 getVSReg( rA_addr
),
35219 getVSReg( rB_addr
),
35220 AT
, ( (MASKS
<< 9 )
35221 | ( inst_prefix
<< 8 ) | XO
),
35222 ACC_mapped_on_VSR
);
35225 PMSK
= IFIELD( prefix
, 14, 2);
35226 XMSK
= IFIELD( prefix
, 4, 4);
35227 YMSK
= IFIELD( prefix
, 0, 4);
35228 DIP("pmxvf16ger2np %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
35229 vsx_matrix_ger( vbi
, MATRIX_16BIT_FLOAT_GER
,
35230 getVSReg( rA_addr
),
35231 getVSReg( rB_addr
),
35232 AT
, ( (MASKS
<< 9 )
35233 | ( inst_prefix
<< 8 ) | XO
),
35234 ACC_mapped_on_VSR
);
35237 PMSK
= IFIELD( prefix
, 14, 2);
35238 XMSK
= IFIELD( prefix
, 4, 4);
35239 YMSK
= IFIELD( prefix
, 0, 4);
35240 DIP("pmxvf16ger2nn %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
35241 vsx_matrix_ger( vbi
, MATRIX_16BIT_FLOAT_GER
,
35242 getVSReg( rA_addr
),
35243 getVSReg( rB_addr
),
35244 AT
, ( (MASKS
<< 9 )
35245 | ( inst_prefix
<< 8 ) | XO
),
35246 ACC_mapped_on_VSR
);
35249 PMSK
= IFIELD( prefix
, 14, 2);
35250 XMSK
= IFIELD( prefix
, 4, 4);
35251 YMSK
= IFIELD( prefix
, 0, 4);
35252 DIP("pmxvf32ger %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
35253 vsx_matrix_ger( vbi
, MATRIX_32BIT_FLOAT_GER
,
35254 getVSReg( rA_addr
),
35255 getVSReg( rB_addr
), AT
,
35256 ( ( MASKS
<< 9 ) | ( inst_prefix
<< 8 ) | XO
),
35257 ACC_mapped_on_VSR
);
35260 PMSK
= IFIELD( prefix
, 14, 2);
35261 XMSK
= IFIELD( prefix
, 4, 4);
35262 YMSK
= IFIELD( prefix
, 0, 4);
35263 DIP("pmxvf32gerpp %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
35264 vsx_matrix_ger( vbi
, MATRIX_32BIT_FLOAT_GER
,
35265 getVSReg( rA_addr
),
35266 getVSReg( rB_addr
), AT
,
35267 ( ( MASKS
<< 9) | ( inst_prefix
<< 8 ) | XO
),
35268 ACC_mapped_on_VSR
);
35272 XMSK
= IFIELD( prefix
, 4, 4);
35273 YMSK
= IFIELD( prefix
, 0, 4);
35274 DIP("pmxvf32gerpn %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
35275 vsx_matrix_ger( vbi
, MATRIX_32BIT_FLOAT_GER
,
35276 getVSReg( rA_addr
),
35277 getVSReg( rB_addr
), AT
,
35278 ( ( MASKS
<< 9) | ( inst_prefix
<< 8 ) | XO
),
35279 ACC_mapped_on_VSR
);
35283 XMSK
= IFIELD( prefix
, 4, 4);
35284 YMSK
= IFIELD( prefix
, 0, 4);
35285 DIP("pmxvf32gernp %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
35286 vsx_matrix_ger( vbi
, MATRIX_32BIT_FLOAT_GER
,
35287 getVSReg( rA_addr
),
35288 getVSReg( rB_addr
), AT
,
35289 ( ( MASKS
<< 9) | ( inst_prefix
<< 8 ) | XO
),
35290 ACC_mapped_on_VSR
);
35294 XMSK
= IFIELD( prefix
, 4, 4);
35295 YMSK
= IFIELD( prefix
, 0, 4);
35296 DIP("pmxvf32gernn %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
35297 vsx_matrix_ger( vbi
, MATRIX_32BIT_FLOAT_GER
,
35298 getVSReg( rA_addr
),
35299 getVSReg( rB_addr
), AT
,
35300 ( ( MASKS
<< 9) | ( inst_prefix
<< 8 ) | XO
),
35301 ACC_mapped_on_VSR
);
35305 XMSK
= IFIELD( prefix
, 4, 4);
35306 YMSK
= IFIELD( prefix
, 2, 2);
35307 DIP("pmxvf64ger %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
35308 vsx_matrix_64bit_float_ger( vbi
, getVSReg( rA_addr
),
35309 getVSReg( rA_addr
+1 ),
35310 getVSReg( rB_addr
), AT
,
35311 ( ( MASKS
<< 9) | ( inst_prefix
<< 8 )
35313 ACC_mapped_on_VSR
);
35317 XMSK
= IFIELD( prefix
, 4, 4);
35318 YMSK
= IFIELD( prefix
, 2, 2);
35319 DIP("pmxvf64gerpp %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
35320 vsx_matrix_64bit_float_ger( vbi
, getVSReg( rA_addr
),
35321 getVSReg( rA_addr
+1 ),
35322 getVSReg( rB_addr
), AT
,
35323 ( ( MASKS
<< 9) | ( inst_prefix
<< 8 )
35325 ACC_mapped_on_VSR
);
35329 XMSK
= IFIELD( prefix
, 4, 4);
35330 YMSK
= IFIELD( prefix
, 2, 2);
35331 DIP("pmxvf64gerpn %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
35332 vsx_matrix_64bit_float_ger( vbi
, getVSReg( rA_addr
),
35333 getVSReg( rA_addr
+1 ),
35334 getVSReg( rB_addr
), AT
,
35335 ( ( MASKS
<< 9) | ( inst_prefix
<< 8 )
35337 ACC_mapped_on_VSR
);
35341 XMSK
= IFIELD( prefix
, 4, 4);
35342 YMSK
= IFIELD( prefix
, 2, 2);
35343 DIP("pmxvf64gernp %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
35344 vsx_matrix_64bit_float_ger( vbi
, getVSReg( rA_addr
),
35345 getVSReg( rA_addr
+1 ),
35346 getVSReg( rB_addr
), AT
,
35347 ( ( MASKS
<< 9) | ( inst_prefix
<< 8 )
35349 ACC_mapped_on_VSR
);
35353 XMSK
= IFIELD( prefix
, 4, 4);
35354 YMSK
= IFIELD( prefix
, 2, 2);
35355 DIP("pmxvf64gernn %u,r%u, r%u\n", AT
, rA_addr
, rB_addr
);
35356 vsx_matrix_64bit_float_ger( vbi
, getVSReg( rA_addr
),
35357 getVSReg( rA_addr
+1 ),
35358 getVSReg( rB_addr
), AT
,
35359 ( ( MASKS
<< 9) | ( inst_prefix
<< 8 )
35361 ACC_mapped_on_VSR
);
35367 } else if ((opc1
== 0x1F) && (opc2
== 0xB1) && (bit11_15
== 0) && !prefix
) {
35368 // FYI, this is not a prefix instruction
35369 DIP("xxmfacc %u\n", AT
);
35371 putVSReg( 4*AT
+0, getACC( AT
, 0, ACC_mapped_on_VSR
) );
35372 putVSReg( 4*AT
+1, getACC( AT
, 1, ACC_mapped_on_VSR
) );
35373 putVSReg( 4*AT
+2, getACC( AT
, 2, ACC_mapped_on_VSR
) );
35374 putVSReg( 4*AT
+3, getACC( AT
, 3, ACC_mapped_on_VSR
) );
35376 } else if ((opc1
== 0x1F) && (opc2
== 0xB1) && (bit11_15
== 3) && !prefix
) {
35377 // FYI, this is not a prefix instruction
35378 IRTemp zero128
= newTemp(Ity_V128
);
35380 DIP("xxsetaccz %u\n", AT
);
35382 assign( zero128
, binop(Iop_64HLtoV128
, mkU64( 0 ), mkU64( 0 ) ) );
35383 putACC( AT
, 0, mkexpr( zero128
), ACC_mapped_on_VSR
);
35384 putACC( AT
, 1, mkexpr( zero128
), ACC_mapped_on_VSR
);
35385 putACC( AT
, 2, mkexpr( zero128
), ACC_mapped_on_VSR
);
35386 putACC( AT
, 3, mkexpr( zero128
), ACC_mapped_on_VSR
);
35388 } else if ((opc1
== 0x1F) && (opc2
== 0xB1) && (bit11_15
== 1) && !prefix
) {
35389 // FYI, this is not a prefix instruction
35390 DIP("xxmtacc %u\n", AT
);
35392 putACC( AT
, 0, getVSReg( 4*AT
+0 ), ACC_mapped_on_VSR
);
35393 putACC( AT
, 1, getVSReg( 4*AT
+1 ), ACC_mapped_on_VSR
);
35394 putACC( AT
, 2, getVSReg( 4*AT
+2 ), ACC_mapped_on_VSR
);
35395 putACC( AT
, 3, getVSReg( 4*AT
+3 ), ACC_mapped_on_VSR
);
35398 vex_printf("ERROR, dis_vsx_accumulator_prefix, Unknown instruction theInstr = 0x%x\n",
35406 static Bool
dis_vector_generate_pvc_from_mask ( UInt prefix
,
35408 const VexAbiInfo
* vbi
)
35410 UChar XT_addr
= ifieldRegXT(theInstr
);
35411 UChar vB_addr
= ifieldRegB(theInstr
);
35412 IRTemp vB
= newTemp( Ity_V128
);
35413 UInt opc2
= ifieldOPClo10(theInstr
);
35414 UInt IMM
= IFIELD(theInstr
, (31-15), 5); // bits[11:15]
35416 assign( vB
, getVReg( vB_addr
) );
35420 DIP("xxgenpcvbm v%u,v%u,%u\n", XT_addr
, vB_addr
, IMM
);
35421 /* vector_gen_pvc_mask uses a dirty helper to calculate the result and
35422 write it to the VSX result register. */
35423 vector_gen_pvc_mask( vbi
, mkexpr( vB
), IMM
, opc2
, XT_addr
);
35427 DIP("xxgenpcvhm v%u,v%u,%u\n", XT_addr
, vB_addr
, IMM
);
35428 /* vector_gen_pvc_mask uses a dirty helper to calculate the result and
35429 write it to the VSX result register. */
35430 vector_gen_pvc_mask( vbi
, mkexpr( vB
), IMM
, opc2
, XT_addr
);
35434 DIP("xxgenpcvwm v%u,v%u,%u\n", XT_addr
, vB_addr
, IMM
);
35435 /* vector_gen_pvc_mask uses a dirty helper to calculate the result and
35436 write it to the VSX result register. */
35437 vector_gen_pvc_mask( vbi
, mkexpr( vB
), IMM
, opc2
, XT_addr
);
35441 DIP("xxgenpcvdm v%u,v%u,%u\n", XT_addr
, vB_addr
, IMM
);
35442 /* vector_gen_pvc_mask uses a dirty helper to calculate the result and
35443 write it to the VSX result register. */
35444 vector_gen_pvc_mask( vbi
, mkexpr( vB
), IMM
, opc2
, XT_addr
);
35454 static Int
dis_copy_paste ( UInt prefix
, UInt theInstr
,
35455 const VexAbiInfo
* vbi
)
35457 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
35458 Bool L
= IFIELD( theInstr
, 21, 1 );
35459 UInt bit0
= IFIELD( theInstr
, 0, 1 );
35460 UInt opc2
= ifieldOPClo10( theInstr
);
35461 UChar rA_addr
= ifieldRegA(theInstr
);
35462 UChar rB_addr
= ifieldRegB(theInstr
);
35463 IRTemp cr0
= newTemp( Ity_I8
);
35464 UInt operation
= INVALD_INST
;
35465 IRTemp EA_base
= newTemp(ty
);
35468 UInt mFx
= Ifx_None
;
35469 IRTemp helper_rtn
= newTemp(Ity_I32
);
35471 /* There is no prefixed version of these instructions. */
35474 assign( EA_base
, ea_rAor0_idxd(rA_addr
, rB_addr
) );
35476 if (ty
!= Ity_I64
) {
35477 vpanic( "ERROR PPC: copy, paste, cpabort only supported on 64-bit systems");
35481 /* The dirty helper is passed the EA_bse for the 128-byte buffer and
35482 and operation, i.e. which instruction to issue on the host. It returns
35483 uint32_t result. The result is condition code CR0. Only for the paste
35484 instruction is the return value relevant and must be used to update the
35487 if (( opc2
== 0x306 ) && ( L
== 1 )) { // copy
35488 DIP("copy %u,%u\n", rA_addr
, rB_addr
);
35489 operation
= COPY_INST
;
35492 } else if ( opc2
== 0x346 ) { // cpabort
35494 operation
= CPABORT_INST
;
35495 /* Abort data transfer if one is in progress. */
35496 /* cpabort does nothing to the guest state, just resets operation
35499 } else if (( opc2
== 0x386 ) && ( bit0
== 1 )) { // paste.
35501 /* The Ifx_write will cause Memcheck will instrument the buffer, if
35502 there is any undefinedness in the inputs, then all of the outputs
35503 will be undefined. Hence:
35505 if EA_base or operation contain any undefined bits
35507 then the return value is undefined and the specified 128-byte
35508 memory area are undefined after the call
35510 else the return value is undefined and the specified 128-byte
35511 memory area are defined after the call */
35512 DIP("paste %u,%u\n", rA_addr
, rB_addr
);
35513 operation
= PASTE_INST
;
35517 /* Unknown instruction, should never get here. */
35521 /* Call dirty helper to issue the copy, paste or cpabort instruction on the
35523 args
= mkIRExprVec_2( mkexpr(EA_base
), mkU32(operation
) );
35525 /* The dirty helper needs to return the 8-bit condition code result from
35526 the copy/paste instructions run on the host. The follwoing hack is used
35527 to get Memcheck to return an error if any of the bits in the 128-byte
35528 copy-paste buffer are uninitialized. The bottom 8-bits of helper_rtn
35529 contain the condition code CR0. The upper bits must all be zero. */
35531 d
= unsafeIRDirty_1_N (
35534 "copy_paste_abort_dirty_helper",
35535 fnptr_to_fnentry( vbi
, ©_paste_abort_dirty_helper
),
35538 /* As part of the hack, we must set mFx/mAddr/mSize so as to declare the
35539 memory area used by the copy/paste instructions. */
35542 if (mFx
!= Ifx_None
) {
35544 d
->mAddr
= mkexpr(EA_base
);
35545 d
->mSize
= 128; /* 128 byte memory region */
35548 stmt( IRStmt_Dirty(d
) );
35550 /* The following Exit state is inserted with a test that the IR
35551 optimization cannot remove. */
35553 binop(Iop_CmpNE32
, binop( Iop_And32
, mkexpr(helper_rtn
),
35557 mode64
? IRConst_U64(guest_CIA_curr_instr
) :
35558 IRConst_U32((UInt
) guest_CIA_curr_instr
),
35561 /* The effects of this hack are as follows:
35563 (1) the above stmt() asks the IR to exit, asking Valgrind to hand
35564 the program a SIGTRAP at this point, if the fake return value is
35565 nonzero, however ..
35567 (2) .. that never happens, because the actual return value is maked
35568 out and the upper bits of the return are always zero.
35570 (3) Memcheck will believe that any undefinedness in the copy/paste
35571 area read by the helper will be propagated through to the helper_rtn
35572 value, and will generate instrumentation to cause that to happen.
35574 (4) Memcheck will instrument the IRStmt_Exit to check the definedness
35575 computed by (3) and emit an error if helper_rtn value contains any
35576 undefined bits. Hence Memcheck will generate a warning for undefined
35577 bits in the copy/paste buffer.
35579 (5) Note that the IR optimisation passes do not know what value the
35580 helper call will return. Hence we are guaranteed that they can't
35581 optimise away the IRStmt_Exit and its associated check. */
35583 /* Need to extract the actual return value and put it into the guest
35585 assign( cr0
, unop(Iop_16to8
,
35586 unop(Iop_32to16
, mkexpr(helper_rtn
))));
35588 if (( opc2
== 0x386 ) && (bit0
== 1 )) {
35589 /* Only the paste instruction sets CR0.
35590 Update CR0 bits [3:1] with the copy/paste result with the host CR0
35591 result value. CR0 bit 0 must match the guest XER_OV value. */
35592 putCR0 ( 0, binop(Iop_And8
, mkU8( 1 ), getXER_OV() ) );
35593 putCR321( 0, binop(Iop_And8
, mkU8( 0xE ), mkexpr(cr0
) ) );
35599 static Int
dis_nop_prefix ( UInt prefix
, UInt theInstr
)
35601 Bool is_prefix
= prefix_instruction( prefix
);
35602 UInt bit6_7
= IFIELD( prefix
, 24, 2);
35603 UInt bit8_11
= IFIELD( prefix
, 20, 4);
35604 UInt bit14_31
= IFIELD( prefix
, 0, 18);
35605 UInt opc2
= ifieldOPClo10(theInstr
);
35607 /* pnop instruction :
35608 must be a prefix instruction;
35612 theInstr[0:31] != Branch instruction
35613 The branch instruction (b) has opc2 = 18 (0x12)); */
35616 if (is_prefix
&& (bit6_7
== 3) && (bit8_11
== 0) && (bit14_31
== 0)) {
35617 if (opc2
== 0x12) {
35618 /* suffix is a branch instruction which is invalid. */
35619 vex_printf("INVALID pnop instruction. Exiting\n");
35620 return PREFIX_NOP_INVALID
;
35624 pDIP( is_prefix
, "nop\n");
35630 static Int
dis_darn ( UInt prefix
, UInt theInstr
,
35631 const VexAbiInfo
* vbi
)
35633 /* darn - Deliver A Random Number */
35634 UInt L
= IFIELD( theInstr
, 16, 2);
35635 UChar rD_addr
= ifieldRegDS( theInstr
);
35636 IRTemp rD
= newTemp( Ity_I64
);
35639 /* L Format or returned value
35641 1 CRN_64bits (0 to 0xFFFF_FFFF_FFFF_FFFE)
35642 2 RRN_64bits (0 to 0xFFFF_FFFF_FFFF_FFFE)
35645 On error, return 0xFFFFFFFFFFFFFFFF
35646 A CRN value is a conditioned random number that was processed
35649 /* There is no prefixed version of these instructions. */
35651 DIP("darn r%u,%u\n", rD_addr
, L
);
35654 /* Hardware reports illegal instruction if L = 3. */
35657 IRExpr
** args
= mkIRExprVec_1( mkU32( L
) );
35659 d
= unsafeIRDirty_1_N (
35662 "darn_dirty_helper",
35663 fnptr_to_fnentry( vbi
, &darn_dirty_helper
),
35666 /* Execute the dirty call, returning the result in rD. The dirty
35667 helper calls the darn instruction on the host returning the
35668 random number generated by the darn instruction on the host.
35669 The dirty helper does not change the state of the guest or guest
35671 stmt( IRStmt_Dirty(d
) );
35672 putIReg( rD_addr
, mkexpr( rD
) );
35677 /*------------------------------------------------------------*/
35678 /*--- Disassemble a single instruction ---*/
35679 /*------------------------------------------------------------*/
35681 /* ISA 3.1 introduced a new 8-byte instruction format called "prefixed
35682 instructions". All instructions up to ISA 3.1 were 4-byte instructions
35683 that are now called "word instructions".
35685 Disassemble a single instruction into IR. The instruction
35686 is located in host memory at &guest_code[delta]. */
35689 DisResult
disInstr_PPC_WRK (
35691 const VexArchInfo
* archinfo
,
35692 const VexAbiInfo
* abiinfo
,
35702 IRType ty
= mode64
? Ity_I64
: Ity_I32
;
35703 UInt hwcaps
= archinfo
->hwcaps
;
35704 UInt inst_size
= WORD_INST_SIZE
; //Default
35706 Bool allow_F
= False
;
35707 Bool allow_V
= False
;
35708 Bool allow_FX
= False
;
35709 Bool allow_GX
= False
;
35710 Bool allow_VX
= False
; // Equates to "supports Power ISA 2.06
35711 Bool allow_DFP
= False
;
35712 Bool allow_isa_2_07
= False
;
35713 Bool allow_isa_3_0
= False
;
35714 Bool allow_isa_3_1
= False
;
35715 Bool allow_scv
= False
;
35718 /* In ISA 3.1 the ACC is implemented on top of the vsr0 thru vsr31.
35720 NOTE, ISA 3.1 says in the future the ACC implentation may change. It
35721 doesn't say how it might change but the assumption is the ACC might be
35722 implemented as a separate register file. If/when the ACC is implemented
35723 as a separate register file, ACC_mapped_on_VSR can be set to False, and
35724 Valgrind will instead utilize the separate register file. 2/8/2022
35726 For example, if ISA_3.2 implements the ACC as a separate register
35727 file, there will need to be a check after the if (mode64) statement below
35728 of the form: if (allow_isa_3_2) ACC_mapped_on_VSR = False;
35729 to set the flag to indicate the ACC is implemented as a separate register
35731 Bool ACC_mapped_on_VSR
= True
;
35733 /* What insn variants are we supporting today? */
35736 allow_V
= (0 != (hwcaps
& VEX_HWCAPS_PPC64_V
));
35737 allow_FX
= (0 != (hwcaps
& VEX_HWCAPS_PPC64_FX
));
35738 allow_GX
= (0 != (hwcaps
& VEX_HWCAPS_PPC64_GX
));
35739 allow_VX
= (0 != (hwcaps
& VEX_HWCAPS_PPC64_VX
));
35740 allow_DFP
= (0 != (hwcaps
& VEX_HWCAPS_PPC64_DFP
));
35741 allow_isa_2_07
= (0 != (hwcaps
& VEX_HWCAPS_PPC64_ISA2_07
));
35742 allow_isa_3_0
= (0 != (hwcaps
& VEX_HWCAPS_PPC64_ISA3_0
));
35743 allow_isa_3_1
= (0 != (hwcaps
& VEX_HWCAPS_PPC64_ISA3_1
));
35744 allow_scv
= archinfo
->ppc_scv_supported
;
35746 allow_F
= (0 != (hwcaps
& VEX_HWCAPS_PPC32_F
));
35747 allow_V
= (0 != (hwcaps
& VEX_HWCAPS_PPC32_V
));
35748 allow_FX
= (0 != (hwcaps
& VEX_HWCAPS_PPC32_FX
));
35749 allow_GX
= (0 != (hwcaps
& VEX_HWCAPS_PPC32_GX
));
35750 allow_VX
= (0 != (hwcaps
& VEX_HWCAPS_PPC32_VX
));
35751 allow_DFP
= (0 != (hwcaps
& VEX_HWCAPS_PPC32_DFP
));
35752 allow_isa_2_07
= (0 != (hwcaps
& VEX_HWCAPS_PPC32_ISA2_07
));
35753 allow_isa_3_0
= (0 != (hwcaps
& VEX_HWCAPS_PPC32_ISA3_0
));
35754 /* ISA 3.1 is not supported in 32-bit mode */
35755 /* The scv instruction is not supported in 32-bit mode */
35758 /* Enable writting the OV32 and CA32 bits added with ISA3.0 */
35759 OV32_CA32_supported
= allow_isa_3_0
;
35761 /* The running delta */
35762 delta
= (Long
)mkSzAddr(ty
, (ULong
)delta64
);
35764 /* Set result defaults. */
35765 dres
.whatNext
= Dis_Continue
;
35767 dres
.jk_StopHere
= Ijk_INVALID
;
35768 dres
.hint
= Dis_HintNone
;
35770 /* At least this is simple on PPC32: insns are all 4 bytes long, and
35771 4-aligned. So just fish the whole thing out of memory right now
35773 theInstr
= getUIntPPCendianly( &guest_code
[delta
] );
35774 prefix
= 0; /* Reset the prefix so instruction flag */
35776 if (0) vex_printf("insn: 0x%x\n", theInstr
);
35778 DIP("\t0x%llx: ", (ULong
)guest_CIA_curr_instr
);
35780 /* Spot "Special" instructions (see comment at top of file). */
35782 const UChar
* code
= guest_code
+ delta
;
35783 /* Spot the 16-byte preamble:
35785 5400183E rlwinm 0,0,3,0,31
35786 5400683E rlwinm 0,0,13,0,31
35787 5400E83E rlwinm 0,0,29,0,31
35788 5400983E rlwinm 0,0,19,0,31
35790 78001800 rotldi 0,0,3
35791 78006800 rotldi 0,0,13
35792 7800E802 rotldi 0,0,61
35793 78009802 rotldi 0,0,51
35795 UInt word1
= mode64
? 0x78001800 : 0x5400183E;
35796 UInt word2
= mode64
? 0x78006800 : 0x5400683E;
35797 UInt word3
= mode64
? 0x7800E802 : 0x5400E83E;
35798 UInt word4
= mode64
? 0x78009802 : 0x5400983E;
35799 Bool is_special_preamble
= False
;
35800 if (getUIntPPCendianly(code
+ 0) == word1
&&
35801 getUIntPPCendianly(code
+ 4) == word2
&&
35802 getUIntPPCendianly(code
+ 8) == word3
&&
35803 getUIntPPCendianly(code
+12) == word4
) {
35804 is_special_preamble
= True
;
35805 } else if (! mode64
&&
35806 getUIntPPCendianly(code
+ 0) == 0x54001800 &&
35807 getUIntPPCendianly(code
+ 4) == 0x54006800 &&
35808 getUIntPPCendianly(code
+ 8) == 0x5400E800 &&
35809 getUIntPPCendianly(code
+12) == 0x54009800) {
35810 static Bool reported
= False
;
35812 vex_printf("disInstr(ppc): old ppc32 instruction magic detected. Code might clobber r0.\n");
35813 vex_printf("disInstr(ppc): source needs to be recompiled against latest valgrind.h.\n");
35816 is_special_preamble
= True
;
35818 if (is_special_preamble
) {
35819 /* Got a "Special" instruction preamble. Which one is it? */
35820 if (getUIntPPCendianly(code
+16) == 0x7C210B78 /* or 1,1,1 */) {
35821 /* %R3 = client_request ( %R4 ) */
35822 DIP("r3 = client_request ( %%r4 )\n");
35824 putGST( PPC_GST_CIA
, mkSzImm( ty
, guest_CIA_bbstart
+ delta
));
35825 dres
.jk_StopHere
= Ijk_ClientReq
;
35826 dres
.whatNext
= Dis_StopHere
;
35827 goto decode_success
;
35830 if (getUIntPPCendianly(code
+16) == 0x7C421378 /* or 2,2,2 */) {
35831 /* %R3 = guest_NRADDR */
35832 DIP("r3 = guest_NRADDR\n");
35835 putIReg(3, IRExpr_Get( OFFB_NRADDR
, ty
));
35836 goto decode_success
;
35839 if (getUIntPPCendianly(code
+16) == 0x7C631B78 /* or 3,3,3 */) {
35841 if (host_endness
== VexEndnessLE
) {
35842 /* branch-and-link-to-noredir %R12 */
35843 DIP("branch-and-link-to-noredir r12\n");
35844 putGST( PPC_GST_LR
,
35845 mkSzImm(ty
, guest_CIA_bbstart
+ (Long
)delta
) );
35846 putGST( PPC_GST_CIA
, getIReg(12));
35848 /* branch-and-link-to-noredir %R11 */
35849 DIP("branch-and-link-to-noredir r11\n");
35850 putGST( PPC_GST_LR
,
35851 mkSzImm(ty
, guest_CIA_bbstart
+ (Long
)delta
) );
35852 putGST( PPC_GST_CIA
, getIReg(11));
35854 dres
.jk_StopHere
= Ijk_NoRedir
;
35855 dres
.whatNext
= Dis_StopHere
;
35856 goto decode_success
;
35859 if (getUIntPPCendianly(code
+16) == 0x7C842378 /* or 4,4,4 */) {
35860 /* %R3 = guest_NRADDR_GPR2 */
35861 DIP("r3 = guest_NRADDR_GPR2\n");
35864 putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2
, ty
));
35865 goto decode_success
;
35868 if (getUIntPPCendianly(code
+16) == 0x7CA52B78 /* or 5,5,5 */) {
35869 DIP("IR injection\n");
35870 if (host_endness
== VexEndnessBE
)
35871 vex_inject_ir(irsb
, Iend_BE
);
35873 vex_inject_ir(irsb
, Iend_LE
);
35878 // Invalidate the current insn. The reason is that the IRop we're
35879 // injecting here can change. In which case the translation has to
35880 // be redone. For ease of handling, we simply invalidate all the
35883 stmt(IRStmt_Put(OFFB_CMSTART
, mkSzImm(ty
, guest_CIA_curr_instr
)));
35884 stmt(IRStmt_Put(OFFB_CMLEN
, mkSzImm(ty
, 20)));
35886 putGST( PPC_GST_CIA
, mkSzImm( ty
, guest_CIA_bbstart
+ delta
));
35887 dres
.whatNext
= Dis_StopHere
;
35888 dres
.jk_StopHere
= Ijk_InvalICache
;
35889 goto decode_success
;
35891 /* We don't know what it is. Set opc1/opc2 so decode_failure
35892 can print the insn following the Special-insn preamble. */
35893 theInstr
= getUIntPPCendianly(code
+16);
35894 opc1
= ifieldOPC(theInstr
);
35895 opc2
= ifieldOPClo10(theInstr
);
35896 goto decode_failure
;
35901 /* Determine if the instruction is a word instruction (4-bytes) or a
35902 prefix instruction (8-bytes).
35904 A prefix instruction basically consists of a 4-byte pre-emble followed
35905 bye the 4-byte word instruction. The pre-emble give information on how
35906 the immediate fields are extended. The following 4-bytes are basically
35907 the word instruction containing the opc1 and opc2 fields. */
35909 if (prefix_instruction ( theInstr
)) {
35911 /* Save the current theInstr into the prefix. Fetch the next
35912 four bytes into theInstr and decode the instruction opc1 and opc2
35913 fields the same as a pre ISA 3.1 word instruction. */
35914 inst_size
= PREFIX_INST_SIZE
;
35915 delta
+= WORD_INST_SIZE
; // Get next instruction word
35918 theInstr
= getUIntPPCendianly( &guest_code
[delta
] );
35920 /* Check for pnop instruction. Suffix field is allowed to be anything
35921 but a branch instruction. */
35922 ret
= dis_nop_prefix( prefix
, theInstr
);
35924 goto decode_success
;
35925 else if (ret
== PREFIX_NOP_INVALID
)
35926 goto decode_failure
;
35927 /* not a pnop instruction, try to decode */
35930 opc1
= ifieldOPC(theInstr
);
35931 opc2
= ifieldOPClo10(theInstr
);
35932 is_prefix
= prefix_instruction( prefix
);
35934 // Note: all 'reserved' bits must be cleared, else invalid
35937 /* Integer Arithmetic Instructions */
35939 ISA_3_1_PREFIX_CHECK
35940 if (dis_int_arith_prefix( prefix
, theInstr
)) goto decode_success
;
35941 goto decode_failure
;
35943 case 0x0C: case 0x0D: // addic, addic.
35944 case 0x0F: case 0x07: case 0x08: // addis, mulli, subfic
35945 if (dis_int_arith( prefix
, theInstr
)) goto decode_success
;
35946 goto decode_failure
;
35948 /* Integer Compare Instructions */
35949 case 0x0B: case 0x0A: // cmpi, cmpli
35950 if (dis_int_cmp( prefix
, theInstr
)) goto decode_success
;
35951 goto decode_failure
;
35953 /* Integer Logical Instructions */
35954 case 0x1C: case 0x1D: case 0x18: // andi., andis., ori
35956 if (dis_int_logic( prefix
, theInstr
)) goto decode_success
;
35957 goto decode_failure
;
35960 if ( !is_prefix
) { // oris
35961 if (dis_int_logic( prefix
, theInstr
)) goto decode_success
;
35963 goto decode_failure
;
35966 if ( !is_prefix
) { //oris
35967 if (dis_int_logic( prefix
, theInstr
))
35968 goto decode_success
;
35970 goto decode_failure
;
35972 /* Integer Rotate Instructions */
35973 case 0x14: case 0x15: case 0x17: // rlwimi, rlwinm, rlwnm
35974 if (dis_int_rot( prefix
, theInstr
)) goto decode_success
;
35975 goto decode_failure
;
35977 /* 64bit Integer Rotate Instructions */
35978 case 0x1E: // rldcl, rldcr, rldic, rldicl, rldicr, rldimi
35979 if (!mode64
) goto decode_failure
;
35980 if (dis_int_rot( prefix
, theInstr
)) goto decode_success
;
35981 goto decode_failure
;
35983 /* Integer Load Instructions */
35986 UInt ptype
= PrefixType(prefix
);
35988 if (( ptype
== 1) && prefix_instruction( prefix
)) {
35989 // splat instructions: xxspltiw, xxspltidp, xxsplti32dx
35990 if ( !(allow_isa_3_1
) ) goto decode_noIsa3_1
;
35991 if (dis_vector_splat_imm_prefix( prefix
, theInstr
))
35992 goto decode_success
;
35994 } else if ( is_prefix
&& (ptype
== pType2
) ) { // plwz
35995 if ( !(allow_isa_3_1
) ) goto decode_noIsa3_1
;
35996 if (dis_int_load_prefix( prefix
, theInstr
))
35997 goto decode_success
;
36000 if (dis_int_load_prefix( prefix
, theInstr
))
36001 goto decode_success
;
36003 goto decode_failure
;
36008 UInt ptype
= PrefixType(prefix
);
36010 if (is_prefix
&& ( ptype
== pType1
) ) {
36011 if ( !(allow_isa_3_1
) ) goto decode_noIsa3_1
;
36012 // splat instructions: xxpermx
36013 if (dis_vector_permute_prefix( prefix
, theInstr
, abiinfo
))
36014 goto decode_success
;
36015 } else if (is_prefix
&& ( ptype
== pType2
) ) { // plbz: load instruction
36016 if ( !(allow_isa_3_1
) ) goto decode_noIsa3_1
;
36017 if (dis_int_load_prefix( prefix
, theInstr
))
36018 goto decode_success
;
36019 } else if (!is_prefix
) { // lbz: load instruction
36020 if (dis_int_load_prefix( prefix
, theInstr
))
36021 goto decode_success
;
36023 goto decode_failure
;
36026 case 0x21: case 0x23: // lwzu, lbzu
36027 if (prefix_instruction( prefix
)) {
36028 // blend instructions: xxblendvb, xxblendvh, xxblendvw, xxblendvd
36029 if ( !(allow_isa_3_1
) ) goto decode_noIsa3_1
;
36030 if (dis_vector_blend_prefix( prefix
, theInstr
))
36031 goto decode_success
;
36033 // lbzu, lhau, lhzu, lwzu
36034 if (dis_int_load( prefix
, theInstr
)) goto decode_success
;
36035 goto decode_failure
;
36037 goto decode_failure
;
36039 /* Integer Store Instructions */
36041 if (is_prefix
&& (PrefixType(prefix
) == pType2
)) { // pstw
36042 ISA_3_1_PREFIX_CHECK
36043 if (dis_int_store_prefix( prefix
, theInstr
, abiinfo
))
36044 goto decode_success
;
36045 } else if ( !is_prefix
) { // stw
36046 if (dis_int_store_prefix( prefix
, theInstr
, abiinfo
))
36047 goto decode_success
;
36049 goto decode_failure
;
36052 if (is_prefix
&& (PrefixType(prefix
) == pType2
)) { // pstb
36053 ISA_3_1_PREFIX_CHECK
36054 if (dis_int_store_prefix( prefix
, theInstr
, abiinfo
))
36055 goto decode_success
;
36056 } else if ( !is_prefix
) { // stb
36057 if (dis_int_store_prefix( prefix
, theInstr
, abiinfo
))
36058 goto decode_success
;
36060 goto decode_failure
;
36063 if (is_prefix
&& (PrefixType(prefix
) == pType2
)) { // psth
36064 ISA_3_1_PREFIX_CHECK
36065 if (dis_int_store_prefix( prefix
, theInstr
, abiinfo
))
36066 goto decode_success
;
36067 } else if ( !is_prefix
) { //sth
36068 if (dis_int_store_prefix( prefix
, theInstr
, abiinfo
))
36069 goto decode_success
;
36071 goto decode_failure
;
36073 case 0x27: case 0x2D: case 0x25: // stbu, sthu, stwu
36074 if (dis_int_store( prefix
, theInstr
, abiinfo
)) goto decode_success
;
36075 goto decode_failure
;
36078 if (is_prefix
&& (PrefixType(prefix
) == pType2
)) { // plhz
36079 ISA_3_1_PREFIX_CHECK
36080 if (dis_int_load_prefix( prefix
, theInstr
))
36081 goto decode_success
;
36082 } else if ( !is_prefix
) { // lhz
36083 if (dis_int_load_prefix( prefix
, theInstr
))
36084 goto decode_success
;
36086 goto decode_failure
;
36089 if (is_prefix
&& (PrefixType(prefix
) == pType0
)) { // plwa
36090 ISA_3_1_PREFIX_CHECK
36091 // prefix inst: plwa
36092 if (dis_int_load_ds_form_prefix( prefix
, theInstr
))
36093 goto decode_success
;
36094 } else if ( !is_prefix
) { // lhzu
36095 if (dis_int_load( prefix
, theInstr
))
36096 goto decode_success
;
36098 goto decode_failure
;
36100 case 0x2A: // lha, plha, plxsd
36102 if (is_prefix
&& (PrefixType(prefix
) == pType0
)) { // plxsd
36103 ISA_3_1_PREFIX_CHECK
36104 if (dis_fp_pair_prefix( prefix
, theInstr
))
36105 goto decode_success
;
36106 } else if (is_prefix
&& (PrefixType(prefix
) == pType2
)) { // plha
36107 ISA_3_1_PREFIX_CHECK
36108 if (dis_int_load_prefix( prefix
, theInstr
))
36109 goto decode_success
;
36110 } else if ( !is_prefix
) {
36111 if (dis_int_load_prefix( prefix
, theInstr
)) // lha
36112 goto decode_success
;
36115 goto decode_failure
;
36117 case 0x2B: // lhau, plxssp
36118 if (is_prefix
&& (PrefixType(prefix
) == pType0
)) { // plxssp
36119 ISA_3_1_PREFIX_CHECK
36120 if (dis_fp_pair_prefix( prefix
, theInstr
))
36121 goto decode_success
;
36122 } else if ( !is_prefix
) { // lhau
36123 if (dis_int_load( prefix
, theInstr
))
36124 goto decode_success
;
36126 goto decode_failure
;
36128 /* Integer Load and Store Multiple Instructions */
36130 if (is_prefix
&& (PrefixType(prefix
) == pType0
)) { // pstxsd
36131 ISA_3_1_PREFIX_CHECK
36132 if (dis_fp_pair_prefix( prefix
, theInstr
)) goto decode_success
;
36133 } else if ( !is_prefix
) { // lmw,
36134 if (dis_int_ldst_mult( prefix
, theInstr
)) goto decode_success
;
36136 goto decode_failure
;
36139 if (is_prefix
&& (PrefixType(prefix
) == pType0
)) { // pstxssp
36140 ISA_3_1_PREFIX_CHECK
36141 if (dis_fp_pair_prefix( prefix
, theInstr
)) goto decode_success
;
36142 } else if ( !is_prefix
) { // stmw
36143 if (dis_int_ldst_mult( prefix
, theInstr
)) goto decode_success
;
36145 goto decode_failure
;
36147 /* Branch Instructions */
36148 case 0x12: case 0x10: // b, bc
36149 if (dis_branch( prefix
, theInstr
, abiinfo
, &dres
))
36150 goto decode_success
;
36151 goto decode_failure
;
36153 /* System Linkage Instructions */
36154 case 0x11: // sc, scv
36155 if (dis_syslink( prefix
, theInstr
, abiinfo
, &dres
, allow_scv
,
36157 goto decode_success
;
36158 goto decode_failure
;
36160 /* Trap Instructions */
36162 if (!mode64
) goto decode_failure
;
36163 if (dis_trapi( prefix
, theInstr
, &dres
)) goto decode_success
;
36164 goto decode_failure
;
36167 if (dis_trapi( prefix
, theInstr
, &dres
)) goto decode_success
;
36168 goto decode_failure
;
36170 case 0x06: // lxvp, stxvp
36171 if (dis_fp_pair_prefix( prefix
, theInstr
))
36172 goto decode_success
;
36173 goto decode_failure
;
36175 /* Floating Point Load Instructions */
36177 if (!allow_F
) goto decode_noF
;
36178 if (is_prefix
&& (PrefixType(prefix
) == pType2
)) { // plfs
36179 ISA_3_1_PREFIX_CHECK
36180 if (dis_fp_load_prefix( prefix
, theInstr
)) goto decode_success
;
36181 } else if ( !is_prefix
) { // lfs
36182 if (dis_fp_load_prefix( prefix
, theInstr
)) goto decode_success
;
36184 goto decode_failure
;
36187 if (!allow_F
) goto decode_noF
;
36188 if (dis_fp_load( prefix
, theInstr
)) goto decode_success
;
36189 goto decode_failure
;
36192 if (is_prefix
&& (PrefixType(prefix
) == pType0
)) { // plxv, TX bit = 0
36193 if (!allow_F
) goto decode_noF
;
36194 ISA_3_1_PREFIX_CHECK
36195 if (dis_fp_pair_prefix( prefix
, theInstr
))
36196 goto decode_success
;
36197 } else if (is_prefix
&& (PrefixType(prefix
) == pType2
)) { // plfd
36198 ISA_3_1_PREFIX_CHECK
36199 if (dis_fp_load_prefix( prefix
, theInstr
))
36200 goto decode_success
;
36201 } else if ( !is_prefix
) { // lfd
36202 if (dis_fp_load_prefix( prefix
, theInstr
))
36203 goto decode_success
;
36205 goto decode_failure
;
36208 if (is_prefix
&& (PrefixType(prefix
) == pType0
)) { // plxv, TX bit = 1
36209 if (!allow_F
) goto decode_noF
;
36210 ISA_3_1_PREFIX_CHECK
36211 if (dis_fp_pair_prefix( prefix
, theInstr
))
36212 goto decode_success
;
36214 if (!allow_F
) goto decode_noF
;
36215 if (dis_fp_load( prefix
, theInstr
)) goto decode_success
;
36217 goto decode_failure
;
36219 /* Floating Point Store Instructions */
36221 if (!allow_F
) goto decode_noF
;
36222 if (is_prefix
&& (PrefixType(prefix
) == pType2
)) { // pstfs
36223 ISA_3_1_PREFIX_CHECK
36224 if (dis_fp_store_prefix( prefix
, theInstr
)) goto decode_success
;
36225 } else if ( !is_prefix
) { // stfs
36226 if (dis_fp_store_prefix( prefix
, theInstr
)) goto decode_success
;
36228 goto decode_failure
;
36230 case 0x35: // stfsu
36231 if (!allow_F
) goto decode_noF
;
36232 if (dis_fp_store( prefix
, theInstr
)) goto decode_success
;
36233 goto decode_failure
;
36236 if (is_prefix
&& (PrefixType(prefix
) == pType0
)) { // pstxv, XS bit = 0
36237 ISA_3_1_PREFIX_CHECK
36238 if (dis_fp_pair_prefix( prefix
, theInstr
))
36239 goto decode_success
;
36240 } else if ( is_prefix
&& (PrefixType(prefix
) == pType2
)) { // pstfd
36241 ISA_3_1_PREFIX_CHECK
36242 if (dis_fp_store_prefix( prefix
, theInstr
))
36243 goto decode_success
;
36244 } else if ( !is_prefix
) { // stfd
36245 if (!allow_F
) goto decode_noF
;
36246 if (dis_fp_store_prefix( prefix
, theInstr
)) goto decode_success
;
36248 goto decode_failure
;
36251 if (is_prefix
&& (PrefixType(prefix
) == pType0
)) { // pstxv, XS bit = 1
36252 ISA_3_1_PREFIX_CHECK
36253 if (dis_fp_pair_prefix( prefix
, theInstr
))
36254 goto decode_success
;
36255 } else if ( !is_prefix
) { // stfdu
36256 if (!allow_F
) goto decode_noF
;
36257 if (dis_fp_store( prefix
, theInstr
)) goto decode_success
;
36259 goto decode_failure
;
36261 /* 128-bit Integer Load */
36263 if (is_prefix
&& (PrefixType(prefix
) == pType0
)) { // plq
36264 ISA_3_1_PREFIX_CHECK
36265 if (dis_int_load_prefix( prefix
, theInstr
)) goto decode_success
;
36266 } else if ( !is_prefix
) { // lq
36267 if (dis_int_load_prefix( prefix
, theInstr
)) goto decode_success
;
36269 goto decode_failure
;
36271 /* Floating Point Load Double Pair Instructions */
36272 case 0x39: // pld, lxsd, lxssp, lfdp
36274 UInt opc2tmp
= ifieldOPC0o2(theInstr
);
36275 if (!allow_F
) goto decode_noF
;
36276 if (prefix_instruction( prefix
)) { // pld
36277 if ( !(allow_isa_3_1
) ) goto decode_noIsa3_1
;
36278 if (dis_int_load_ds_form_prefix( prefix
, theInstr
))
36279 goto decode_success
;
36282 if ((opc2tmp
== 2) || (opc2tmp
== 3)) { // lxsd, lxssp
36283 if (dis_fp_pair_prefix( prefix
, theInstr
))
36284 goto decode_success
;
36286 } else if (opc2tmp
== 0) { // lfdp
36287 if (dis_fp_pair( prefix
, theInstr
))
36288 goto decode_success
;
36291 goto decode_failure
;
36296 UInt bits1_0
= IFIELD( theInstr
, 0, 2 );
36297 UInt bits2_0
= IFIELD( theInstr
, 0, 3 );
36299 if (is_prefix
&& (PrefixType(prefix
) == pType0
)) { // pstd
36300 if (dis_int_store_ds_prefix( prefix
, theInstr
, abiinfo
))
36301 goto decode_success
;
36303 } else if ( !is_prefix
) {
36304 if (bits2_0
== 0x1) { // lxv [29:31] = 1
36305 if (dis_fp_pair_prefix( prefix
, theInstr
))
36306 goto decode_success
;
36307 } else if (bits2_0
== 0x5) { // stxv [29:31] = 5
36308 if (dis_fp_pair_prefix( prefix
, theInstr
))
36309 goto decode_success
;
36310 } else if (bits1_0
== 0x0) { // stfdp [30:31] = 0
36311 if (dis_fp_pair( prefix
, theInstr
))
36312 goto decode_success
;
36313 } else if (bits1_0
== 0x2) { // stxsd [30:31] = 2
36314 if (dis_fp_pair_prefix( prefix
, theInstr
))
36315 goto decode_success
;
36316 } else if (bits1_0
== 0x3) { // stxssp [30:31] = 3
36317 if (dis_fp_pair_prefix( prefix
, theInstr
))
36318 goto decode_success
;
36321 goto decode_failure
;
36324 /* 64bit Integer Loads */
36325 case 0x3A: // word inst: ld, ldu, lwa
36327 UChar b1_0
= IFIELD(theInstr
, 0, 2);
36328 if (!mode64
) goto decode_failure
;
36330 if (is_prefix
&& (PrefixType(prefix
) == pType0
)) { // plxvp
36331 ISA_3_1_PREFIX_CHECK
36332 if (dis_fp_pair_prefix( prefix
, theInstr
))
36333 goto decode_success
;
36335 } else if ( !is_prefix
&& ( b1_0
!= 0x3 )) {
36339 /* Note, here we only deal with the non prefix versions
36340 of the instructions. Hence do not check for ISA 3.1. */
36341 if (dis_int_load_ds_form_prefix( prefix
, theInstr
))
36342 goto decode_success
;
36344 goto decode_failure
;
36348 if (!allow_F
) goto decode_noF
;
36349 opc2
= ifieldOPClo10(theInstr
);
36352 case 0x2: // dadd - DFP Add
36353 case 0x202: // dsub - DFP Subtract
36354 case 0x22: // dmul - DFP Mult
36355 case 0x222: // ddiv - DFP Divide
36356 if (!allow_DFP
) goto decode_noDFP
;
36357 if (dis_dfp_arith( prefix
, theInstr
) )
36358 goto decode_success
;
36359 goto decode_failure
;
36360 case 0x82: // dcmpo, DFP comparison ordered instruction
36361 case 0x282: // dcmpu, DFP comparison unordered instruction
36362 if (!allow_DFP
) goto decode_noDFP
;
36363 if (dis_dfp_compare( prefix
, theInstr
) )
36364 goto decode_success
;
36365 goto decode_failure
;
36366 case 0x102: // dctdp - DFP convert to DFP long
36367 case 0x302: // drsp - DFP round to dfp short
36368 case 0x122: // dctfix - DFP convert to fixed
36369 if (!allow_DFP
) goto decode_noDFP
;
36370 if (dis_dfp_fmt_conv( prefix
, theInstr
) )
36371 goto decode_success
;
36372 goto decode_failure
;
36373 case 0x322: // POWER 7 inst, dcffix - DFP convert from fixed
36375 goto decode_failure
;
36376 if (!allow_DFP
) goto decode_noDFP
;
36377 if (dis_dfp_fmt_conv( prefix
, theInstr
) )
36378 goto decode_success
;
36379 goto decode_failure
;
36380 case 0x2A2: // dtstsf - DFP number of significant digits
36381 case 0x2A3: // dtstsfi - DFP number of significant digits Immediate
36382 if (!allow_DFP
) goto decode_noDFP
;
36383 if (dis_dfp_significant_digits( prefix
, theInstr
) )
36384 goto decode_success
;
36385 goto decode_failure
;
36386 case 0x142: // ddedpd DFP Decode DPD to BCD
36387 case 0x342: // denbcd DFP Encode BCD to DPD
36388 if (!allow_DFP
) goto decode_noDFP
;
36389 if (dis_dfp_bcd( prefix
, theInstr
) )
36390 goto decode_success
;
36391 goto decode_failure
;
36392 case 0x162: // dxex - Extract exponent
36393 case 0x362: // diex - Insert exponent
36394 if (!allow_DFP
) goto decode_noDFP
;
36395 if (dis_dfp_extract_insert( prefix
, theInstr
) )
36396 goto decode_success
;
36397 goto decode_failure
;
36398 case 0x3CE: // fcfidus (implemented as native insn)
36401 if (dis_fp_round( prefix
, theInstr
) )
36402 goto decode_success
;
36403 goto decode_failure
;
36404 case 0x34E: // fcfids
36405 if (dis_fp_round( prefix
, theInstr
) )
36406 goto decode_success
;
36407 goto decode_failure
;
36410 opc2
= ifieldOPClo9( theInstr
);
36412 case 0x42: // dscli, DFP shift left
36413 case 0x62: // dscri, DFP shift right
36414 if (!allow_DFP
) goto decode_noDFP
;
36415 if (dis_dfp_shift( prefix
, theInstr
))
36416 goto decode_success
;
36417 goto decode_failure
;
36418 case 0xc2: // dtstdc, DFP test data class
36419 case 0xe2: // dtstdg, DFP test data group
36420 if (!allow_DFP
) goto decode_noDFP
;
36421 if (dis_dfp_class_test( prefix
, theInstr
))
36422 goto decode_success
;
36423 goto decode_failure
;
36426 opc2
= ifieldOPClo8( theInstr
);
36428 case 0x3: // dqua - DFP Quantize
36429 case 0x23: // drrnd - DFP Reround
36430 case 0x43: // dquai - DFP Quantize immediate
36431 if (!allow_DFP
) goto decode_noDFP
;
36432 if (dis_dfp_quantize_sig_rrnd( prefix
, theInstr
) )
36433 goto decode_success
;
36434 goto decode_failure
;
36435 case 0xA2: // dtstex - DFP Test exponent
36436 if (!allow_DFP
) goto decode_noDFP
;
36437 if (dis_dfp_exponent_test( prefix
, theInstr
) )
36438 goto decode_success
;
36439 goto decode_failure
;
36440 case 0x63: // drintx - Round to an integer value
36441 case 0xE3: // drintn - Round to an integer value
36442 if (!allow_DFP
) goto decode_noDFP
;
36443 if (dis_dfp_round( prefix
, theInstr
) ) {
36444 goto decode_success
;
36446 goto decode_failure
;
36448 break; /* fall through to next opc2 check */
36451 opc2
= IFIELD(theInstr
, 1, 5);
36453 /* Floating Point Arith Instructions */
36454 case 0x12: case 0x14: case 0x15: // fdivs, fsubs, fadds
36455 case 0x19: // fmuls
36456 if (dis_fp_arith( prefix
, theInstr
)) goto decode_success
;
36457 goto decode_failure
;
36458 case 0x16: // fsqrts
36459 if (!allow_FX
) goto decode_noFX
;
36460 if (dis_fp_arith( prefix
, theInstr
)) goto decode_success
;
36461 goto decode_failure
;
36463 if (!allow_GX
) goto decode_noGX
;
36464 if (dis_fp_arith( prefix
, theInstr
)) goto decode_success
;
36465 goto decode_failure
;
36467 /* Floating Point Mult-Add Instructions */
36468 case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs
36469 case 0x1F: // fnmadds
36470 if (dis_fp_multadd( prefix
, theInstr
)) goto decode_success
;
36471 goto decode_failure
;
36473 case 0x1A: // frsqrtes
36474 if (!allow_GX
) goto decode_noGX
;
36475 if (dis_fp_arith( prefix
, theInstr
)) goto decode_success
;
36476 goto decode_failure
;
36479 ; // Fall thru to the next check
36482 if ( !prefix_instruction( prefix
) ) {
36483 if ( !(allow_isa_3_1
) ) goto decode_noIsa3_1
;
36484 opc2
= IFIELD( theInstr
, 3, 8 );
36485 if ((opc2
== XVI4GER8
) || // xvi4ger8
36486 (opc2
== XVI4GER8PP
) || // xvi4ger8pp
36487 (opc2
== XVI8GER4
) || // xvi8ger4
36488 (opc2
== XVI8GER4PP
) || // xvi8ger4pp
36489 (opc2
== XVI8GER4SPP
) || // xvi8ger4spp
36490 (opc2
== XVI16GER2
) || // xvi16ger2
36491 (opc2
== XVI16GER2PP
) || // xvi16ger2pp
36492 (opc2
== XVBF16GER2
) || // xvbf16ger2
36493 (opc2
== XVBF16GER2PP
) || // xvbf16ger2pp
36494 (opc2
== XVBF16GER2PN
) || // xvbf16ger2pn
36495 (opc2
== XVBF16GER2NP
) || // xvbf16ger2np
36496 (opc2
== XVBF16GER2NN
) || // xvbf16ger2nn
36497 (opc2
== XVF16GER2
) || // xvf16ger2
36498 (opc2
== XVF16GER2PP
) || // xvf16ger2pp
36499 (opc2
== XVF16GER2PN
) || // xvf16ger2pn
36500 (opc2
== XVF16GER2NP
) || // xvf16ger2np
36501 (opc2
== XVF16GER2NN
) || // xvf16ger2nn
36502 (opc2
== XVI16GER2S
) || // xvi16ger2s
36503 (opc2
== XVI16GER2SPP
) || // xvi16ger2spp
36504 (opc2
== XVF32GER
) || // xvf32ger
36505 (opc2
== XVF32GERPP
) || // xvf32gerpp
36506 (opc2
== XVF32GERPN
) || // xvf32gerpn
36507 (opc2
== XVF32GERNP
) || // xvf32gernp
36508 (opc2
== XVF32GERNN
) || // xvf32gernn
36509 (opc2
== XVF64GER
) || // xvf64ger
36510 (opc2
== XVF64GERPP
) || // xvf64gerpp
36511 (opc2
== XVF64GERPN
) || // xvf64gerpn
36512 (opc2
== XVF64GERNP
) || // xvf64gernp
36513 (opc2
== XVF64GERNN
)) { // xvf64gernn
36514 if (dis_vsx_accumulator_prefix( prefix
, theInstr
, abiinfo
,
36515 ACC_mapped_on_VSR
) )
36516 goto decode_success
;
36517 goto decode_failure
;
36519 vex_printf("ERROR, dis_vsx_accumulator_prefix, unknown opc2 = 0x%x\n",
36521 goto decode_failure
;
36526 if (dis_vsx_accumulator_prefix( prefix
, theInstr
, abiinfo
,
36527 ACC_mapped_on_VSR
) )
36528 goto decode_success
;
36529 goto decode_failure
;
36533 case 0x3C: // pstq, VSX instructions (except load/store)
36535 if ( is_prefix
&& (PrefixType(prefix
) == pType0
) ) {
36536 // pstq instruction
36537 ISA_3_1_PREFIX_CHECK
36538 if (dis_int_store_ds_prefix( prefix
, theInstr
, abiinfo
))
36539 goto decode_success
;
36540 goto decode_failure
;
36543 // All of these VSX instructions use some VMX facilities, so
36544 // if allow_V is not set, we'll skip trying to decode.
36545 if (!allow_V
) goto decode_noVX
;
36546 /* The xvtstdcdp and xvtstdcsp instructions do not have a
36547 contiguous opc2 field. The following vsxOpc2 = get_VSX60_opc2()
36548 doesn't correctly match these instructions for dc != 0. So,
36549 we will explicitly look for the two instructions. */
36550 opc2
= ifieldOPClo10(theInstr
);
36551 UInt opc2hi
= IFIELD(theInstr
, 7, 4);
36552 UInt opc2lo
= IFIELD(theInstr
, 3, 3);
36555 if (( opc2hi
== 13 ) && ( opc2lo
== 5)) { //xvtstdcsp
36556 if (dis_vxs_misc( prefix
, theInstr
, abiinfo
, 0x354, allow_isa_3_0
))
36557 goto decode_success
;
36558 goto decode_failure
;
36561 if (( opc2hi
== 15 ) && ( opc2lo
== 5)) { //xvtstdcdp
36562 if (dis_vxs_misc( prefix
, theInstr
, abiinfo
, 0x3D4, allow_isa_3_0
))
36563 goto decode_success
;
36564 goto decode_failure
;
36567 if ( ( opc2
== 0x168 ) && ( IFIELD( theInstr
, 19, 2 ) == 0 ) )// xxspltib
36569 /* This is a special case of the XX1 form where the RA, RB
36570 * fields hold an immediate value.
36572 if (dis_vxs_misc( prefix
, theInstr
, abiinfo
, opc2
,
36574 goto decode_success
;
36575 goto decode_failure
;
36578 /* This is a special instruction where the opc2 field instr[21:30] = 360
36579 (0x168) and field instr[11:15] = 31 (0x1F) */
36580 if ( ( opc2
== 0x168 ) && ( IFIELD( theInstr
, 16, 5 ) == 31 ) )// lxvlq
36582 if ( !(allow_isa_3_1
) ) goto decode_noIsa3_1
;
36583 if (dis_load_vector_special( prefix
, theInstr
, abiinfo
, opc2
,
36585 goto decode_success
;
36586 goto decode_failure
;
36589 if ( ( opc2
== 0x394 ) || // xxgenpcvbm
36590 ( opc2
== 0x395 ) || // xxgenpcvwm
36591 ( opc2
== 0x3B4 ) || // xxgenpcvhm
36592 ( opc2
== 0x3B5 ) ) { // xxgenpcvdm
36593 if ( !(allow_isa_3_1
) ) goto decode_noIsa3_1
;
36594 if (dis_vector_generate_pvc_from_mask( prefix
, theInstr
,
36596 goto decode_success
;
36597 goto decode_failure
;
36600 /* The vsxOpc2 returned is the "normalized" value, representing the
36601 * instructions secondary opcode as taken from the standard secondary
36602 * opcode field [21:30] (IBM notatition), even if the actual field
36603 * is non-standard. These normalized values are given in the opcode
36604 * appendices of the ISA 2.06 document.
36606 vsxOpc2
= get_VSX60_opc2(opc2
, theInstr
);
36609 case 0x8: case 0x28: case 0x48: case 0xc8: // xxsldwi, xxpermdi, xxmrghw, xxmrglw
36610 case 0x068: case 0xE8: // xxperm, xxpermr
36611 case 0x018: case 0x148: // xxsel, xxspltw
36612 if (dis_vx_permute_misc( prefix
, theInstr
, vsxOpc2
))
36613 goto decode_success
;
36614 goto decode_failure
;
36615 case 0xC: case 0x2C: case 0x4C: // xscmpeqdp, xscmpgtdp, xscmpgedp
36616 case 0x200: case 0x220: //xsmaxcdp, xsmincdp
36617 if (dis_vx_misc( prefix
, theInstr
, vsxOpc2
)) goto decode_success
;
36618 goto decode_failure
;
36619 case 0x268: case 0x248: case 0x288: // xxlxor, xxlor, xxlnor,
36620 case 0x208: case 0x228: // xxland, xxlandc
36621 case 0x2A8: case 0x2C8: case 0x2E8: // xxlorc, xxlnand, xxleqv
36622 if (dis_vx_logic( prefix
, theInstr
, vsxOpc2
)) goto decode_success
;
36623 goto decode_failure
;
36624 case 0x0ec: // xscmpexpdp
36625 case 0x14A: case 0x16A: // xxextractuw, xxinsertw
36626 case 0x2B2: case 0x2C0: // xsabsdp, xscpsgndp
36627 case 0x2D2: case 0x2F2: // xsnabsdp, xsnegdp
36628 case 0x280: case 0x2A0: // xsmaxdp, xsmindp
36629 case 0x0F2: case 0x0D2: // xsrdpim, xsrdpip
36630 case 0x034: case 0x014: // xsresp, xsrsqrtesp
36631 case 0x0B4: case 0x094: // xsredp, xsrsqrtedp
36632 case 0x0D6: case 0x0B2: // xsrdpic, xsrdpiz
36633 case 0x092: case 0x232: // xsrdpi, xsrsp
36634 case 0x2b6: // xsxexpdp, xsxsigdp
36635 case 0x254: case 0x2d4: // xststdcsp, xststdcdp
36636 case 0x354: // xvtstdcsp
36637 case 0x360:case 0x396: // xviexpsp, xsiexpdp
36638 case 0x3D4: case 0x3E0: // xvtstdcdp, xviexpdp
36639 if (dis_vxs_misc( prefix
, theInstr
, abiinfo
, vsxOpc2
,
36641 goto decode_success
;
36642 goto decode_failure
;
36645 UInt inst_select
= IFIELD( theInstr
, 16, 5);
36647 if (inst_select
== 2) { //xvtlsbb
36648 if (dis_test_LSB_by_bit( prefix
, theInstr
))
36649 goto decode_success
;
36650 goto decode_failure
;
36653 // xxbrh, xxbrw, xxbrd, xxbrq, xvxexpdp, xvxexpsp, xvxsigdp
36654 // xvxsigsp, xvcvhpsp, xvcvbf16spn, xvcvspbf16
36655 if (dis_vxs_misc( prefix
, theInstr
, abiinfo
, vsxOpc2
,
36657 goto decode_success
;
36658 goto decode_failure
;
36661 case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
36662 if (dis_vx_cmp( prefix
, theInstr
, vsxOpc2
)) goto decode_success
;
36663 goto decode_failure
;
36665 case 0x0: case 0x020: // xsaddsp, xssubsp
36666 case 0x080: // xsadddp
36667 case 0x060: case 0x0E0: // xsdivsp, xsdivdp
36668 case 0x004: case 0x024: // xsmaddasp, xsmaddmsp
36669 case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp
36670 case 0x044: case 0x064: // xsmsubasp, xsmsubmsp
36671 case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp
36672 case 0x204: case 0x224: // xsnmaddasp, xsnmaddmsp
36673 case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp
36674 case 0x244: case 0x264: // xsnmsubasp, xsnmsubmsp
36675 case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp
36676 case 0x040: case 0x0C0: // xsmulsp, xsmuldp
36677 case 0x0A0: // xssubdp
36678 case 0x016: case 0x096: // xssqrtsp,xssqrtdp
36679 case 0x0F4: case 0x0D4: // xstdivdp, xstsqrtdp
36680 if (dis_vxs_arith( prefix
, theInstr
, vsxOpc2
)) goto decode_success
;
36681 goto decode_failure
;
36682 case 0x180: // xvadddp
36683 case 0x1E0: // xvdivdp
36684 case 0x1C0: // xvmuldp
36685 case 0x1A0: // xvsubdp
36686 case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp
36687 case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp
36688 case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp
36689 case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp
36690 case 0x1D4: case 0x1F4: // xvtsqrtdp, xvtdivdp
36691 case 0x196: // xvsqrtdp
36692 if (dis_vxv_dp_arith( prefix
, theInstr
, vsxOpc2
))
36693 goto decode_success
;
36694 goto decode_failure
;
36695 case 0x100: // xvaddsp
36696 case 0x160: // xvdivsp
36697 case 0x140: // xvmulsp
36698 case 0x120: // xvsubsp
36699 case 0x104: case 0x124: // xvmaddasp, xvmaddmsp
36700 case 0x144: case 0x164: // xvmsubasp, xvmsubmsp
36701 case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp
36702 case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp
36703 case 0x154: case 0x174: // xvtsqrtsp, xvtdivsp
36704 case 0x116: // xvsqrtsp
36705 if (dis_vxv_sp_arith( prefix
, theInstr
, vsxOpc2
))
36706 goto decode_success
;
36707 goto decode_failure
;
36709 case 0x250: // xscvuxdsp
36710 case 0x2D0: case 0x3d0: // xscvuxddp, xvcvuxddp
36711 case 0x350: case 0x1d0: // xvcvuxdsp, xvcvuxwdp
36712 case 0x090: // xscvdpuxws
36713 // The above VSX conversion instructions employ some ISA 2.06
36714 // floating point conversion instructions under the covers,
36715 // so if allow_VX (which means "supports ISA 2.06") is not set,
36716 // we'll skip the decode.
36717 if (!allow_VX
) goto decode_noVX
;
36718 if (dis_vx_conv( prefix
, theInstr
, vsxOpc2
)) goto decode_success
;
36719 goto decode_failure
;
36721 case 0x2B0: // xscvdpsxds
36722 case 0x270: case 0x2F0: // xscvsxdsp, xscvsxddp
36723 case 0x1b0: case 0x130: // xvcvdpsxws, xvcvspsxws
36724 case 0x0b0: case 0x290: // xscvdpsxws, xscvdpuxds
36725 case 0x212: case 0x216: // xscvdpsp, xscvdpspn
36726 case 0x292: case 0x296: // xscvspdp, xscvspdpn
36727 case 0x312: // xvcvdpsp
36728 case 0x390: case 0x190: // xvcvdpuxds, xvcvdpuxws
36729 case 0x3B0: case 0x310: // xvcvdpsxds, xvcvspuxds
36730 case 0x392: case 0x330: // xvcvspdp, xvcvspsxds
36731 case 0x110: case 0x3f0: // xvcvspuxws, xvcvsxddp
36732 case 0x370: case 0x1f0: // xvcvsxdsp, xvcvsxwdp
36733 case 0x170: case 0x150: // xvcvsxwsp, xvcvuxwsp
36734 if (dis_vx_conv( prefix
, theInstr
, vsxOpc2
)) goto decode_success
;
36735 goto decode_failure
;
36737 case 0x18C: // xvcmpeqdp[.]
36738 case 0x10C: // xvcmpeqsp[.]
36739 case 0x14C: // xvcmpgesp[.]
36740 case 0x12C: // xvcmpgtsp[.]
36741 case 0x1CC: // xvcmpgedp[.]
36742 case 0x1AC: // xvcmpgtdp[.]
36743 if (dis_vvec_cmp( prefix
, theInstr
, vsxOpc2
)) goto decode_success
;
36744 goto decode_failure
;
36746 case 0x134: // xvresp
36747 case 0x1B4: // xvredp
36748 case 0x194: case 0x114: // xvrsqrtedp, xvrsqrtesp
36749 case 0x372: // xvnegsp
36750 case 0x380: case 0x3A0: // xvmaxdp, xvmindp
36751 case 0x300: case 0x320: // xvmaxsp, xvminsp
36752 case 0x3C0: case 0x340: // xvcpsgndp, xvcpsgnsp
36753 case 0x3B2: case 0x332: // xvabsdp, xvabssp
36754 case 0x3D2: case 0x352: // xvnabsdp, xvnabssp
36755 case 0x192: case 0x1D6: // xvrdpi, xvrdpic
36756 case 0x1F2: case 0x1D2: // xvrdpim, xvrdpip
36757 case 0x1B2: case 0x3F2: // xvrdpiz, xvnegdp
36758 case 0x112: case 0x156: // xvrspi, xvrspic
36759 case 0x172: case 0x152: // xvrspim, xvrspip
36760 case 0x132: // xvrspiz
36761 if (dis_vxv_misc( prefix
, theInstr
, vsxOpc2
)) goto decode_success
;
36762 goto decode_failure
;
36765 goto decode_failure
;
36770 /* 64bit Integer Stores */
36771 case 0x3E: // std, stdu, stq, pstxvp
36773 UChar b1_0
= IFIELD(theInstr
, 2, 0);
36775 if (is_prefix
&& (PrefixType(prefix
) == pType0
)) { // pstxvp
36776 if (dis_fp_pair_prefix( prefix
, theInstr
))
36777 goto decode_success
;
36779 } else if ( !is_prefix
&& (b1_0
!= 3)) {
36781 // stdu [30:31] = 1
36783 if (dis_int_store_ds_prefix( prefix
, theInstr
, abiinfo
))
36784 goto decode_success
;
36787 vex_printf("No mapping for instruction, opc1 = 0x3E, theInstr = 0x%x\n",
36791 goto decode_failure
;
36794 if ( prefix_instruction( prefix
) ) { // stxacc
36795 if ( !(allow_isa_3_1
) ) goto decode_noIsa3_1
;
36796 if (dis_vsx_accumulator_prefix( prefix
, theInstr
, abiinfo
,
36797 ACC_mapped_on_VSR
) )
36798 goto decode_success
;
36799 goto decode_failure
;
36802 if (!allow_F
) goto decode_noF
;
36803 /* Instrs using opc[1:5] never overlap instrs using opc[1:10],
36804 so we can simply fall through the first switch statement */
36806 opc2
= IFIELD(theInstr
, 1, 5);
36808 /* Floating Point Arith Instructions */
36809 case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd
36811 if (dis_fp_arith( prefix
, theInstr
)) goto decode_success
;
36812 goto decode_failure
;
36813 case 0x16: // fsqrt
36814 if (!allow_FX
) goto decode_noFX
;
36815 if (dis_fp_arith( prefix
, theInstr
)) goto decode_success
;
36816 goto decode_failure
;
36817 case 0x17: case 0x1A: // fsel, frsqrte
36818 if (!allow_GX
) goto decode_noGX
;
36819 if (dis_fp_arith( prefix
, theInstr
)) goto decode_success
;
36820 goto decode_failure
;
36822 /* Floating Point Mult-Add Instructions */
36823 case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub
36824 case 0x1F: // fnmadd
36825 if (dis_fp_multadd( prefix
, theInstr
)) goto decode_success
;
36826 goto decode_failure
;
36829 if (!allow_GX
) goto decode_noGX
;
36830 if (dis_fp_arith( prefix
, theInstr
)) goto decode_success
;
36831 goto decode_failure
;
36834 break; // Fall through
36837 opc2
= IFIELD(theInstr
, 1, 8);
36839 case 0x5: // xsrqpi, xsrqpix
36840 case 0x25: // xsrqpxp
36841 if ( !mode64
|| !allow_isa_3_0
) goto decode_failure
;
36842 if ( dis_vx_Scalar_Round_to_quad_integer( prefix
, theInstr
, abiinfo
) )
36843 goto decode_success
;
36844 goto decode_failure
;
36846 break; // Fall through
36849 opc2
= IFIELD(theInstr
, 1, 10);
36850 UInt inst_select
= IFIELD( theInstr
, 16, 5 );
36853 /* 128-bit DFP instructions */
36854 case 0x2: // daddq - DFP Add
36855 case 0x202: // dsubq - DFP Subtract
36856 case 0x22: // dmulq - DFP Mult
36857 case 0x222: // ddivq - DFP Divide
36858 if (!allow_DFP
) goto decode_noDFP
;
36859 if (dis_dfp_arithq( prefix
, theInstr
))
36860 goto decode_success
;
36861 goto decode_failure
;
36862 case 0x162: // dxexq - DFP Extract exponent
36863 case 0x362: // diexq - DFP Insert exponent
36864 if (!allow_DFP
) goto decode_noDFP
;
36865 if (dis_dfp_extract_insertq( prefix
, theInstr
))
36866 goto decode_success
;
36867 goto decode_failure
;
36869 case 0x82: // dcmpoq, DFP comparison ordered instruction
36870 case 0x282: // dcmpuq, DFP comparison unordered instruction
36871 if (!allow_DFP
) goto decode_noDFP
;
36872 if (dis_dfp_compare( prefix
, theInstr
) )
36873 goto decode_success
;
36874 goto decode_failure
;
36876 case 0x3E2: // dcffixqq - DFP Convert From Fixed Quadword
36877 // dctfixqq - DFP Convert To Fixed Quadword
36878 if (!allow_DFP
) goto decode_noDFP
;
36879 if ( !(allow_isa_3_1
) ) goto decode_noIsa3_1
;
36880 if (dis_dfp_fmt_convq( prefix
, theInstr
, abiinfo
))
36881 goto decode_success
;
36882 goto decode_failure
;
36884 case 0x102: // dctqpq - DFP convert to DFP extended
36885 case 0x302: // drdpq - DFP round to dfp Long
36886 case 0x122: // dctfixq - DFP convert to fixed quad
36887 case 0x322: // dcffixq - DFP convert from fixed quad
36888 if (!allow_DFP
) goto decode_noDFP
;
36889 if (dis_dfp_fmt_convq( prefix
, theInstr
, abiinfo
))
36890 goto decode_success
;
36891 goto decode_failure
;
36893 case 0x2A2: // dtstsfq - DFP number of significant digits
36894 case 0x2A3: // dtstsfiq - DFP number of significant digits Immediate
36895 if (!allow_DFP
) goto decode_noDFP
;
36896 if (dis_dfp_significant_digits( prefix
, theInstr
))
36897 goto decode_success
;
36898 goto decode_failure
;
36900 case 0x142: // ddedpdq DFP Decode DPD to BCD
36901 case 0x342: // denbcdq DFP Encode BCD to DPD
36902 if (!allow_DFP
) goto decode_noDFP
;
36903 if (dis_dfp_bcdq( prefix
, theInstr
))
36904 goto decode_success
;
36905 goto decode_failure
;
36907 /* Floating Point Compare Instructions */
36908 case 0x000: // fcmpu
36909 case 0x020: // fcmpo
36910 if (dis_fp_cmp( prefix
, theInstr
)) goto decode_success
;
36911 goto decode_failure
;
36913 case 0x080: // ftdiv
36914 case 0x0A0: // ftsqrt
36915 if (dis_fp_tests( prefix
, theInstr
)) goto decode_success
;
36916 goto decode_failure
;
36918 /* Floating Point Rounding/Conversion Instructions */
36919 case 0x00C: // frsp
36920 case 0x00E: // fctiw
36921 case 0x00F: // fctiwz
36922 case 0x32E: // fctid
36923 case 0x32F: // fctidz
36924 case 0x34E: // fcfid
36925 if (dis_fp_round( prefix
, theInstr
)) goto decode_success
;
36926 goto decode_failure
;
36927 case 0x3CE: case 0x3AE: case 0x3AF: // fcfidu, fctidu[z] (implemented as native insns)
36928 case 0x08F: case 0x08E: // fctiwu[z] (implemented as native insns)
36929 if (!allow_VX
) goto decode_noVX
;
36930 if (dis_fp_round( prefix
, theInstr
)) goto decode_success
;
36931 goto decode_failure
;
36933 /* Power6 rounding stuff */
36934 case 0x1E8: // frim
36935 case 0x1C8: // frip
36936 case 0x188: // frin
36937 case 0x1A8: // friz
36938 /* A hack to check for P6 capability . . . */
36939 if ((allow_F
&& allow_V
&& allow_FX
&& allow_GX
) &&
36940 (dis_fp_round( prefix
, theInstr
)))
36941 goto decode_success
;
36942 goto decode_failure
;
36944 /* Floating Point Move Instructions */
36945 case 0x008: // fcpsgn
36946 case 0x028: // fneg
36948 case 0x088: // fnabs
36949 case 0x108: // fabs
36950 if (dis_fp_move( prefix
, theInstr
)) goto decode_success
;
36951 goto decode_failure
;
36953 case 0x3c6: case 0x346: // fmrgew, fmrgow
36954 if (dis_fp_merge( prefix
, theInstr
)) goto decode_success
;
36955 goto decode_failure
;
36957 /* Floating Point Status/Control Register Instructions */
36958 case 0x026: // mtfsb1
36959 case 0x040: // mcrfs
36960 case 0x046: // mtfsb0
36961 case 0x086: // mtfsfi
36962 case 0x247: // mffs, mmfs., mffsce, mffscdrn, mffscdrni,
36963 // mffscrn, mffscrn, mffscri, mffsl
36964 case 0x2C7: // mtfsf
36965 // Some of the above instructions need to know more about the
36966 // ISA level supported by the host.
36967 if (dis_fp_scr( prefix
, theInstr
, allow_GX
)) goto decode_success
;
36968 goto decode_failure
;
36970 case 0x324: // xsabsqp, xsxexpqp,xsnabsqp, xsnegqp, xsxsigqp
36971 if ( inst_select
== 27 ) { // xssqrtqp
36972 if ( dis_vx_Floating_Point_Arithmetic_quad_precision( prefix
,
36975 goto decode_success
;
36977 /* fallthrough to dis_vx_scalar_quad_precision */
36979 /* Instructions implemented with Pre ISA 3.0 Iops */
36980 /* VSX Scalar Quad-Precision instructions */
36981 case 0x064: // xscpsgnqp
36982 case 0x0A4: // xscmpexpqp
36983 case 0x084: // xscmpoqp
36984 case 0x284: // xscmpuqp
36985 case 0x2C4: // xststdcqp
36986 case 0x364: // xsiexpqp
36987 if (dis_vx_scalar_quad_precision( prefix
, theInstr
))
36988 goto decode_success
;
36989 goto decode_failure
;
36991 case 0x044: // xscmpeqqp
36992 case 0x0C4: // xscmpgeqp
36993 case 0x0E4: // xscmpgtqp
36994 case 0x2A4: // xsmaxcqp
36995 case 0x2E4: // xsmincqp
36996 if ( !(allow_isa_3_1
) ) goto decode_noIsa3_1
;
36997 if (dis_vx_scalar_quad_precision( prefix
, theInstr
))
36998 goto decode_success
;
36999 goto decode_failure
;
37001 /* Instructions implemented using ISA 3.0 instructions */
37002 // xsaddqpo (VSX Scalar Add Quad-Precision [using round to ODD]
37003 case 0x004: // xsaddqp (VSX Scalar Add Quad-Precision [using RN mode]
37004 // xsmulqpo (VSX Scalar Multiply Quad-Precision [using round to ODD]
37005 case 0x024: // xsmulqp (VSX Scalar Multiply Quad-Precision [using RN mode]
37006 // xsmaddqpo (VSX Scalar Multiply Add Quad-Precision [using round to ODD]
37007 case 0x184: // xsmaddqp (VSX Scalar Multiply Add Quad-Precision [using RN mode]
37008 // xsmsubqpo (VSX Scalar Multiply Sub Quad-Precision [using round to ODD]
37009 case 0x1A4: // xsmsubqp (VSX Scalar Multiply Sub Quad-Precision [using RN mode]
37010 // xsnmaddqpo (VSX Scalar Negative Multiply Add Quad-Precision [using round to ODD]
37011 case 0x1C4: // xsnmaddqp (VSX Scalar Negative Multiply Add Quad-Precision [using RN mode]
37012 // xsnmsubqpo (VSX Scalar Negative Multiply Sub Quad-Precision [using round to ODD]
37013 case 0x1E4: // xsnmsubqp (VSX Scalar Negative Multiply Sub Quad-Precision [usin RN mode]
37014 // xssubqpo (VSX Scalar Subrtact Quad-Precision [using round to ODD]
37015 case 0x204: // xssubqp (VSX Scalar Subrtact Quad-Precision [using RN mode]
37016 // xsdivqpo (VSX Scalar Divde Quad-Precision [using round to ODD]
37017 case 0x224: // xsdivqp (VSX Scalar Divde Quad-Precision [using RN mode]
37018 if ( dis_vx_Floating_Point_Arithmetic_quad_precision( prefix
,
37021 goto decode_success
;
37022 goto decode_failure
;
37024 case 0x344: // xscvudqp, xscvsdqp, xscvqpdp, xscvqpdpo, xsvqpdp
37025 // xscvqpswz, xscvqpuwz, xscvqpudz, xscvqpsdz
37026 /* ISA 3.1 instructions: xscvqpuqz, xscvuqqp, xscvqpsqz,
37028 if (( IFIELD( theInstr
, 16, 5) == 0 // xscvqpuqz
37029 || IFIELD( theInstr
, 16, 5) == 3 // xscvuqqp
37030 || IFIELD( theInstr
, 16, 5) == 8 // xscvqpsqz
37031 || IFIELD( theInstr
, 16, 5) == 11 )) { // xscvsqqp
37032 if (!allow_isa_3_1
)
37033 goto decode_noIsa3_1
;
37035 if ( dis_vx_Floating_Point_Arithmetic_quad_precision( prefix
,
37038 goto decode_success
;
37039 goto decode_failure
;
37042 if ( !mode64
|| !allow_isa_3_0
) goto decode_failure
;
37043 if ( dis_vx_Floating_Point_Arithmetic_quad_precision( prefix
,
37046 goto decode_success
;
37047 goto decode_failure
;
37050 break; // Fall through...
37053 opc2
= ifieldOPClo9( theInstr
);
37055 case 0x42: // dscli, DFP shift left
37056 case 0x62: // dscri, DFP shift right
37057 if (!allow_DFP
) goto decode_noDFP
;
37058 if (dis_dfp_shiftq( prefix
, theInstr
))
37059 goto decode_success
;
37060 goto decode_failure
;
37061 case 0xc2: // dtstdc, DFP test data class
37062 case 0xe2: // dtstdg, DFP test data group
37063 if (!allow_DFP
) goto decode_noDFP
;
37064 if (dis_dfp_class_test( prefix
, theInstr
))
37065 goto decode_success
;
37066 goto decode_failure
;
37071 opc2
= ifieldOPClo8( theInstr
);
37073 case 0x3: // dquaq - DFP Quantize Quad
37074 case 0x23: // drrndq - DFP Reround Quad
37075 case 0x43: // dquaiq - DFP Quantize immediate Quad
37076 if (!allow_DFP
) goto decode_noDFP
;
37077 if (dis_dfp_quantize_sig_rrndq( prefix
, theInstr
))
37078 goto decode_success
;
37079 goto decode_failure
;
37080 case 0xA2: // dtstexq - DFP Test exponent Quad
37081 if (!allow_DFP
) goto decode_noDFP
;
37082 if (dis_dfp_exponent_test( prefix
, theInstr
) )
37083 goto decode_success
;
37084 goto decode_failure
;
37085 case 0x63: // drintxq - DFP Round to an integer value
37086 case 0xE3: // drintnq - DFP Round to an integer value
37087 if (!allow_DFP
) goto decode_noDFP
;
37088 if (dis_dfp_roundq( prefix
, theInstr
))
37089 goto decode_success
;
37090 goto decode_failure
;
37093 goto decode_failure
;
37099 opc2
= ifieldOPClo5(theInstr
);
37102 /* PC relative load/store */
37103 case 0x002: // addpcis
37104 if (dis_pc_relative( prefix
, theInstr
)) goto decode_success
;
37105 goto decode_failure
;
37107 /* fall through to the next opc2 field size */
37110 opc2
= ifieldOPClo10(theInstr
);
37113 /* Condition Register Logical Instructions */
37114 case 0x101: case 0x081: case 0x121: // crand, crandc, creqv
37115 case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor, cror
37116 case 0x1A1: case 0x0C1: case 0x000: // crorc, crxor, mcrf
37117 if (dis_cond_logic( prefix
, theInstr
)) goto decode_success
;
37118 goto decode_failure
;
37120 /* Branch Instructions */
37121 case 0x210: case 0x010: // bcctr, bclr
37122 if (dis_branch( prefix
, theInstr
, abiinfo
, &dres
))
37123 goto decode_success
;
37124 goto decode_failure
;
37126 /* Memory Synchronization Instructions */
37127 case 0x096: // isync
37128 if (dis_memsync( prefix
, theInstr
, allow_isa_3_0
, allow_isa_3_1
))
37129 goto decode_success
;
37130 goto decode_failure
;
37133 goto decode_failure
;
37138 if ( prefix_instruction( prefix
) ) { // stxacc
37139 if ( !(allow_isa_3_1
) ) goto decode_noIsa3_1
;
37140 if (dis_vsx_accumulator_prefix( prefix
, theInstr
, abiinfo
,
37141 ACC_mapped_on_VSR
) )
37142 goto decode_success
;
37143 goto decode_failure
;
37146 /* For arith instns, bit10 is the OE flag (overflow enable) */
37148 opc2
= IFIELD(theInstr
, 1, 9);
37150 /* Integer Arithmetic Instructions */
37151 case 0x10A: case 0x00A: case 0x08A: // add, addc, adde
37152 case 0x0AA: // addex
37153 case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw
37154 case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu
37155 case 0x0EB: case 0x068: case 0x028: // mullw, neg, subf
37156 case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme
37157 case 0x0C8: // subfze
37158 if (dis_int_arith( prefix
, theInstr
)) goto decode_success
;
37159 goto decode_failure
;
37161 case 0x18B: // divweu (implemented as native insn)
37162 case 0x1AB: // divwe (implemented as native insn)
37163 if (!allow_VX
) goto decode_noVX
;
37164 if (dis_int_arith( prefix
, theInstr
)) goto decode_success
;
37165 goto decode_failure
;
37167 /* 64bit Integer Arithmetic */
37168 case 0x009: case 0x049: case 0x0E9: // mulhdu, mulhd, mulld
37169 case 0x1C9: case 0x1E9: // divdu, divd
37170 if (!mode64
) goto decode_failure
;
37171 if (dis_int_arith( prefix
, theInstr
)) goto decode_success
;
37172 goto decode_failure
;
37174 case 0x1A9: // divde (implemented as native insn)
37175 case 0x189: // divdeuo (implemented as native insn)
37176 if (!allow_VX
) goto decode_noVX
;
37177 if (!mode64
) goto decode_failure
;
37178 if (dis_int_arith( prefix
, theInstr
)) goto decode_success
;
37179 goto decode_failure
;
37181 case 0x1FC: // cmpb
37182 if (dis_int_logic( prefix
, theInstr
)) goto decode_success
;
37183 goto decode_failure
;
37185 case 0x180: case 0x1A0: // setbc, setbcr
37186 case 0x1C0: case 0x1E0: // setnbc, setnbcr
37187 if (!allow_isa_3_0
) goto decode_noIsa3_1
;
37188 if (dis_set_bool_condition( prefix
, theInstr
))
37189 goto decode_success
;
37190 goto decode_failure
;
37192 case 0x14D: // lxvpx
37193 case 0x1CD: // stxvpx
37194 if (dis_vsx_vector_paired_load_store( prefix
, theInstr
))
37195 goto decode_success
;
37196 goto decode_failure
;
37199 break; // Fall through...
37202 /* All remaining opcodes use full 10 bits. */
37204 opc2
= IFIELD(theInstr
, 1, 10);
37206 case 0xB1: // xxmfacc, xxsetaccz
37208 if ( !(allow_isa_3_1
) ) goto decode_noIsa3_1
;
37209 if (dis_vsx_accumulator_prefix( prefix
, theInstr
, abiinfo
,
37210 ACC_mapped_on_VSR
) )
37211 goto decode_success
;
37212 goto decode_failure
;
37218 if (dis_byte_reverse( prefix
, theInstr
)) goto decode_success
;
37219 goto decode_failure
;
37221 /* X-form instructions */
37222 case 0x03B: // cntlzdm, Count Leading Zeros Doubleword under bit Mask
37223 case 0x0BC: // pextd, Parallel Bits Extract Doubleword
37224 case 0x09C: // pdepd, Parallel Bits Deposit Doubleword
37225 case 0x23B: // cnttzdm, Count Trailing Zeros Doubleword under bit Mask
37226 case 0x0DC: // cfuged, Centrifuge Doubleword
37227 if ( !(allow_isa_3_1
) ) goto decode_noIsa3_1
;
37228 if (dis_logical_mask_bits( prefix
, theInstr
, abiinfo
) )
37229 goto decode_success
;
37230 goto decode_failure
;
37232 /* Integer miscellaneous instructions */
37233 case 0x01E: // wait RFC 2500
37234 if (dis_int_misc( prefix
, theInstr
)) goto decode_success
;
37235 goto decode_failure
;
37238 /* Integer Compare Instructions */
37239 case 0x000: case 0x020: case 0x080: // cmp, cmpl, setb
37240 if (dis_int_cmp( prefix
, theInstr
)) goto decode_success
;
37241 goto decode_failure
;
37243 case 0x0C0: case 0x0E0: // cmprb, cmpeqb
37244 if (dis_byte_cmp( prefix
, theInstr
)) goto decode_success
;
37245 goto decode_failure
;
37247 case 0x10B: case 0x30B: // moduw, modsw
37248 case 0x109: case 0x309: // modsd, modud
37249 if (dis_modulo_int( prefix
, theInstr
)) goto decode_success
;
37250 goto decode_failure
;
37252 case 0x21A: case 0x23A: // cnttzw, cnttzd
37253 if (dis_modulo_int( prefix
, theInstr
)) goto decode_success
;
37254 goto decode_failure
;
37256 /* Integer Logical Instructions */
37257 case 0x01C: case 0x03C: case 0x01A: // and, andc, cntlzw
37258 case 0x11C: case 0x3BA: case 0x39A: // eqv, extsb, extsh
37259 case 0x1DC: case 0x07C: case 0x1BC: // nand, nor, or
37260 case 0x19C: case 0x13C: // orc, xor
37261 case 0x2DF: case 0x25F: // mftgpr, mffgpr
37262 if (dis_int_logic( prefix
, theInstr
)) goto decode_success
;
37263 goto decode_failure
;
37265 case 0x2F3: // darn - Deliver A Random Number
37266 if (!allow_isa_3_0
) goto decode_noP9
;
37267 if (dis_darn( prefix
, theInstr
, abiinfo
))
37268 goto decode_success
;
37269 goto decode_failure
;
37271 case 0x28E: case 0x2AE: // tbegin., tend.
37272 case 0x2EE: case 0x2CE: case 0x30E: // tsr., tcheck., tabortwc.
37273 case 0x32E: case 0x34E: case 0x36E: // tabortdc., tabortwci., tabortdci.
37274 case 0x38E: case 0x3AE: case 0x3EE: // tabort., treclaim., trechkpt.
37275 if (dis_transactional_memory( prefix
, theInstr
,
37276 getUIntPPCendianly( &guest_code
[delta
+ 4]),
37278 goto decode_success
;
37279 goto decode_failure
;
37281 /* 64bit Integer Logical Instructions */
37282 case 0x3DA: case 0x03A: // extsw, cntlzd
37283 if (!mode64
) goto decode_failure
;
37284 if (dis_int_logic( prefix
, theInstr
)) goto decode_success
;
37285 goto decode_failure
;
37287 /* 64bit Integer Parity Instructions */
37288 case 0xba: // prtyd
37289 if (!mode64
) goto decode_failure
;
37290 if (dis_int_parity( prefix
, theInstr
)) goto decode_success
;
37291 goto decode_failure
;
37293 case 0x9a: // prtyw
37294 if (dis_int_parity( prefix
, theInstr
)) goto decode_success
;
37295 goto decode_failure
;
37297 /* Integer Shift Instructions */
37298 case 0x018: case 0x318: case 0x338: // slw, sraw, srawi
37300 if (dis_int_shift( prefix
, theInstr
, allow_isa_3_0
))
37301 goto decode_success
;
37302 goto decode_failure
;
37304 /* 64bit Integer Shift Instructions */
37305 case 0x01B: case 0x31A: // sld, srad
37306 case 0x33A: case 0x33B: // sradi
37308 if (!mode64
) goto decode_failure
;
37309 if (dis_int_shift( prefix
, theInstr
, allow_isa_3_0
))
37310 goto decode_success
;
37311 goto decode_failure
;
37313 /* Integer Load Instructions */
37314 case 0x057: case 0x077: case 0x157: // lbzx, lbzux, lhax
37315 case 0x177: case 0x117: case 0x137: // lhaux, lhzx, lhzux
37316 case 0x017: case 0x037: // lwzx, lwzux
37317 if (dis_int_load( prefix
, theInstr
)) goto decode_success
;
37318 goto decode_failure
;
37320 /* 64bit Integer Load Instructions */
37321 case 0x035: case 0x015: // ldux, ldx
37322 case 0x175: case 0x155: // lwaux, lwax
37323 if (!mode64
) goto decode_failure
;
37324 if (dis_int_load( prefix
, theInstr
)) goto decode_success
;
37325 goto decode_failure
;
37327 /* Integer Store Instructions */
37328 case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx, sthux
37329 case 0x197: case 0x0B7: case 0x097: // sthx, stwux, stwx
37330 if (dis_int_store( prefix
, theInstr
, abiinfo
)) goto decode_success
;
37331 goto decode_failure
;
37333 /* 64bit Integer Store Instructions */
37334 case 0x0B5: case 0x095: // stdux, stdx
37335 if (!mode64
) goto decode_failure
;
37336 if (dis_int_store( prefix
, theInstr
, abiinfo
)) goto decode_success
;
37337 goto decode_failure
;
37339 /* Integer Load and Store with Byte Reverse Instructions */
37340 case 0x214: case 0x294: // ldbrx, stdbrx
37341 if (!mode64
) goto decode_failure
;
37342 if (dis_int_ldst_rev( prefix
, theInstr
)) goto decode_success
;
37343 goto decode_failure
;
37345 case 0x216: case 0x316: case 0x296: // lwbrx, lhbrx, stwbrx
37346 case 0x396: // sthbrx
37347 if (dis_int_ldst_rev( prefix
, theInstr
)) goto decode_success
;
37348 goto decode_failure
;
37350 /* Integer Load and Store String Instructions */
37351 case 0x255: case 0x215: case 0x2D5: // lswi, lswx, stswi
37352 case 0x295: { // stswx
37353 Bool stopHere
= False
;
37354 Bool ok
= dis_int_ldst_str( prefix
, theInstr
, &stopHere
);
37355 if (!ok
) goto decode_failure
;
37357 putGST( PPC_GST_CIA
, mkSzImm(ty
, nextInsnAddr()) );
37358 dres
.jk_StopHere
= Ijk_Boring
;
37359 dres
.whatNext
= Dis_StopHere
;
37361 goto decode_success
;
37364 /* Memory Synchronization Instructions */
37365 case 0x034: case 0x074: // lbarx, lharx
37366 case 0x2B6: case 0x2D6: // stbcx, sthcx
37367 if (!allow_isa_2_07
) goto decode_noP8
;
37368 if (dis_memsync( prefix
, theInstr
, allow_isa_3_0
, allow_isa_3_1
))
37369 goto decode_success
;
37370 goto decode_failure
;
37372 case 0x356: case 0x014: case 0x096: // eieio, lwarx, stwcx.
37373 case 0x256: // sync
37374 if (dis_memsync( prefix
, theInstr
, allow_isa_3_0
, allow_isa_3_1
))
37375 goto decode_success
;
37376 goto decode_failure
;
37378 /* 64bit Memory Synchronization Instructions */
37379 case 0x054: case 0x0D6: // ldarx, stdcx.
37380 if (!mode64
) goto decode_failure
;
37381 if (dis_memsync( prefix
, theInstr
, allow_isa_3_0
, allow_isa_3_1
))
37382 goto decode_success
;
37383 goto decode_failure
;
37385 case 0x114: case 0x0B6: // lqarx, stqcx.
37386 if (dis_memsync( prefix
, theInstr
, allow_isa_3_0
, allow_isa_3_1
))
37387 goto decode_success
;
37388 goto decode_failure
;
37390 /* Processor Control Instructions */
37391 case 0x33: case 0x73: // mfvsrd, mfvsrwz
37392 case 0xB3: case 0xD3: case 0xF3: // mtvsrd, mtvsrwa, mtvsrwz
37393 case 0x200: case 0x013: case 0x153: // mcrxr, mfcr, mfspr
37394 case 0x173: case 0x090: case 0x1D3: // mftb, mtcrf, mtspr
37395 case 0x220: // mcrxrt
37396 case 0x240: // mcrxrx
37397 if (dis_proc_ctl( abiinfo
, prefix
, theInstr
)) goto decode_success
;
37398 goto decode_failure
;
37400 /* Cache Management Instructions */
37401 case 0x2F6: case 0x056: case 0x036: // dcba, dcbf, dcbst
37402 case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz
37403 case 0x3D6: // icbi
37404 if (dis_cache_manage( prefix
, theInstr
, &dres
, allow_isa_3_1
,
37406 goto decode_success
;
37407 goto decode_failure
;
37409 //zz /* External Control Instructions */
37410 //zz case 0x136: case 0x1B6: // eciwx, ecowx
37411 //zz DIP("external control op => not implemented\n");
37412 //zz goto decode_failure;
37414 /* Trap Instructions */
37416 if (dis_trap( prefix
, theInstr
, &dres
)) goto decode_success
;
37417 goto decode_failure
;
37420 if (!mode64
) goto decode_failure
;
37421 if (dis_trap( prefix
, theInstr
, &dres
)) goto decode_success
;
37422 goto decode_failure
;
37424 /* Floating Point Load Instructions */
37425 case 0x217: case 0x237: case 0x257: // lfsx, lfsux, lfdx
37426 case 0x277: // lfdux
37427 if (!allow_F
) goto decode_noF
;
37428 if (dis_fp_load( prefix
, theInstr
)) goto decode_success
;
37429 goto decode_failure
;
37431 /* Floating Point Store Instructions */
37432 case 0x297: case 0x2B7: case 0x2D7: // stfs, stfsu, stfd
37433 case 0x2F7: // stfdu, stfiwx
37434 if (!allow_F
) goto decode_noF
;
37435 if (dis_fp_store( prefix
, theInstr
)) goto decode_success
;
37436 goto decode_failure
;
37437 case 0x3D7: // stfiwx
37438 if (!allow_F
) goto decode_noF
;
37439 if (!allow_GX
) goto decode_noGX
;
37440 if (dis_fp_store( prefix
, theInstr
)) goto decode_success
;
37441 goto decode_failure
;
37443 /* Floating Point Double Pair Indexed Instructions */
37444 case 0x317: // lfdpx (Power6)
37445 case 0x397: // stfdpx (Power6)
37446 if (!allow_F
) goto decode_noF
;
37447 if (dis_fp_pair( prefix
, theInstr
)) goto decode_success
;
37448 goto decode_failure
;
37450 case 0x357: // lfiwax
37451 if (!allow_F
) goto decode_noF
;
37452 if (dis_fp_load( prefix
, theInstr
)) goto decode_success
;
37453 goto decode_failure
;
37455 case 0x377: // lfiwzx
37456 if (!allow_F
) goto decode_noF
;
37457 if (dis_fp_load( prefix
, theInstr
)) goto decode_success
;
37458 goto decode_failure
;
37460 /* AltiVec instructions */
37462 /* AV Cache Control - Data streams */
37463 case 0x156: case 0x176: case 0x336: // dst, dstst, dss
37464 if (!allow_V
) goto decode_noV
;
37465 if (dis_av_datastream( prefix
, theInstr
)) goto decode_success
;
37466 goto decode_failure
;
37469 case 0x006: case 0x026: // lvsl, lvsr
37470 case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx
37471 case 0x067: case 0x167: // lvx, lvxl
37472 if (!allow_V
) goto decode_noV
;
37473 if (dis_av_load( abiinfo
, prefix
, theInstr
)) goto decode_success
;
37474 goto decode_failure
;
37477 case 0x087: case 0x0A7: case 0x0C7: // stvebx, stvehx, stvewx
37478 case 0x0E7: case 0x1E7: // stvx, stvxl
37479 if (!allow_V
) goto decode_noV
;
37480 if (dis_av_store( prefix
, theInstr
)) goto decode_success
;
37481 goto decode_failure
;
37484 case 0x00C: // lxsiwzx
37485 case 0x04C: // lxsiwax
37486 case 0x10C: // lxvx
37487 case 0x10D: // lxvl
37488 case 0x12D: // lxvll
37489 case 0x16C: // lxvwsx
37490 case 0x20C: // lxsspx
37491 case 0x24C: // lxsdx
37492 case 0x32C: // lxvh8x
37493 case 0x30D: // lxsibzx
37494 case 0x32D: // lxsihzx
37495 case 0x34C: // lxvd2x
37496 case 0x36C: // lxvb16x
37497 case 0x14C: // lxvdsx
37498 case 0x30C: // lxvw4x
37499 // All of these VSX load instructions use some VMX facilities, so
37500 // if allow_V is not set, we'll skip trying to decode.
37501 if (!allow_V
) goto decode_noV
;
37503 if (dis_vx_load( prefix
, theInstr
)) goto decode_success
;
37504 goto decode_failure
;
37506 case 0x00D: // lxvrbx
37507 case 0x02D: // lxvrhx
37508 case 0x04D: // lxvrwx
37509 case 0x06D: // lxvrdx
37510 case 0x08D: // stxvrbx
37511 case 0x0AD: // stxvrhx
37512 case 0x0CD: // stxvrwx
37513 case 0x0ED: // stxvrdx
37514 // All of these VSX load instructions use some VMX facilities, so
37515 // if allow_V is not set, we'll skip trying to decode.
37516 if (!allow_V
) goto decode_noV
;
37517 if ( !(allow_isa_3_1
) ) goto decode_noIsa3_1
;
37518 if (dis_vx_load( prefix
, theInstr
)) goto decode_success
;
37519 goto decode_failure
;
37522 case 0x08C: // stxsiwx
37523 case 0x18C: // stxvx
37524 case 0x18D: // stxvl
37525 case 0x1AD: // stxvll
37526 case 0x28C: // stxsspx
37527 case 0x2CC: // stxsdx
37528 case 0x38C: // stxvw4x
37529 case 0x3CC: // stxvd2x
37530 case 0x38D: // stxsibx
37531 case 0x3AD: // stxsihx
37532 case 0x3AC: // stxvh8x
37533 case 0x3EC: // stxvb16x
37534 // All of these VSX store instructions use some VMX facilities, so
37535 // if allow_V is not set, we'll skip trying to decode.
37536 if (!allow_V
) goto decode_noV
;
37538 if (dis_vx_store( prefix
, theInstr
)) goto decode_success
;
37539 goto decode_failure
;
37541 case 0x133: case 0x193: case 0x1B3: // mfvsrld, mfvsrdd, mtvsrws
37542 // The move from/to VSX instructions use some VMX facilities, so
37543 // if allow_V is not set, we'll skip trying to decode.
37544 if (!allow_V
) goto decode_noV
;
37545 if (dis_vx_move( prefix
, theInstr
)) goto decode_success
;
37546 goto decode_failure
;
37548 /* Miscellaneous ISA 2.06 instructions */
37549 case 0x1FA: // popcntd
37550 if (!mode64
) goto decode_failure
;
37551 /* else fallthru */
37552 case 0x17A: // popcntw
37553 case 0x7A: // popcntb
37554 if (dis_int_logic( prefix
, theInstr
)) goto decode_success
;
37555 goto decode_failure
;
37557 case 0x0FC: // bpermd
37558 if (!mode64
) goto decode_failure
;
37559 if (dis_int_logic( prefix
, theInstr
)) goto decode_success
;
37560 goto decode_failure
;
37562 case 0x306: // copy
37563 if ( !mode64
|| !allow_isa_3_0
) goto decode_failure
;
37564 if (dis_copy_paste( prefix
, theInstr
, abiinfo
)) goto decode_success
;
37565 goto decode_failure
;
37567 case 0x346: // cpabort
37568 if ( !mode64
|| !allow_isa_3_0
) goto decode_failure
;
37569 if (dis_copy_paste( prefix
, theInstr
, abiinfo
)) goto decode_success
;
37570 goto decode_failure
;
37572 case 0x386: // paste.
37573 if ( !mode64
|| !allow_isa_3_0
) goto decode_failure
;
37574 if (dis_copy_paste( prefix
, theInstr
, abiinfo
)) goto decode_success
;
37575 goto decode_failure
;
37578 /* Deal with some other cases that we would otherwise have
37580 /* --- ISEL (PowerISA_V2.05.pdf, p74) --- */
37581 /* only decode this insn when reserved bit 0 (31 in IBM's
37582 notation) is zero */
37583 if (IFIELD(theInstr
, 0, 6) == (15<<1)) {
37584 UInt rT
= ifieldRegDS( theInstr
);
37585 UInt rA
= ifieldRegA( theInstr
);
37586 UInt rB
= ifieldRegB( theInstr
);
37587 UInt bi
= ifieldRegC( theInstr
);
37590 IRExpr_ITE( binop(Iop_CmpNE32
, getCRbit( bi
), mkU32(0)),
37591 rA
== 0 ? (mode64
? mkU64(0) : mkU32(0))
37596 DIP("isel r%u,r%u,r%u,crb%u\n", rT
,rA
,rB
,bi
);
37597 goto decode_success
;
37601 opc2
= IFIELD(theInstr
, 2, 9);
37604 if (!mode64
) goto decode_failure
;
37605 if (dis_int_logic( prefix
, theInstr
)) goto decode_success
;
37606 goto decode_failure
;
37609 goto decode_failure
;
37615 /* AltiVec instructions */
37617 opc2
= IFIELD(theInstr
, 1, 5);
37619 case 0xA: // mtvsrbmi
37620 if (!allow_V
) goto decode_noV
;
37621 if ( !(allow_isa_3_1
) ) goto decode_noIsa3_1
;
37622 if (dis_VSR_byte_mask( prefix
, theInstr
, abiinfo
))
37623 goto decode_success
;
37624 goto decode_failure
;
37628 break; // Fall through...
37631 opc2
= IFIELD(theInstr
, 0, 6);
37633 /* AV Mult-Add, Mult-Sum */
37634 case 0x16: // vsldbi/vsrdbi
37635 if (!allow_V
) goto decode_noV
;
37636 if (dis_av_shift( prefix
, theInstr
)) goto decode_success
;
37637 goto decode_failure
;
37639 case 0x17: // vmsumcud
37640 if ( !(allow_isa_3_1
) ) goto decode_noIsa3_1
;
37641 if (dis_vx_quadword_arith( prefix
, theInstr
)) {
37642 goto decode_success
;
37644 goto decode_failure
;
37646 case 0x18: case 0x19: // vextdubvlx, vextdubvrx
37647 case 0x1A: case 0x1B: // vextduhvlx, vextduhvrx
37648 case 0x1C: case 0x1D: // vextduwvlx, vextduwvrx
37649 case 0x1E: case 0x1F: // vextddvlx, vextddvrx
37650 if (!allow_V
) goto decode_noV
;
37651 if ( !(allow_isa_3_1
) ) goto decode_noIsa3_1
;
37652 if (dis_vec_extract_insert( prefix
, theInstr
))
37653 goto decode_success
;
37654 goto decode_failure
;
37656 case 0x20: case 0x21: case 0x22: // vmhaddshs, vmhraddshs, vmladduhm
37657 case 0x23: // vmsumudm
37658 case 0x24: case 0x25: case 0x26: // vmsumubm, vmsummbm, vmsumuhm
37659 case 0x27: case 0x28: case 0x29: // vmsumuhs, vmsumshm, vmsumshs
37660 if (!allow_V
) goto decode_noV
;
37661 if (dis_av_multarith( prefix
, theInstr
)) goto decode_success
;
37662 goto decode_failure
;
37664 case 0x30: case 0x31: case 0x33: // maddhd, madhdu, maddld
37665 if (!mode64
) goto decode_failure
;
37666 if (dis_int_mult_add( prefix
, theInstr
)) goto decode_success
;
37667 goto decode_failure
;
37669 /* AV Permutations */
37671 case 0x2B: // vperm
37672 case 0x2C: // vsldoi
37673 if (!allow_V
) goto decode_noV
;
37674 if (dis_av_permute( prefix
, theInstr
)) goto decode_success
;
37675 goto decode_failure
;
37677 case 0x2D: // vpermxor
37678 case 0x3B: // vpermr
37679 if (!allow_isa_2_07
) goto decode_noP8
;
37680 if (dis_av_permute( prefix
, theInstr
)) goto decode_success
;
37681 goto decode_failure
;
37683 /* AV Floating Point Mult-Add/Sub */
37684 case 0x2E: case 0x2F: // vmaddfp, vnmsubfp
37685 if (!allow_V
) goto decode_noV
;
37686 if (dis_av_fp_arith( prefix
, theInstr
)) goto decode_success
;
37687 goto decode_failure
;
37689 case 0x3D: case 0x3C: // vaddecuq, vaddeuqm
37690 case 0x3F: case 0x3E: // vsubecuq, vsubeuqm
37691 if (!allow_V
) goto decode_noV
;
37692 if (dis_av_quad( prefix
, theInstr
, abiinfo
)) goto decode_success
;
37693 goto decode_failure
;
37696 break; // Fall through...
37699 opc2
= IFIELD(theInstr
, 0, 9);
37700 if (IFIELD(theInstr
, 10, 1) == 1) {
37701 /* The following instructions have bit 21 set and a PS bit (bit 22)
37702 * Bit 21 distinquishes them from instructions with an 11 bit opc2
37706 /* BCD arithmetic */
37707 case 0x001: case 0x041: // bcdadd, bcdsub
37708 case 0x101: case 0x141: // bcdtrunc., bcdutrunc.
37709 case 0x081: case 0x0C1: case 0x1C1: // bcdus., bcds., bcdsr.
37710 case 0x181: // bcdcfn., bcdcfz.
37711 // bcdctz., bcdcfsq., bcdctsq.
37712 if (!allow_isa_2_07
) goto decode_noP8
;
37713 if (dis_av_bcd( prefix
, theInstr
, abiinfo
)) goto decode_success
;
37714 goto decode_failure
;
37716 break; // Fall through...
37720 opc2
= IFIELD(theInstr
, 0, 10);
37721 opc3
= IFIELD(theInstr
, 16, 5);
37723 if ((opc2
== 0x0D) & (opc3
< 4)) { // vstrihr, vstrihl, vstribr vstrib
37724 /* Vector String Isolate instructions */
37725 if ( !(allow_isa_3_1
) ) goto decode_noIsa3_1
;
37726 if (dis_string_isolate( prefix
, theInstr
))
37727 goto decode_success
;
37728 goto decode_failure
;
37731 opc2
= IFIELD(theInstr
, 0, 11);
37734 /* Vector String Isolate instructions */
37735 case 0x18D: // vclrlb
37736 case 0x1CD: // vclrrb
37737 if ( !(allow_isa_3_1
) ) goto decode_noIsa3_1
;
37738 if (dis_string_isolate( prefix
, theInstr
))
37739 goto decode_success
;
37740 goto decode_failure
;
37742 /* BCD manipulation */
37743 case 0x341: // bcdcpsgn
37744 if (!allow_isa_2_07
) goto decode_noP8
;
37745 if (dis_av_bcd_misc( prefix
, theInstr
, abiinfo
))
37746 goto decode_success
;
37747 goto decode_failure
;
37750 /* AV Arithmetic */
37751 case 0x180: // vaddcuw
37752 case 0x000: case 0x040: case 0x080: // vaddubm, vadduhm, vadduwm
37753 case 0x200: case 0x240: case 0x280: // vaddubs, vadduhs, vadduws
37754 case 0x300: case 0x340: case 0x380: // vaddsbs, vaddshs, vaddsws
37755 case 0x580: // vsubcuw
37756 case 0x400: case 0x440: case 0x480: // vsububm, vsubuhm, vsubuwm
37757 case 0x600: case 0x640: case 0x680: // vsububs, vsubuhs, vsubuws
37758 case 0x700: case 0x740: case 0x780: // vsubsbs, vsubshs, vsubsws
37759 case 0x402: case 0x442: case 0x482: // vavgub, vavguh, vavguw
37760 case 0x502: case 0x542: case 0x582: // vavgsb, vavgsh, vavgsw
37761 case 0x002: case 0x042: case 0x082: // vmaxub, vmaxuh, vmaxuw
37762 case 0x102: case 0x142: case 0x182: // vmaxsb, vmaxsh, vmaxsw
37763 case 0x202: case 0x242: case 0x282: // vminub, vminuh, vminuw
37764 case 0x302: case 0x342: case 0x382: // vminsb, vminsh, vminsw
37765 case 0x008: case 0x048: // vmuloub, vmulouh
37766 case 0x108: case 0x148: // vmulosb, vmulosh
37767 case 0x208: case 0x248: // vmuleub, vmuleuh
37768 case 0x308: case 0x348: // vmulesb, vmulesh
37769 case 0x608: case 0x708: case 0x648: // vsum4ubs, vsum4sbs, vsum4shs
37770 case 0x688: case 0x788: // vsum2sws, vsumsws
37771 if (!allow_V
) goto decode_noV
;
37772 if (dis_av_arith( prefix
, theInstr
)) goto decode_success
;
37773 goto decode_failure
;
37775 case 0x0C8: case 0x1C8: case 0x2C8: // vmuloud, vmulosd, vmuleud
37776 case 0x3C8: // vmulesd
37777 if (!allow_V
) goto decode_noV
;
37778 if ( !(allow_isa_3_1
) ) goto decode_noIsa3_1
;
37779 if (dis_av_arith( prefix
, theInstr
)) goto decode_success
;
37780 goto decode_failure
;
37782 case 0x08B: case 0x18B: // vdivuw, vdivsw
37783 case 0x289: case 0x389: // vmulhuw, vmulhsw
37784 case 0x28B: case 0x38B: // vdiveuw, vdivesw
37785 case 0x68B: case 0x78B: // vmoduw, vmodsw
37786 case 0x1c9: // vmulld
37787 case 0x2C9: case 0x3C9: // vmulhud, vmulhsd
37788 case 0x0CB: case 0x1CB: // vdivud, vdivsd
37789 case 0x2CB: case 0x3CB: // vdiveud, vdivesd
37790 case 0x6CB: case 0x7CB: // vmodud, vmodsd
37791 if (!allow_V
) goto decode_noV
;
37792 if (dis_av_arith( prefix
, theInstr
)) goto decode_success
;
37793 goto decode_failure
;
37795 case 0x005: // vrlq
37796 case 0x00B: case 0x10B: // vdivuq, vdivsq
37797 case 0x045: // vrlqmi
37798 case 0x101: case 0x141: // vcmpuq, vcmpsq
37799 case 0x105: case 0x145: // vslq, vrlqnm
37800 case 0x1C7: case 0x5C7: // vcmpequq, vcmpequq.
37801 case 0x205: // vsrq
37802 case 0x20B: case 0x30B: // vdivueq, vdivesq
37803 case 0x287: case 0x687: // vcmpgtuq, vcmpgtuq.
37804 case 0x305: // vsraq
37805 case 0x387: case 0x787: // vcmpgtsq, vcmpgtsq.
37806 case 0x60B: case 0x70B: // vmoduq, vmodsq
37807 if (!allow_V
) goto decode_noV
;
37808 if ( !(allow_isa_3_1
) ) goto decode_noIsa3_1
;
37809 if (dis_vx_quadword_arith( prefix
, theInstr
))
37810 goto decode_success
;
37811 goto decode_failure
;
37813 case 0x088: case 0x089: // vmulouw, vmuluwm
37814 case 0x0C0: case 0x0C2: // vaddudm, vmaxud
37815 case 0x1C2: case 0x2C2: case 0x3C2: // vmaxsd, vminud, vminsd
37816 case 0x188: case 0x288: case 0x388: // vmulosw, vmuleuw, vmulesw
37817 case 0x4C0: // vsubudm
37818 if (!allow_isa_2_07
) goto decode_noP8
;
37819 if (dis_av_arith( prefix
, theInstr
)) goto decode_success
;
37820 goto decode_failure
;
37822 /* AV Polynomial Vector Multiply Add */
37823 case 0x408: case 0x448: // vpmsumb, vpmsumd
37824 case 0x488: case 0x4C8: // vpmsumw, vpmsumh
37825 if (!allow_isa_2_07
) goto decode_noP8
;
37826 if (dis_av_polymultarith( prefix
, theInstr
)) goto decode_success
;
37827 goto decode_failure
;
37829 /* AV Rotate, Shift */
37830 case 0x004: case 0x044: case 0x084: // vrlb, vrlh, vrlw
37831 case 0x104: case 0x144: case 0x184: // vslb, vslh, vslw
37832 case 0x204: case 0x244: case 0x284: // vsrb, vsrh, vsrw
37833 case 0x304: case 0x344: case 0x384: // vsrab, vsrah, vsraw
37834 case 0x1C4: case 0x2C4: // vsl, vsr
37835 case 0x40C: case 0x44C: // vslo, vsro
37836 if (!allow_V
) goto decode_noV
;
37837 if (dis_av_shift( prefix
, theInstr
)) goto decode_success
;
37838 goto decode_failure
;
37840 case 0x0C4: // vrld
37841 case 0x3C4: case 0x5C4: case 0x6C4: // vsrad, vsld, vsrd
37842 if (!allow_isa_2_07
) goto decode_noP8
;
37843 if (dis_av_shift( prefix
, theInstr
)) goto decode_success
;
37844 goto decode_failure
;
37847 case 0x404: case 0x444: case 0x484: // vand, vandc, vor
37848 case 0x4C4: case 0x504: // vxor, vnor
37849 if (!allow_V
) goto decode_noV
;
37850 if (dis_av_logic( prefix
, theInstr
)) goto decode_success
;
37851 goto decode_failure
;
37853 case 0x544: // vorc
37854 case 0x584: case 0x684: // vnand, veqv
37855 if (!allow_isa_2_07
) goto decode_noP8
;
37856 if (dis_av_logic( prefix
, theInstr
)) goto decode_success
;
37857 goto decode_failure
;
37860 case 0x085: case 0x185: // vrlwmi, vrlwnm
37861 case 0x0C5: case 0x1C5: // vrldmi, vrldnm
37862 if (!allow_V
) goto decode_noV
;
37863 if (dis_av_rotate( prefix
, theInstr
)) goto decode_success
;
37864 goto decode_failure
;
37866 /* AV Processor Control */
37867 case 0x604: case 0x644: // mfvscr, mtvscr
37868 if (!allow_V
) goto decode_noV
;
37869 if (dis_av_procctl( prefix
, theInstr
)) goto decode_success
;
37870 goto decode_failure
;
37872 /* AV Vector Insert Element instructions */
37873 case 0x00F: case 0x10F: // vinsbvlx, vinsbvrx
37874 case 0x04F: case 0x14F: // vinshvlx, vinshvrx
37875 case 0x08F: case 0x18F: // vinswvlx, vinswvrx
37876 case 0x0CF: case 0x1CF: // vinsw, vinsw
37877 case 0x20F: case 0x30F: // vinsblx, vinsbrx
37878 case 0x24F: case 0x34F: // vinshlx, vinshrx
37879 case 0x28F: case 0x38F: // vinswlx, vinswrx
37880 case 0x2CF: case 0x3CF: // vinsdlx, vinsdrx
37881 if (!allow_V
) goto decode_noV
;
37882 if ( !(allow_isa_3_1
) ) goto decode_noIsa3_1
;
37883 if (dis_av_insert_element( prefix
, theInstr
))
37884 goto decode_success
;
37885 goto decode_failure
;
37887 /* AV Vector Extract Element instructions */
37888 case 0x60D: case 0x64D: case 0x68D: // vextublx, vextuhlx, vextuwlx
37889 case 0x70D: case 0x74D: case 0x78D: // vextubrx, vextuhrx, vextuwrx
37890 if (!allow_V
) goto decode_noV
;
37891 if (dis_av_extract_element( prefix
, theInstr
)) goto decode_success
;
37892 goto decode_failure
;
37895 /* AV Floating Point Arithmetic */
37896 case 0x00A: case 0x04A: // vaddfp, vsubfp
37897 case 0x10A: case 0x14A: case 0x18A: // vrefp, vrsqrtefp, vexptefp
37898 case 0x1CA: // vlogefp
37899 case 0x40A: case 0x44A: // vmaxfp, vminfp
37900 if (!allow_V
) goto decode_noV
;
37901 if (dis_av_fp_arith( prefix
, theInstr
)) goto decode_success
;
37902 goto decode_failure
;
37904 /* AV Floating Point Round/Convert */
37905 case 0x20A: case 0x24A: case 0x28A: // vrfin, vrfiz, vrfip
37906 case 0x2CA: // vrfim
37907 case 0x30A: case 0x34A: case 0x38A: // vcfux, vcfsx, vctuxs
37908 case 0x3CA: // vctsxs
37909 if (!allow_V
) goto decode_noV
;
37910 if (dis_av_fp_convert( prefix
, theInstr
)) goto decode_success
;
37911 goto decode_failure
;
37913 /* AV Merge, Splat, Extract, Insert */
37914 case 0x00C: case 0x04C: case 0x08C: // vmrghb, vmrghh, vmrghw
37915 case 0x10C: case 0x14C: case 0x18C: // vmrglb, vmrglh, vmrglw
37916 case 0x20C: case 0x24C: case 0x28C: // vspltb, vsplth, vspltw
37917 case 0x20D: case 0x24D: // vextractub, vextractuh,
37918 case 0x28D: case 0x2CD: // vextractuw, vextractd,
37919 case 0x30D: case 0x34D: // vinsertb, vinserth
37920 case 0x38D: case 0x3CD: // vinsertw, vinsertd
37921 case 0x30C: case 0x34C: case 0x38C: // vspltisb, vspltish, vspltisw
37922 if (!allow_V
) goto decode_noV
;
37923 if (dis_av_permute( prefix
, theInstr
)) goto decode_success
;
37924 goto decode_failure
;
37926 case 0x68C: case 0x78C: // vmrgow, vmrgew
37927 if (!allow_isa_2_07
) goto decode_noP8
;
37928 if (dis_av_permute( prefix
, theInstr
)) goto decode_success
;
37929 goto decode_failure
;
37931 /* AltiVec 128 bit integer multiply by 10 Instructions */
37932 case 0x201: case 0x001: //vmul10uq, vmul10cuq
37933 case 0x241: case 0x041: //vmul10euq, vmul10ceuq
37934 if (!allow_V
) goto decode_noV
;
37935 if (!allow_isa_3_0
) goto decode_noP9
;
37936 if (dis_av_mult10( prefix
, theInstr
)) goto decode_success
;
37937 goto decode_failure
;
37939 /* AV Pack, Unpack */
37940 case 0x00E: case 0x04E: case 0x08E: // vpkuhum, vpkuwum, vpkuhus
37941 case 0x0CE: // vpkuwus
37942 case 0x10E: case 0x14E: case 0x18E: // vpkshus, vpkswus, vpkshss
37943 case 0x1CE: // vpkswss
37944 case 0x20E: case 0x24E: case 0x28E: // vupkhsb, vupkhsh, vupklsb
37945 case 0x2CE: // vupklsh
37946 case 0x30E: case 0x34E: case 0x3CE: // vpkpx, vupkhpx, vupklpx
37947 if (!allow_V
) goto decode_noV
;
37948 if (dis_av_pack( prefix
, theInstr
)) goto decode_success
;
37949 goto decode_failure
;
37951 case 0x403: case 0x443: case 0x483: // vabsdub, vabsduh, vabsduw
37952 if (!allow_V
) goto decode_noV
;
37953 if (dis_abs_diff( prefix
, theInstr
)) goto decode_success
;
37954 goto decode_failure
;
37956 case 0x44E: case 0x4CE: case 0x54E: // vpkudum, vpkudus, vpksdus
37957 case 0x5CE: case 0x64E: case 0x6cE: // vpksdss, vupkhsw, vupklsw
37958 if (!allow_isa_2_07
) goto decode_noP8
;
37959 if (dis_av_pack( prefix
, theInstr
)) goto decode_success
;
37960 goto decode_failure
;
37962 case 0x508: case 0x509: // vcipher, vcipherlast
37963 case 0x548: case 0x549: // vncipher, vncipherlast
37964 case 0x5C8: // vsbox
37965 if (!allow_isa_2_07
) goto decode_noP8
;
37966 if (dis_av_cipher( prefix
, theInstr
)) goto decode_success
;
37967 goto decode_failure
;
37969 /* AV Vector Extend Sign Instructions and
37970 * Vector Count Leading/Trailing zero Least-Significant bits Byte.
37971 * Vector Integer Negate Instructions
37973 case 0x602: // vextsb2w, vextsh2w, vextsb2d, vextsh2d, vextsw2d
37974 // vclzlsbb and vctzlsbb
37976 // vprtybw, vprtybd, vprtybq
37977 // vctzb, vctzh, vctzw, vctzd
37979 if (!allow_V
) goto decode_noV
;
37980 if ( !(allow_isa_3_1
)
37981 && (ifieldRegA( theInstr
) == 27) ) // vextsd2q
37982 goto decode_noIsa3_1
;
37983 if (dis_av_extend_sign_count_zero( prefix
, theInstr
,
37986 goto decode_success
;
37987 goto decode_failure
;
37989 case 0x642: // mtvsrbm, mtvsrhm, mtvswm, mtvsdm, mtvsqm, mtvsrbmi
37990 // vcntmbb, vcntmbh, vcntmbw, vcntmbd
37991 // vexpandbm, vexpandhm, vexpandwm, vexpanddm, vexpandqm
37992 // vextractbm, vextracthm, vextractwm, vextractdm, vextractqm
37993 if (!allow_V
) goto decode_noV
;
37994 if ( !(allow_isa_3_1
) ) goto decode_noIsa3_1
;
37995 if (dis_VSR_byte_mask( prefix
, theInstr
, abiinfo
))
37996 goto decode_success
;
37997 goto decode_failure
;
37999 case 0x6C2: case 0x682: // vshasigmaw, vshasigmad
38000 if (!allow_isa_2_07
) goto decode_noP8
;
38001 if (dis_av_hash( prefix
, theInstr
)) goto decode_success
;
38002 goto decode_failure
;
38004 case 0x702: case 0x742: // vclzb, vclzh
38005 case 0x782: case 0x7c2: // vclzw, vclzd
38006 if (!allow_isa_2_07
) goto decode_noP8
;
38007 if (dis_av_count_bitTranspose( prefix
, theInstr
, opc2
))
38008 goto decode_success
;
38009 goto decode_failure
;
38011 case 0x4CC: case 0x54D: // vgnb, vcfuged
38012 case 0x58D: case 0x5CD: // vpextd, vpdepd
38013 case 0x784: case 0x7C4: // vclzdm, vctzdm
38014 if ( !(allow_isa_3_1
) ) goto decode_noIsa3_1
;
38015 if (dis_vector_logical_mask_bits( prefix
, theInstr
, opc2
,
38017 goto decode_success
;
38018 goto decode_failure
;
38020 case 0x703: case 0x743: // vpopcntb, vpopcnth
38021 case 0x783: case 0x7c3: // vpopcntw, vpopcntd
38022 if (!allow_isa_2_07
) goto decode_noP8
;
38023 if (dis_av_count_bitTranspose( prefix
, theInstr
, opc2
))
38024 goto decode_success
;
38025 goto decode_failure
;
38027 case 0x50c: // vgbbd
38028 case 0x5cc: // vbpermd
38029 if (!allow_isa_2_07
) goto decode_noP8
;
38030 if (dis_av_count_bitTranspose( prefix
, theInstr
, opc2
))
38031 goto decode_success
;
38032 goto decode_failure
;
38034 case 0x140: case 0x100: // vaddcuq, vadduqm
38035 case 0x540: case 0x500: // vsubcuq, vsubuqm
38036 case 0x54C: // vbpermq
38037 if (!allow_V
) goto decode_noV
;
38038 if (dis_av_quad( prefix
, theInstr
, abiinfo
)) goto decode_success
;
38039 goto decode_failure
;
38042 break; // Fall through...
38045 opc2
= IFIELD(theInstr
, 0, 10);
38049 case 0x006: case 0x007: case 0x107: // vcmpequb, vcmpneb, vcmpnezb
38050 case 0x046: case 0x047: case 0x147: // vcmpequh, vcmpneh, vcmpnezh
38051 case 0x086: case 0x087: case 0x187: // vcmpequw, vcmpnew, vcmpnezw
38052 case 0x206: case 0x246: case 0x286: // vcmpgtub, vcmpgtuh, vcmpgtuw
38053 case 0x306: case 0x346: case 0x386: // vcmpgtsb, vcmpgtsh, vcmpgtsw
38054 if (!allow_V
) goto decode_noV
;
38055 if (dis_av_cmp( prefix
, theInstr
)) goto decode_success
;
38056 goto decode_failure
;
38058 case 0x0C7: // vcmpequd
38059 case 0x2C7: // vcmpgtud
38060 case 0x3C7: // vcmpgtsd
38061 if (!allow_isa_2_07
) goto decode_noP8
;
38062 if (dis_av_cmp( prefix
, theInstr
)) goto decode_success
;
38063 goto decode_failure
;
38065 /* AV Floating Point Compare */
38066 case 0x0C6: case 0x1C6: case 0x2C6: // vcmpeqfp, vcmpgefp, vcmpgtfp
38067 case 0x3C6: // vcmpbfp
38068 if (!allow_V
) goto decode_noV
;
38069 if (dis_av_fp_cmp( prefix
, theInstr
))
38070 goto decode_success
;
38071 goto decode_failure
;
38074 goto decode_failure
;
38079 goto decode_failure
;
38084 vex_printf("disInstr(ppc): found the Floating Point instruction 0x%x that\n"
38085 "can't be handled by Valgrind on this host. This instruction\n"
38086 "requires a host that supports Floating Point instructions.\n",
38088 goto not_supported
;
38092 vex_printf("disInstr(ppc): found an AltiVec or an e500 instruction 0x%x\n"
38093 "that can't be handled by Valgrind. If this instruction is an\n"
38094 "Altivec instruction, Valgrind must be run on a host that supports"
38095 "AltiVec instructions. If the application was compiled for e500, then\n"
38096 "unfortunately Valgrind does not yet support e500 instructions.\n",
38098 goto not_supported
;
38100 vassert(!allow_VX
);
38102 vex_printf("disInstr(ppc): found the instruction 0x%x that is defined in the\n"
38103 "Power ISA 2.06 ABI but can't be handled by Valgrind on this host.\n"
38104 "This instruction \nrequires a host that supports the ISA 2.06 ABI.\n",
38106 goto not_supported
;
38108 vassert(!allow_FX
);
38110 vex_printf("disInstr(ppc): found the General Purpose-Optional instruction 0x%x\n"
38111 "that can't be handled by Valgrind on this host. This instruction\n"
38112 "requires a host that supports the General Purpose-Optional instructions.\n",
38114 goto not_supported
;
38116 vassert(!allow_GX
);
38118 vex_printf("disInstr(ppc): found the Graphics-Optional instruction 0x%x\n"
38119 "that can't be handled by Valgrind on this host. This instruction\n"
38120 "requires a host that supports the Graphic-Optional instructions.\n",
38122 goto not_supported
;
38124 vassert(!allow_DFP
);
38126 vex_printf("disInstr(ppc): found the decimal floating point (DFP) instruction 0x%x\n"
38127 "that can't be handled by Valgrind on this host. This instruction\n"
38128 "requires a host that supports DFP instructions.\n",
38130 goto not_supported
;
38132 vassert(!allow_isa_2_07
);
38134 vex_printf("disInstr(ppc): found the Power 8 instruction 0x%x that can't be handled\n"
38135 "by Valgrind on this host. This instruction requires a host that\n"
38136 "supports Power 8 instructions.\n",
38138 goto not_supported
;
38141 vassert(!allow_isa_3_0
);
38143 vex_printf("disInstr(ppc): found the Power 9 instruction 0x%x that can't be handled\n"
38144 "by Valgrind on this host. This instruction requires a host that\n"
38145 "supports Power 9 instructions.\n",
38147 goto not_supported
;
38150 vassert(!allow_isa_3_1
);
38152 vex_printf("disInstr(ppc): found the Power 10 instruction 0x%x that can't be handled\n"
38153 "by Valgrind on this host. This instruction requires a host that\n"
38154 "supports ISA 3.1 instructions.\n", theInstr
);
38155 goto not_supported
;
38158 /* All decode failures end up here. */
38159 opc1
= ifieldOPC(theInstr
);
38160 opc2
= (theInstr
) & 0x7FF;
38163 if (prefix_instruction( prefix
)) {
38164 vex_printf("disInstr(ppc): unhandled prefix instruction: "
38165 "prefix = 0x%x, theInstr 0x%x\n", prefix
, theInstr
);
38166 vex_printf(" primary %d(0x%x), secondary %u(0x%x)\n",
38167 opc1
, opc1
, opc2
, opc2
);
38170 vex_printf("disInstr(ppc): unhandled instruction: "
38171 "0x%x\n", theInstr
);
38172 vex_printf(" primary %d(0x%x), secondary %u(0x%x)\n",
38173 opc1
, opc1
, opc2
, opc2
);
38178 /* Tell the dispatcher that this insn cannot be decoded, and so has
38179 not been executed, and (is currently) the next to be executed.
38180 CIA should be up-to-date since it made so at the start of each
38181 insn, but nevertheless be paranoid and update it again right
38183 putGST( PPC_GST_CIA
, mkSzImm(ty
, guest_CIA_curr_instr
) );
38185 dres
.whatNext
= Dis_StopHere
;
38186 dres
.jk_StopHere
= Ijk_NoDecode
;
38188 } /* switch (opc) for the main (primary) opcode switch. */
38191 /* All decode successes end up here. */
38192 switch (dres
.whatNext
) {
38194 /* Update the guest current instruction address (CIA) by size of
38195 the instruction just executed. */
38196 putGST( PPC_GST_CIA
, mkSzImm(ty
, guest_CIA_curr_instr
+ inst_size
));
38205 if (dres
.len
== 0) {
38206 dres
.len
= inst_size
; //Tell Valgrind the size of the instruction just excuted
38208 vassert(dres
.len
== 20);
38217 /*------------------------------------------------------------*/
38218 /*--- Top-level fn ---*/
38219 /*------------------------------------------------------------*/
38221 /* Disassemble a single instruction into IR. The instruction
38222 is located in host memory at &guest_code[delta]. */
38224 DisResult
disInstr_PPC ( IRSB
* irsb_IN
,
38225 const UChar
* guest_code_IN
,
38228 VexArch guest_arch
,
38229 const VexArchInfo
* archinfo
,
38230 const VexAbiInfo
* abiinfo
,
38231 VexEndness host_endness_IN
,
38232 Bool sigill_diag_IN
)
38236 UInt mask32
, mask64
;
38237 UInt hwcaps_guest
= archinfo
->hwcaps
;
38239 vassert(guest_arch
== VexArchPPC32
|| guest_arch
== VexArchPPC64
);
38241 /* global -- ick */
38242 mode64
= guest_arch
== VexArchPPC64
;
38243 ty
= mode64
? Ity_I64
: Ity_I32
;
38244 if (!mode64
&& (host_endness_IN
== VexEndnessLE
)) {
38245 vex_printf("disInstr(ppc): Little Endian 32-bit mode is not supported\n");
38247 dres
.whatNext
= Dis_StopHere
;
38248 dres
.jk_StopHere
= Ijk_NoDecode
;
38249 dres
.hint
= Dis_HintNone
;
38253 /* do some sanity checks */
38254 mask32
= VEX_HWCAPS_PPC32_F
| VEX_HWCAPS_PPC32_V
38255 | VEX_HWCAPS_PPC32_FX
| VEX_HWCAPS_PPC32_GX
| VEX_HWCAPS_PPC32_VX
38256 | VEX_HWCAPS_PPC32_DFP
| VEX_HWCAPS_PPC32_ISA2_07
;
38258 mask64
= VEX_HWCAPS_PPC64_V
| VEX_HWCAPS_PPC64_FX
38259 | VEX_HWCAPS_PPC64_GX
| VEX_HWCAPS_PPC64_VX
| VEX_HWCAPS_PPC64_DFP
38260 | VEX_HWCAPS_PPC64_ISA2_07
| VEX_HWCAPS_PPC64_ISA3_0
38261 | VEX_HWCAPS_PPC64_ISA3_1
;
38264 vassert((hwcaps_guest
& mask32
) == 0);
38266 vassert((hwcaps_guest
& mask64
) == 0);
38269 /* Set globals (see top of this file) */
38270 guest_code
= guest_code_IN
;
38272 host_endness
= host_endness_IN
;
38274 guest_CIA_curr_instr
= mkSzAddr(ty
, guest_IP
);
38275 guest_CIA_bbstart
= mkSzAddr(ty
, guest_IP
- delta
);
38277 dres
= disInstr_PPC_WRK ( delta
, archinfo
, abiinfo
, sigill_diag_IN
);
38282 /*--------------------------------------------------------------------*/
38283 /*--- end guest_ppc_toIR.c ---*/
38284 /*--------------------------------------------------------------------*/