Bug 439685 compiler warning in callgrind/main.c
[valgrind.git] / VEX / priv / guest_ppc_toIR.c
blob16181768e4e1507ae2bd441713ecbbe30d6ca6ec
2 /*--------------------------------------------------------------------*/
3 /*--- begin guest_ppc_toIR.c ---*/
4 /*--------------------------------------------------------------------*/
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
10 Copyright (C) 2004-2017 OpenWorks LLP
11 info@open-works.net
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.
34 /* TODO 18/Nov/05:
36 Spot rld... cases which are simply left/right shifts and emit
37 Shl64/Shr64 accordingly.
39 Altivec
40 - datastream insns
41 - lvxl,stvxl: load/store with 'least recently used' hint
42 - vexptefp, vlogefp
44 LIMITATIONS:
46 Various, including:
48 - Some invalid forms of lswi and lswx are accepted when they should
49 not be.
51 - Floating Point:
52 - All exceptions disabled in FPSCR
53 - condition codes not set in FPSCR
55 - Altivec floating point:
56 - vmaddfp, vnmsubfp
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
59 (lowest bit only).
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
124 * of the register.
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,
163 * vrfip, vrfim
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
168 * state.
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
176 * like.
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
182 * VSCR[NJ].guest.
186 /* Translates PPC32/64 code to IR. */
188 /* References
190 #define PPC32
191 "PowerPC Microprocessor Family:
192 The Programming Environments Manual for 32-Bit Microprocessors"
193 02/21/2000
194 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2
196 #define PPC64
197 "PowerPC Microprocessor Family:
198 Programming Environments Manual for 64-Bit Microprocessors"
199 06/10/2003
200 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/F7E732FF811F783187256FDD004D3797
202 #define AV
203 "PowerPC Microprocessor Family:
204 AltiVec(TM) Technology Programming Environments Manual"
205 07/10/2003
206 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/FBFA164F824370F987256D6A006F424D
209 #include "libvex_basictypes.h"
210 #include "libvex_ir.h"
211 #include "libvex.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 /*------------------------------------------------------------*/
222 /*--- Globals ---*/
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
228 given insn. */
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
240 translated. */
241 static Addr64 guest_CIA_curr_instr;
243 /* The IRSB* into which we're generating code. */
244 static IRSB* irsb;
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]);
263 } else {
264 /* Simple; "& f" points directly at the code for f. */
265 return 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. */
298 #define DIPn(flag) \
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 /*------------------------------------------------------------*/
511 typedef enum {
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
535 * needed.
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.
541 PPC_GST_ACC_0_r1,
542 PPC_GST_ACC_0_r2,
543 PPC_GST_ACC_0_r3,
544 PPC_GST_ACC_1_r0,
545 PPC_GST_ACC_1_r1,
546 PPC_GST_ACC_1_r2,
547 PPC_GST_ACC_1_r3,
548 PPC_GST_ACC_2_r0,
549 PPC_GST_ACC_2_r1,
550 PPC_GST_ACC_2_r2,
551 PPC_GST_ACC_2_r3,
552 PPC_GST_ACC_3_r0,
553 PPC_GST_ACC_3_r1,
554 PPC_GST_ACC_3_r2,
555 PPC_GST_ACC_3_r3,
556 PPC_GST_ACC_4_r0,
557 PPC_GST_ACC_4_r1,
558 PPC_GST_ACC_4_r2,
559 PPC_GST_ACC_4_r3,
560 PPC_GST_ACC_5_r0,
561 PPC_GST_ACC_5_r1,
562 PPC_GST_ACC_5_r2,
563 PPC_GST_ACC_5_r3,
564 PPC_GST_ACC_6_r0,
565 PPC_GST_ACC_6_r1,
566 PPC_GST_ACC_6_r2,
567 PPC_GST_ACC_6_r3,
568 PPC_GST_ACC_7_r0,
569 PPC_GST_ACC_7_r1,
570 PPC_GST_ACC_7_r2,
571 PPC_GST_ACC_7_r3,
572 PPC_GST_MAX
573 } PPC_GST;
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 )
594 UInt m1, m2, mask;
595 vassert(begin < 32);
596 vassert(end < 32);
597 m1 = ((UInt)(-1)) << begin;
598 m2 = ((UInt)(-1)) << end << 1;
599 mask = m1 ^ m2;
600 if (begin > end) mask = ~mask; // wrap mask
601 return mask;
604 static ULong MASK64( UInt begin, UInt end )
606 ULong m1, m2, mask;
607 vassert(begin < 64);
608 vassert(end < 64);
609 m1 = ((ULong)(-1)) << begin;
610 m2 = ((ULong)(-1)) << end << 1;
611 mask = m1 ^ m2;
612 if (begin > end) mask = ~mask; // wrap mask
613 return 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 )
680 UInt w = 0;
681 if (host_endness == VexEndnessBE) {
682 w = (w << 8) | p[0];
683 w = (w << 8) | p[1];
684 w = (w << 8) | p[2];
685 w = (w << 8) | p[3];
686 } else {
687 w = (w << 8) | p[3];
688 w = (w << 8) | p[2];
689 w = (w << 8) | p[1];
690 w = (w << 8) | p[0];
692 return w;
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) );
713 else
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);
776 else
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);
785 else
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,
806 IRTemp t3 )
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,
816 mkexpr( t0 ),
817 binop( Iop_OrV128, mkexpr( t1 ), mkexpr( t2 ) ) );
820 static inline IRExpr* mkOr4_V128( IRTemp t0, IRTemp t1, IRTemp t2,
821 IRTemp t3 )
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,
829 IRExpr* t3 )
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,
917 /*OUTs*/
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) );
936 assign( *t3,
937 unop( Iop_F32toF64,
938 unop( Iop_ReinterpI32asF32,
939 unop( Iop_64HIto32, mkexpr( hi64 ) ) ) ) );
940 assign( *t2,
941 unop( Iop_F32toF64,
942 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( hi64 ) ) ) ) );
943 assign( *t1,
944 unop( Iop_F32toF64,
945 unop( Iop_ReinterpI32asF32,
946 unop( Iop_64HIto32, mkexpr( lo64 ) ) ) ) );
947 assign( *t0,
948 unop( Iop_F32toF64,
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,
955 /*OUTs*/
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,
982 /*OUTs*/
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,
1008 /*OUTs*/
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 )
1036 return
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,
1047 binop( Iop_AndV128,
1048 binop( Iop_ShrV128,
1049 mkexpr( vB ),
1050 unop( Iop_64to8,
1051 binop( Iop_Mul64, index,
1052 mkU64( 8 ) ) ) ),
1053 binop( Iop_64HLtoV128,
1054 mkU64( 0x0 ),
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,
1070 binop( Iop_Mul64,
1071 binop( Iop_And64,
1072 index,
1073 mkU64( index_mask ) ),
1074 mkU64( 8 ) ) ) );
1075 assign( tmp_mask, binop( Iop_ShlV128,
1076 binop( Iop_64HLtoV128,
1077 mkU64( 0x0 ),
1078 mask ),
1079 mkexpr( shift) ) );
1080 assign( tmp_not_mask, unop( Iop_NotV128, mkexpr( tmp_mask ) ) );
1081 return binop( Iop_OrV128,
1082 binop( Iop_AndV128,
1083 mkexpr( vSrc ),
1084 mkexpr( tmp_not_mask ) ),
1085 binop( Iop_AndV128,
1086 binop( Iop_ShlV128,
1087 binop( Iop_64HLtoV128,
1088 mkU64( 0x0 ),
1089 bits ),
1090 mkexpr( shift) ),
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,
1106 binop( Iop_Mul64,
1107 binop( Iop_And64,
1108 mkU64( 0xF ),
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,
1115 unop( Iop_64to1,
1116 binop( Iop_Shr64,
1117 mkexpr( byte_index ),
1118 mkU8( 4 ) ) ) ) );
1120 assign( reg_select, binop( Iop_64HLtoV128,
1121 mkexpr( select_tmp ),
1122 mkexpr( select_tmp ) ) );
1124 assign( src_tmp,
1125 binop( Iop_OrV128,
1126 binop( Iop_AndV128,
1127 mkexpr( reg_select ),
1128 binop( Iop_ShrV128,
1129 mkexpr( vA ),
1130 mkexpr( shift ) ) ),
1131 binop( Iop_AndV128,
1132 unop( Iop_NotV128, mkexpr( reg_select ) ),
1133 binop( Iop_ShrV128,
1134 mkexpr( vB ),
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));
1154 return IRExpr_ITE(
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 */
1159 mkexpr(lo32),
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));
1176 return IRExpr_ITE(
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 */
1180 mkexpr(lo32),
1181 /* else: positive saturate -> 0xFFFFFFFF */
1182 mkU32(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,
1194 binop(Iop_32HLto64,
1195 mkQNarrow64Sto32( t3 ),
1196 mkQNarrow64Sto32( t2 )),
1197 binop(Iop_32HLto64,
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,
1211 binop(Iop_32HLto64,
1212 mkQNarrow64Uto32( t3 ),
1213 mkQNarrow64Uto32( t2 )),
1214 binop(Iop_32HLto64,
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 )
1265 Int adj;
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 ||
1272 op8 == Iop_Not8 );
1273 adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3));
1274 return adj + op8;
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 ?
1282 (Addr64)addr :
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)) :
1317 mkU32(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 )
1342 IROp op;
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 )
1351 IROp op;
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);
1361 if (ty == Ity_I32)
1362 return src;
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?
1375 switch (archreg) {
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);
1408 default: break;
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) {
1436 switch (archreg) {
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;
1469 default: break;
1471 } else {
1472 switch (archreg) {
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);
1505 default: break;
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) {
1527 IRExpr *e;
1528 vassert( archreg < 32 );
1529 e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D64 );
1530 return e;
1532 static IRExpr* getDReg32(UInt archreg) {
1533 IRExpr *e;
1534 vassert( archreg < 32 );
1535 e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D32 );
1536 return e;
1539 /* Read a floating point register pair and combine their contents into a
1540 128-bit value */
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);
1579 switch (archreg) {
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);
1644 default: break;
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);
1654 switch (archreg) {
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);
1687 default: break;
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 )
1739 switch (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 )
1754 switch (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)");
1767 typedef enum {
1768 _placeholder0,
1769 _placeholder1,
1770 _placeholder2,
1771 BYTE,
1772 HWORD,
1773 WORD,
1774 DWORD
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,
1787 byte: data_type = 3
1788 half word: data_type = 4
1789 word: data_type = 5
1790 double word: data_type = 6 (not supported for 32-bit type)
1792 Int shift[6];
1793 _popcount_data_type idx, i;
1794 IRTemp mask[6];
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)));
1805 return res;
1808 if (ty == Ity_I32 && data_type == WORD) {
1809 IRTemp res = newTemp(Ity_I32);
1810 assign(res, unop(Iop_PopCount32, mkexpr(src)));
1811 return res;
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));
1827 old = src;
1828 for (i = 0; i < data_type; i++) {
1829 nyu = newTemp(ty);
1830 assign(nyu,
1831 binop(Iop_Add32,
1832 binop(Iop_And32,
1833 mkexpr(old),
1834 mkexpr(mask[i])),
1835 binop(Iop_And32,
1836 binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
1837 mkexpr(mask[i]))));
1838 old = nyu;
1840 return nyu;
1843 // else, ty == Ity_I64
1844 vassert(mode64);
1846 for (i = 0; i < DWORD; i++) {
1847 mask[i] = newTemp( Ity_I64 );
1848 shift[i] = 1 << i;
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 ) );
1856 old = src;
1857 for (i = 0; i < data_type; i++) {
1858 nyu = newTemp( Ity_I64 );
1859 assign( nyu,
1860 binop( Iop_Add64,
1861 binop( Iop_And64, mkexpr( old ), mkexpr( mask[i] ) ),
1862 binop( Iop_And64,
1863 binop( Iop_Shr64, mkexpr( old ), mkU8( shift[i] ) ),
1864 mkexpr( mask[i] ) ) ) );
1865 old = nyu;
1867 return nyu;
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);
1877 vassert(!mode64);
1879 assign(retval,
1880 unop(Iop_32Uto64,
1881 binop(Iop_Add32,
1882 unop(Iop_PopCount32, mkexpr(src1)),
1883 unop(Iop_PopCount32, mkexpr(src2)))));
1884 return retval;
1888 // ROTL(src32/64, rot_amt5/6)
1889 static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src,
1890 IRExpr* rot_amt )
1892 IRExpr *mask, *rot;
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)));
1901 } else {
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;
1921 vassert(rA < 32);
1922 vassert(rB < 32);
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;
1930 vassert(rA < 32);
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;
1939 vassert(rA < 32);
1940 if (rA == 0) {
1941 return mkSzImm(ty, 0);
1942 } else {
1943 return getIReg(rA);
1947 /* Standard effective address calc: (rA|0) + rB */
1948 static IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB )
1950 vassert(rA < 32);
1951 vassert(rB < 32);
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;
1959 vassert(rA < 32);
1960 if (rA == 0) {
1961 return mkSzExtendS16(ty, simm16);
1962 } else {
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;
1972 ULong mask;
1973 switch (align) {
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
1978 default:
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);
1994 if (mode64) {
1995 vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64);
1996 stmt(
1997 IRStmt_Exit(
1998 binop(Iop_CmpNE64,
1999 binop(Iop_And64, mkexpr(addr), mkU64(align-1)),
2000 mkU64(0)),
2001 Ijk_SigBUS,
2002 IRConst_U64( guest_CIA_curr_instr ), OFFB_CIA
2005 } else {
2006 vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32);
2007 stmt(
2008 IRStmt_Exit(
2009 binop(Iop_CmpNE32,
2010 binop(Iop_And32, mkexpr(addr), mkU32(align-1)),
2011 mkU32(0)),
2012 Ijk_SigBUS,
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);
2031 vassert(szB >= 0);
2032 if (szB > 0) {
2033 if (mode64) {
2034 vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64);
2035 stmt( IRStmt_AbiHint(
2036 binop(Iop_Sub64, getIReg(1), mkU64(szB)),
2037 szB,
2038 mkexpr(nia)
2040 } else {
2041 vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32);
2042 stmt( IRStmt_AbiHint(
2043 binop(Iop_Sub32, getIReg(1), mkU32(szB)),
2044 szB,
2045 mkexpr(nia)
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:
2072 let n = BI / 4
2073 off = BI % 4
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 )
2088 vassert(cr < 8);
2089 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2090 stmt( IRStmt_Put(guestCR321offset(cr), e) );
2093 static void putCR0 ( UInt cr, IRExpr* e )
2095 vassert(cr < 8);
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
2104 * 32 bit value.
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.
2113 IRExpr* tmp;
2115 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I32);
2117 /* Get the FPCC bit field */
2118 tmp = binop( Iop_And32,
2119 mkU32( 0xF ),
2120 unop( Iop_8Uto32, IRExpr_Get( OFFB_C_FPCC, Ity_I8 ) ) );
2122 stmt( IRStmt_Put( OFFB_C_FPCC,
2123 unop( Iop_32to8,
2124 binop( Iop_Or32, tmp,
2125 binop( Iop_Shl32,
2126 binop( Iop_And32, mkU32( 0x1 ), e ),
2127 mkU8( 4 ) ) ) ) ) );
2130 static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr )
2132 vassert(cr < 8);
2133 return IRExpr_Get(guestCR0offset(cr), Ity_I8);
2136 static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr )
2138 vassert(cr < 8);
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
2144 to be zero. */
2145 static IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi )
2147 UInt n = bi / 4;
2148 UInt off = bi % 4;
2149 vassert(bi < 32);
2150 if (off == 3) {
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));
2155 } else {
2156 /* Fetch the <, > or == bit for this CR field */
2157 return binop( Iop_And32,
2158 binop( Iop_Shr32,
2159 unop(Iop_8Uto32, getCR321(n)),
2160 mkU8(toUChar(3-off)) ),
2161 mkU32(1) );
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 )
2169 UInt n, off;
2170 IRExpr* safe;
2171 vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32);
2172 safe = binop(Iop_And32, bit, mkU32(1));
2173 n = bi / 4;
2174 off = bi % 4;
2175 vassert(bi < 32);
2176 if (off == 3) {
2177 /* This is the SO bit for this CR field */
2178 putCR0(n, unop(Iop_32to8, safe));
2179 } else {
2180 off = 3 - off;
2181 vassert(off == 1 || off == 2 || off == 3);
2182 putCR321(
2184 unop( Iop_32to8,
2185 binop( Iop_Or32,
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. */
2204 static
2205 IRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where )
2207 UInt n = bi / 4;
2208 UInt off = bi % 4;
2209 vassert(bi < 32);
2210 if (off == 3) {
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. */
2214 *where = 0;
2215 return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
2216 } else {
2217 /* Fetch the <, > or == bit for this CR field */
2218 *where = 3-off;
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);
2233 if (mode64) {
2234 putCR321( 0, unop(Iop_64to8,
2235 binop(Iop_CmpORD64S, result, mkU64(0))) );
2236 } else {
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.
2246 * */
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);
2266 if (mode64) {
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)));
2275 } else {
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,
2285 binop(Iop_OrV128,
2286 binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)),
2287 binop(Iop_OrV128, mkexpr(v2), mkexpr(v3))));
2288 assign(overlappedAnded,
2289 binop(Iop_AndV128,
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);
2297 if (mode64) {
2298 assign(rZeroes,
2299 unop(Iop_1Uto8,
2300 binop(Iop_CmpEQ64,
2301 mkU64(0),
2302 unop(Iop_V128to64, mkexpr(overlappedOred)))));
2303 assign(rOnes,
2304 unop(Iop_1Uto8,
2305 binop(Iop_CmpEQ64,
2306 mkU64(0),
2307 unop(Iop_Not64,
2308 unop(Iop_V128to64, mkexpr(overlappedAnded))))));
2309 } else {
2310 assign(rZeroes,
2311 unop(Iop_1Uto8,
2312 binop(Iop_CmpEQ32,
2313 mkU32(0),
2314 unop(Iop_V128to32, mkexpr(overlappedOred)))));
2315 assign(rOnes,
2316 unop(Iop_1Uto8,
2317 binop(Iop_CmpEQ32,
2318 mkU32(0),
2319 unop(Iop_Not32,
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))) );
2330 } else {
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.
2343 IRTemp neg;
2344 IROp opAND, opOR, opSHL, opXto1, op1UtoX;
2346 vassert( ( size == Ity_I32 ) || ( size == Ity_I64 ) );
2348 if ( size == Ity_I32 ) {
2349 opSHL = Iop_Shl32;
2350 opAND = Iop_And32;
2351 opOR = Iop_Or32;
2352 opXto1 = Iop_32to1;
2353 op1UtoX = Iop_1Uto32;
2354 neg = newTemp( Ity_I32 );
2356 } else {
2357 opSHL = Iop_Shl64;
2358 opAND = Iop_And64;
2359 opOR = Iop_Or64;
2360 opXto1 = Iop_64to1;
2361 op1UtoX = Iop_1Uto64;
2362 neg = newTemp( Ity_I64 );
2365 assign( neg, unop( op1UtoX, mkNOT1( unop( opXto1,
2366 mkexpr ( pos ) ) ) ) );
2368 return binop( opOR,
2369 binop( opSHL, mkexpr( NaN ), mkU8( 6 ) ),
2370 binop( opOR,
2371 binop( opOR,
2372 binop( opOR,
2373 binop( opSHL,
2374 binop( opAND,
2375 mkexpr( pos ),
2376 mkexpr( inf ) ),
2377 mkU8( 5 ) ),
2378 binop( opSHL,
2379 binop( opAND,
2380 mkexpr( neg ),
2381 mkexpr( inf ) ),
2382 mkU8( 4 ) ) ),
2383 binop( opOR,
2384 binop( opSHL,
2385 binop( opAND,
2386 mkexpr( pos ),
2387 mkexpr( zero ) ),
2388 mkU8( 3 ) ),
2389 binop( opSHL,
2390 binop( opAND,
2391 mkexpr( neg ),
2392 mkexpr( zero ) ),
2393 mkU8( 2 ) ) ) ),
2394 binop( opOR,
2395 binop( opSHL,
2396 binop( opAND,
2397 mkexpr( pos ),
2398 mkexpr( dnorm ) ),
2399 mkU8( 1 ) ),
2400 binop( opAND,
2401 mkexpr( neg ),
2402 mkexpr( dnorm ) ) ) ) );
2405 /*------------------------------------------------------------*/
2406 /*--- Helpers for XER flags. ---*/
2407 /*------------------------------------------------------------*/
2409 static void putXER_SO ( IRExpr* e )
2411 IRExpr* so;
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] */
2420 IRExpr* 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] */
2429 IRExpr* ov;
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] */
2442 IRExpr* 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] */
2451 IRExpr* ca;
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 )
2463 IRExpr* bc;
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 )
2533 IRTemp t64;
2534 IRExpr* xer_ov;
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))
2547 #define NOT(_jj) \
2548 unop(Iop_Not32, (_jj))
2550 switch (op) {
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))
2555 xer_ov
2556 = AND3( XOR3(argL,argR,mkU32(-1)),
2557 XOR2(argL,res),
2558 mkU32(INT32_MIN) );
2559 /* xer_ov can only be 0 or 1<<31 */
2560 xer_ov
2561 = binop(Iop_Shr32, xer_ov, mkU8(31) );
2562 break;
2564 case /* 2 */ PPCG_FLAG_OP_DIVW:
2565 /* (argL == INT32_MIN && argR == -1) || argR == 0 */
2566 xer_ov
2567 = mkOR1(
2568 mkAND1(
2569 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)),
2570 binop(Iop_CmpEQ32, argR, mkU32(-1))
2572 binop(Iop_CmpEQ32, argR, mkU32(0) )
2574 xer_ov
2575 = unop(Iop_1Uto32, xer_ov);
2576 break;
2578 case /* 3 */ PPCG_FLAG_OP_DIVWU:
2579 /* argR == 0 */
2580 xer_ov
2581 = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0)));
2582 break;
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) );
2589 xer_ov
2590 = binop( Iop_CmpNE32,
2591 unop(Iop_64HIto32, mkexpr(t64)),
2592 binop( Iop_Sar32,
2593 unop(Iop_64to32, mkexpr(t64)),
2594 mkU8(31))
2596 xer_ov
2597 = unop(Iop_1Uto32, xer_ov);
2598 break;
2600 case /* 5 */ PPCG_FLAG_OP_NEG:
2601 /* argL == INT32_MIN */
2602 xer_ov
2603 = unop( Iop_1Uto32,
2604 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) );
2605 break;
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; */
2611 xer_ov
2612 = AND3( XOR3(NOT(argL),argR,mkU32(-1)),
2613 XOR2(NOT(argL),res),
2614 mkU32(INT32_MIN) );
2615 /* xer_ov can only be 0 or 1<<31 */
2616 xer_ov
2617 = binop(Iop_Shr32, xer_ov, mkU8(31) );
2618 break;
2620 case PPCG_FLAG_OP_DIVWEU:
2621 xer_ov
2622 = binop( Iop_Or32,
2623 unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
2624 unop( Iop_1Uto32, binop( Iop_CmpLT32U, argR, argL ) ) );
2625 break;
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 ) ) ) ) ) );
2638 break;
2642 default:
2643 vex_printf("calculate_XER_OV_32: op = %u\n", op);
2644 vpanic("calculate_XER_OV_32(ppc)");
2647 return xer_ov;
2649 # undef INT32_MIN
2650 # undef AND3
2651 # undef XOR3
2652 # undef XOR2
2653 # undef NOT
2656 static void set_XER_OV_OV32_32( UInt op, IRExpr* res,
2657 IRExpr* argL, IRExpr* argR )
2659 IRExpr* xer_ov;
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 )
2676 IRExpr* xer_ov;
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))
2689 #define NOT(_jj) \
2690 unop(Iop_Not64, (_jj))
2692 switch (op) {
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))
2697 xer_ov
2698 = AND3( XOR3(argL,argR,mkU64(-1)),
2699 XOR2(argL,res),
2700 mkU64(INT64_MIN) );
2701 /* xer_ov can only be 0 or 1<<63 */
2702 xer_ov
2703 = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
2704 break;
2706 case /* 2 */ PPCG_FLAG_OP_DIVW:
2707 /* (argL == INT64_MIN && argR == -1) || argR == 0 */
2708 xer_ov
2709 = mkOR1(
2710 mkAND1(
2711 binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)),
2712 binop(Iop_CmpEQ64, argR, mkU64(-1))
2714 binop(Iop_CmpEQ64, argR, mkU64(0) )
2716 break;
2718 case /* 3 */ PPCG_FLAG_OP_DIVWU:
2719 /* argR == 0 */
2720 xer_ov
2721 = binop(Iop_CmpEQ64, argR, mkU64(0));
2722 break;
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 */
2727 xer_ov
2728 = binop( Iop_CmpNE32,
2729 unop(Iop_64HIto32, res),
2730 binop( Iop_Sar32,
2731 unop(Iop_64to32, res),
2732 mkU8(31))
2734 break;
2737 case /* 5 */ PPCG_FLAG_OP_NEG:
2738 /* argL == INT64_MIN */
2739 xer_ov
2740 = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN));
2741 break;
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; */
2747 xer_ov
2748 = AND3( XOR3(NOT(argL),argR,mkU64(-1)),
2749 XOR2(NOT(argL),res),
2750 mkU64(INT64_MIN) );
2751 /* xer_ov can only be 0 or 1<<63 */
2752 xer_ov
2753 = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
2754 break;
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.
2763 xer_ov
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 ) ) ) ) );
2768 break;
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 ) );
2774 break;
2776 case /* 18 */ PPCG_FLAG_OP_MULLD: {
2777 IRTemp t128;
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) );
2782 xer_ov
2783 = binop( Iop_CmpNE64,
2784 unop(Iop_128HIto64, mkexpr(t128)),
2785 binop( Iop_Sar64,
2786 unop(Iop_128to64, mkexpr(t128)),
2787 mkU8(63))
2789 break;
2792 default:
2793 vex_printf("calculate_XER_OV_64: op = %u\n", op);
2794 vpanic("calculate_XER_OV_64(ppc64)");
2797 return xer_ov;
2799 # undef INT64_MIN
2800 # undef AND3
2801 # undef XOR3
2802 # undef XOR2
2803 # undef NOT
2806 static void set_XER_OV_64( UInt op, IRExpr* res,
2807 IRExpr* argL, IRExpr* argR )
2809 IRExpr* xer_ov;
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 );
2838 } else {
2839 IRExpr* xer_ov_32;
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) );
2846 update_SO();
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 )
2857 IRExpr* xer_ca;
2859 switch (op) {
2860 case /* 0 */ PPCG_FLAG_OP_ADD:
2861 /* res <u argL */
2862 xer_ca
2863 = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL));
2864 break;
2866 case /* 1 */ PPCG_FLAG_OP_ADDE:
2867 /* res <u argL || (old_ca==1 && res==argL) */
2868 xer_ca
2869 = mkOR1(
2870 binop(Iop_CmpLT32U, res, argL),
2871 mkAND1(
2872 binop(Iop_CmpEQ32, oldca, mkU32(1)),
2873 binop(Iop_CmpEQ32, res, argL)
2876 xer_ca
2877 = unop(Iop_1Uto32, xer_ca);
2878 break;
2880 case /* 8 */ PPCG_FLAG_OP_SUBFE:
2881 /* res <u argR || (old_ca==1 && res==argR) */
2882 xer_ca
2883 = mkOR1(
2884 binop(Iop_CmpLT32U, res, argR),
2885 mkAND1(
2886 binop(Iop_CmpEQ32, oldca, mkU32(1)),
2887 binop(Iop_CmpEQ32, res, argR)
2890 xer_ca
2891 = unop(Iop_1Uto32, xer_ca);
2892 break;
2894 case /* 7 */ PPCG_FLAG_OP_SUBFC:
2895 case /* 9 */ PPCG_FLAG_OP_SUBFI:
2896 /* res <=u argR */
2897 xer_ca
2898 = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR));
2899 break;
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
2904 bit of argL. */
2905 /* This term valid for shift amount < 32 only */
2906 xer_ca
2907 = binop(
2908 Iop_And32,
2909 binop(Iop_Sar32, argL, mkU8(31)),
2910 binop( Iop_And32,
2911 argL,
2912 binop( Iop_Sub32,
2913 binop(Iop_Shl32, mkU32(1),
2914 unop(Iop_32to8,argR)),
2915 mkU32(1) )
2918 xer_ca
2919 = IRExpr_ITE(
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)))
2927 break;
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 */
2936 xer_ca
2937 = binop(
2938 Iop_And32,
2939 binop(Iop_Sar32, argL, mkU8(31)),
2940 binop( Iop_And32,
2941 argL,
2942 binop( Iop_Sub32,
2943 binop(Iop_Shl32, mkU32(1),
2944 unop(Iop_32to8,argR)),
2945 mkU32(1) )
2948 xer_ca
2949 = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)));
2950 break;
2952 default:
2953 vex_printf("set_XER_CA: op = %u\n", op);
2954 vpanic("set_XER_CA(ppc)");
2957 return xer_ca;
2960 static void set_XER_CA_32 ( UInt op, IRExpr* res,
2961 IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2963 IRExpr* xer_ca;
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 )
2985 IRExpr* xer_ca;
2987 switch (op) {
2988 case /* 0 */ PPCG_FLAG_OP_ADD:
2989 /* res <u argL */
2990 xer_ca
2991 = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL));
2992 break;
2994 case /* 1 */ PPCG_FLAG_OP_ADDE:
2995 /* res <u argL || (old_ca==1 && res==argL) */
2996 xer_ca
2997 = mkOR1(
2998 binop(Iop_CmpLT64U, res, argL),
2999 mkAND1(
3000 binop(Iop_CmpEQ64, oldca, mkU64(1)),
3001 binop(Iop_CmpEQ64, res, argL)
3004 xer_ca
3005 = unop(Iop_1Uto32, xer_ca);
3006 break;
3008 case /* 8 */ PPCG_FLAG_OP_SUBFE:
3009 /* res <u argR || (old_ca==1 && res==argR) */
3010 xer_ca
3011 = mkOR1(
3012 binop(Iop_CmpLT64U, res, argR),
3013 mkAND1(
3014 binop(Iop_CmpEQ64, oldca, mkU64(1)),
3015 binop(Iop_CmpEQ64, res, argR)
3018 xer_ca
3019 = unop(Iop_1Uto32, xer_ca);
3020 break;
3022 case /* 7 */ PPCG_FLAG_OP_SUBFC:
3023 case /* 9 */ PPCG_FLAG_OP_SUBFI:
3024 /* res <=u argR */
3025 xer_ca
3026 = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR));
3027 break;
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
3033 bit of argL. */
3034 /* This term valid for shift amount < 31 only */
3036 xer_ca
3037 = binop(
3038 Iop_And64,
3039 binop(Iop_Sar64, argL, mkU8(31)),
3040 binop( Iop_And64,
3041 argL,
3042 binop( Iop_Sub64,
3043 binop(Iop_Shl64, mkU64(1),
3044 unop(Iop_64to8,argR)),
3045 mkU64(1) )
3048 xer_ca
3049 = IRExpr_ITE(
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)))
3057 break;
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 */
3067 xer_ca
3068 = binop(
3069 Iop_And64,
3070 binop(Iop_Sar64, argL, mkU8(31)),
3071 binop( Iop_And64,
3072 argL,
3073 binop( Iop_Sub64,
3074 binop(Iop_Shl64, mkU64(1),
3075 unop(Iop_64to8,argR)),
3076 mkU64(1) )
3079 xer_ca
3080 = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
3081 break;
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
3087 bit of argL. */
3088 /* This term valid for shift amount < 63 only */
3090 xer_ca
3091 = binop(
3092 Iop_And64,
3093 binop(Iop_Sar64, argL, mkU8(63)),
3094 binop( Iop_And64,
3095 argL,
3096 binop( Iop_Sub64,
3097 binop(Iop_Shl64, mkU64(1),
3098 unop(Iop_64to8,argR)),
3099 mkU64(1) )
3102 xer_ca
3103 = IRExpr_ITE(
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)))
3111 break;
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 */
3122 xer_ca
3123 = binop(
3124 Iop_And64,
3125 binop(Iop_Sar64, argL, mkU8(63)),
3126 binop( Iop_And64,
3127 argL,
3128 binop( Iop_Sub64,
3129 binop(Iop_Shl64, mkU64(1),
3130 unop(Iop_64to8,argR)),
3131 mkU64(1) )
3134 xer_ca
3135 = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
3136 break;
3138 default:
3139 vex_printf("set_XER_CA: op = %u\n", op);
3140 vpanic("set_XER_CA(ppc64)");
3143 return xer_ca;
3146 static void set_XER_CA_64 ( UInt op, IRExpr* res,
3147 IRExpr* argL, IRExpr* argR, IRExpr* oldca )
3149 IRExpr* xer_ca;
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 );
3173 } else {
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,
3181 IRExpr* old_ov )
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) );
3190 } else {
3191 IRExpr *xer_ov;
3192 IRExpr* xer_ov_32;
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 )
3207 IRTemp sign_mask;
3208 IRTemp twos_comp;
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 )
3224 #define MAX_ELE 16
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). */
3230 UInt i, num_bytes;
3231 UInt max = 0; /* number of vector elements */
3232 UInt mask = 0;
3233 IRTemp cnt[MAX_ELE+1];
3234 IRTemp flag[MAX_ELE+1];
3235 IRTemp cmp_result[MAX_ELE];
3236 UInt byte_index;
3238 vassert(size == Ity_I8 || size == Ity_I16);
3240 if (size == Ity_I8) {
3241 mask = 0xFF;
3242 max = 128/8;
3243 num_bytes = 1;
3244 } else {
3245 mask = 0xFFFF;
3246 max = 128/16;
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++) {
3256 if (dir == 0) {
3257 byte_index = (max - 1 - i)*num_bytes;
3258 } else {
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],
3267 unop( Iop_1Uto8,
3268 binop( Iop_CmpEQ64,
3269 binop( Iop_And64,
3270 mkU64( mask ),
3271 value ),
3272 extract_field_from_vector( src,
3273 mkU64( byte_index ),
3274 mask ) ) ) );
3276 assign( flag[i+1], binop( Iop_And8,
3277 mkexpr( flag[i] ),
3278 unop( Iop_Not8,
3279 mkexpr( cmp_result[i] ) ) ) );
3281 // Once flag[i] becomes zero, it forces the increment to zero
3282 assign( cnt[i+1],
3283 binop( Iop_Add8,
3284 binop( Iop_And8, mkexpr( flag[i+1] ), mkU8( 1 ) ),
3285 mkexpr( cnt[i] ) ) );
3287 return mkexpr( cnt[max] );
3288 #undef MAX_ELE
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 ) ); }
3307 #else
3308 #define PREFIX_CHECK { }
3309 #endif
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 )
3367 vassert(rA < 32);
3368 vassert(mode64);
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 )
3375 vassert(rA < 32);
3376 vassert(mode64);
3377 if (rA == 0) {
3378 return mkSzExtendS34(simm34);
3379 } else {
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;
3392 return False;
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,
3400 UInt *R )
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);
3409 if ( !is_prefix ) {
3410 *immediate_val = extend_s_16to32( d1 );
3411 assign( tmp, ea_rAor0_simm( rA_addr, d1 ) );
3412 *R = 0;
3414 } else {
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 ) );
3422 /* Get the EA */
3423 if ( *R == 0 )
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,
3430 mkexpr ( tmp ),
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;
3462 switch (reg) {
3463 case PPC_GST_SPRG3_RO:
3464 return IRExpr_Get( OFFB_SPRG3_RO, ty );
3466 case PPC_GST_CIA:
3467 return IRExpr_Get( OFFB_CIA, ty );
3469 case PPC_GST_LR:
3470 return IRExpr_Get( OFFB_LR, ty );
3472 case PPC_GST_CTR:
3473 return IRExpr_Get( OFFB_CTR, ty );
3475 case PPC_GST_VRSAVE:
3476 return IRExpr_Get( OFFB_VRSAVE, Ity_I32 );
3478 case PPC_GST_VSCR:
3479 return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ),
3480 mkU32(MASK_VSCR_VALID));
3482 case PPC_GST_CR: {
3483 /* Synthesise the entire CR into a single word. Expensive. */
3484 # define FIELD(_n) \
3485 binop(Iop_Shl32, \
3486 unop(Iop_8Uto32, \
3487 binop(Iop_Or8, \
3488 binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \
3489 binop(Iop_And8, getCR0(_n), mkU8(1)) \
3491 ), \
3492 mkU8(4 * (7-(_n))) \
3494 return binop(Iop_Or32,
3495 binop(Iop_Or32,
3496 binop(Iop_Or32, FIELD(0), FIELD(1)),
3497 binop(Iop_Or32, FIELD(2), FIELD(3))
3499 binop(Iop_Or32,
3500 binop(Iop_Or32, FIELD(4), FIELD(5)),
3501 binop(Iop_Or32, FIELD(6), FIELD(7))
3504 # undef FIELD
3507 case PPC_GST_XER:
3508 return binop(Iop_Or32,
3509 binop(Iop_Or32,
3510 binop(Iop_Or32,
3511 binop( Iop_Shl32, getXER_SO_32(), mkU8(31)),
3512 binop( Iop_Shl32, getXER_OV_32(), mkU8(30))),
3513 binop(Iop_Or32,
3514 binop( Iop_Shl32, getXER_CA_32(), mkU8(29)),
3515 getXER_BC_32())),
3516 binop(Iop_Or32,
3517 binop( Iop_Shl32, getXER_OV32_32(), mkU8(19)),
3518 binop( Iop_Shl32, getXER_CA32_32(), mkU8(18))));
3520 case PPC_GST_TFHAR:
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 );
3529 case PPC_GST_TFIAR:
3530 return IRExpr_Get( OFFB_TFIAR, ty );
3532 case PPC_GST_PPR:
3533 return IRExpr_Get( OFFB_PPR, ty );
3535 case PPC_GST_PPR32:
3536 return unop( Iop_64HIto32, IRExpr_Get( OFFB_PPR, ty ) );
3538 case PPC_GST_PSPB:
3539 return IRExpr_Get( OFFB_PSPB, ty );
3541 case PPC_GST_DSCR:
3542 return IRExpr_Get( OFFB_DSCR, ty );
3544 default:
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 );
3556 switch (reg) {
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 ) ),
3570 binop( Iop_Shl32,
3571 unop( Iop_8Uto32,
3572 IRExpr_Get( OFFB_C_FPCC, Ity_I8 ) ),
3573 mkU8( 12 ) ) ) );
3574 } else {
3575 assign( val, mkU32(0x0) );
3578 break;
3581 default:
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));
3588 } else {
3589 return mkexpr(val);
3593 /* Get a masked word from the given reg */
3594 static IRExpr* /* ::Ity_I32 */getGST_masked_upper(PPC_GST reg, ULong mask) {
3595 IRExpr * val;
3596 vassert( reg < PPC_GST_MAX );
3598 switch (reg) {
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 ) ) );
3609 } else {
3610 val = mkU32( 0x0ULL );
3612 break;
3615 default:
3616 vex_printf( "getGST_masked_upper(ppc): reg = %u", reg );
3617 vpanic( "getGST_masked_upper(ppc)" );
3619 return val;
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 )
3628 UInt shft, mask;
3630 vassert( fld < 8 );
3631 vassert( reg < PPC_GST_MAX );
3633 shft = 4*(7-fld);
3634 mask = 0xF<<shft;
3636 switch (reg) {
3637 case PPC_GST_XER:
3638 vassert(fld ==7);
3639 return binop(Iop_Or32,
3640 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)));
3644 break;
3646 default:
3647 if (shft == 0)
3648 return getGST_masked( reg, mask );
3649 else
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 );
3661 switch (reg) {
3662 case PPC_GST_IP_AT_SYSCALL:
3663 vassert( ty_src == ty );
3664 stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) );
3665 break;
3666 case PPC_GST_CIA:
3667 vassert( ty_src == ty );
3668 stmt( IRStmt_Put( OFFB_CIA, src ) );
3669 break;
3670 case PPC_GST_LR:
3671 vassert( ty_src == ty );
3672 stmt( IRStmt_Put( OFFB_LR, src ) );
3673 break;
3674 case PPC_GST_CTR:
3675 vassert( ty_src == ty );
3676 stmt( IRStmt_Put( OFFB_CTR, src ) );
3677 break;
3678 case PPC_GST_VRSAVE:
3679 vassert( ty_src == Ity_I32 );
3680 stmt( IRStmt_Put( OFFB_VRSAVE,src));
3681 break;
3682 case PPC_GST_VSCR:
3683 vassert( ty_src == Ity_I32 );
3684 stmt( IRStmt_Put( OFFB_VSCR,
3685 binop(Iop_And32, src,
3686 mkU32(MASK_VSCR_VALID)) ) );
3687 break;
3688 case PPC_GST_XER:
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) );
3696 break;
3698 case PPC_GST_EMWARN:
3699 vassert( ty_src == Ity_I32 );
3700 stmt( IRStmt_Put( OFFB_EMNOTE,src) );
3701 break;
3703 case PPC_GST_CMSTART:
3704 vassert( ty_src == ty );
3705 stmt( IRStmt_Put( OFFB_CMSTART, src) );
3706 break;
3708 case PPC_GST_CMLEN:
3709 vassert( ty_src == ty );
3710 stmt( IRStmt_Put( OFFB_CMLEN, src) );
3711 break;
3713 case PPC_GST_TEXASR:
3714 vassert( ty_src == Ity_I64 );
3715 stmt( IRStmt_Put( OFFB_TEXASR, src ) );
3716 break;
3718 case PPC_GST_TEXASRU:
3719 vassert( ty_src == Ity_I32 );
3720 stmt( IRStmt_Put( OFFB_TEXASRU, src ) );
3721 break;
3723 case PPC_GST_TFIAR:
3724 vassert( ty_src == Ity_I64 );
3725 stmt( IRStmt_Put( OFFB_TFIAR, src ) );
3726 break;
3727 case PPC_GST_TFHAR:
3728 vassert( ty_src == Ity_I64 );
3729 stmt( IRStmt_Put( OFFB_TFHAR, src ) );
3730 break;
3732 case PPC_GST_PPR32:
3733 case PPC_GST_PPR:
3735 /* The Program Priority Register (PPR) stores the priority in
3736 * bits [52:50]. The user setable priorities are:
3738 * 001 very low
3739 * 010 low
3740 * 011 medium low
3741 * 100 medium
3742 * 101 medium high
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,
3758 mkU32( 0 ),
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,
3763 mkU32(0),
3764 binop( Iop_And32,
3765 binop( Iop_Shr32, src, mkU8( 18 ) ),
3766 mkU32( 0x7 ) ) ) );
3767 } else {
3768 vassert( ty_src == Ity_I64 );
3769 assign( value, binop( Iop_And64,
3770 binop( Iop_Shr64, src, mkU8( 50 ) ),
3771 mkU64( 0x7 ) ) );
3773 assign( has_perm,
3774 binop( Iop_And64,
3775 unop( Iop_1Sto64,
3776 binop( Iop_CmpEQ64,
3777 mkexpr( PSPB_val ),
3778 mkU64( 0 ) ) ),
3779 unop( Iop_1Sto64,
3780 binop( Iop_CmpEQ64,
3781 mkU64( 0x5 ),
3782 mkexpr( value ) ) ) ) );
3783 assign( not_valid,
3784 binop( Iop_Or64,
3785 unop( Iop_1Sto64,
3786 binop( Iop_CmpEQ64,
3787 mkexpr( value ),
3788 mkU64( 0 ) ) ),
3789 unop( Iop_1Sto64,
3790 binop( Iop_CmpLT64U,
3791 mkU64( 0x5 ),
3792 mkexpr( value ) ) ) ) );
3793 assign( new_src,
3794 binop( Iop_Or64,
3795 binop( Iop_And64,
3796 unop( Iop_Not64,
3797 mkexpr( not_valid ) ),
3798 src ),
3799 binop( Iop_And64,
3800 mkexpr( not_valid ),
3801 binop( Iop_Or64,
3802 binop( Iop_And64,
3803 mkexpr( has_perm),
3804 binop( Iop_Shl64,
3805 mkexpr( value ),
3806 mkU8( 50 ) ) ),
3807 binop( Iop_And64,
3808 IRExpr_Get( OFFB_PPR, ty ),
3809 unop( Iop_Not64,
3810 mkexpr( has_perm )
3811 ) ) ) ) ) );
3813 /* make sure we only set the valid bit field [52:50] */
3814 stmt( IRStmt_Put( OFFB_PPR,
3815 binop( Iop_And64,
3816 mkexpr( new_src ),
3817 mkU64( 0x1C000000000000) ) ) );
3818 break;
3820 case PPC_GST_DSCR:
3821 vassert( ty_src == Ity_I64 );
3822 stmt( IRStmt_Put( OFFB_DSCR, src ) );
3823 break;
3825 default:
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 );
3838 switch (reg) {
3839 case PPC_GST_FPSCR: {
3840 /* Allow writes to either binary or decimal floating point
3841 Rounding Mode.
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) {
3848 stmt(
3849 IRStmt_Put(
3850 OFFB_FPROUND,
3851 unop(
3852 Iop_32to8,
3853 binop(
3854 Iop_Or32,
3855 binop(
3856 Iop_And32,
3857 unop(Iop_64to32, src),
3858 mkU32(MASK_FPSCR_RN & mask)
3860 binop(
3861 Iop_And32,
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] */
3873 stmt(
3874 IRStmt_Put(
3875 OFFB_C_FPCC,
3876 unop(
3877 Iop_32to8,
3878 binop(Iop_Shr32,
3879 binop(
3880 Iop_Or32,
3881 binop(
3882 Iop_And32,
3883 unop(Iop_64to32, src),
3884 mkU32(MASK_FPSCR_C_FPCC & mask) ),
3885 binop(
3886 Iop_And32,
3887 unop(Iop_8Uto32,
3888 IRExpr_Get(OFFB_C_FPCC,Ity_I8)),
3889 mkU32(MASK_FPSCR_C_FPCC & ~mask)
3890 ) ),
3891 mkU8( 12 ) )
3892 ) ) );
3895 /* Similarly, update FPSCR.DRN if any bits of |mask|
3896 corresponding to FPSCR.DRN are set. */
3897 if (mask & MASK_FPSCR_DRN) {
3898 stmt(
3899 IRStmt_Put(
3900 OFFB_DFPROUND,
3901 unop(
3902 Iop_32to8,
3903 binop(
3904 Iop_Or32,
3905 binop(
3906 Iop_And32,
3907 unop(Iop_64HIto32, src),
3908 mkU32((MASK_FPSCR_DRN & mask) >> 32)
3910 binop(
3911 Iop_And32,
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
3923 - Non-IEEE Mode
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) );
3932 stmt(
3933 IRStmt_Exit(
3934 binop(Iop_CmpNE32, mkU32(ew), mkU32(EmNote_NONE)),
3935 Ijk_EmWarn,
3936 mkSzConst( ty, nextInsnAddr()), OFFB_CIA ));
3939 /* Ignore all other writes */
3940 break;
3943 default:
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 )
3953 UInt shft;
3954 ULong mask;
3956 vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 );
3957 vassert( fld < 16 );
3958 vassert( reg < PPC_GST_MAX );
3960 if (fld < 8)
3961 shft = 4*(7-fld);
3962 else
3963 shft = 4*(15-fld);
3964 mask = 0xF;
3965 mask = mask << shft;
3967 switch (reg) {
3968 case PPC_GST_CR:
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)));
3971 break;
3973 default:
3975 IRExpr * src64 = unop( Iop_32Uto64, src );
3977 if (shft == 0) {
3978 putGST_masked( reg, src64, mask );
3979 } else {
3980 putGST_masked( reg,
3981 binop( Iop_Shl64, src64, mkU8( toUChar( shft ) ) ),
3982 mask );
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.
4000 IRExpr* tmp;
4002 vassert( typeOfIRExpr( irsb->tyenv, e ) == Ity_I32 );
4003 /* Get the C bit field */
4004 tmp = binop( Iop_And32,
4005 mkU32( 0x10 ),
4006 unop( Iop_8Uto32, IRExpr_Get( OFFB_C_FPCC, Ity_I8 ) ) );
4008 stmt( IRStmt_Put( OFFB_C_FPCC,
4009 unop( Iop_32to8,
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 ) ),
4025 mkU8( 4 ) ) );
4026 return mkexpr(val);
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 ) ),
4039 mkU32( 0xF ) ));
4040 return mkexpr(val);
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
4072 register file. */
4073 if ( ACC_mapped_on_VSR ) /* ISA 3.1 implementation */
4074 return offsetofPPCGuestState( guest_VSR0 );
4075 else
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
4100 * special FP value.
4102 *------------------------------------------------------------*/
4104 #define NONZERO_FRAC_MASK 0x000fffffffffffffULL
4105 #define FP_FRAC_PART(x) binop( Iop_And64, \
4106 mkexpr( x ), \
4107 mkU64( NONZERO_FRAC_MASK ) )
4109 #define NONZERO_FRAC_MASK32 0x007fffffULL
4110 #define FP_FRAC_PART32(x) binop( Iop_And32, \
4111 mkexpr( x ), \
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 );
4140 } else {
4141 /*NOTREACHED*/
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 ) );
4207 } else {
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 */
4233 opAND = Iop_And32;
4234 opCmpEQ = Iop_CmpEQ32;
4236 } else {
4237 opAND = Iop_And64;
4238 opCmpEQ = Iop_CmpEQ64;
4241 if( size == Ity_V128 ) {
4242 return binop( opCmpEQ,
4243 binop ( opAND,
4244 unop( Iop_V128HIto64, mkexpr( src ) ),
4245 mkexpr( exp_mask ) ),
4246 exp_val );
4248 } else if( ( size == Ity_I16 ) || ( size == Ity_I32 ) ) {
4249 return binop( opCmpEQ,
4250 binop ( opAND, mkexpr( src ), mkexpr( exp_mask ) ),
4251 exp_val );
4252 } else {
4253 /* 64-bit operands */
4255 if (mode64) {
4256 return binop( opCmpEQ,
4257 binop ( opAND, mkexpr( src ), mkexpr( exp_mask ) ),
4258 exp_val );
4259 } else {
4260 /* No support for 64-bit compares in 32-bit mode, need to do upper
4261 * and lower parts using 32-bit compare operators.
4263 return
4264 mkAND1( binop( Iop_CmpEQ32,
4265 binop ( Iop_And32,
4266 unop(Iop_64HIto32, mkexpr( src ) ),
4267 unop(Iop_64HIto32, mkexpr( exp_mask ) ) ),
4268 unop(Iop_64HIto32, exp_val ) ),
4269 binop( Iop_CmpEQ32,
4270 binop ( Iop_And32,
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 */
4286 opAND = Iop_And32;
4287 opCmpEQ = Iop_CmpEQ32;
4289 } else {
4290 opAND = Iop_And64;
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,
4300 binop( Iop_Or64,
4301 binop( opAND,
4302 unop( Iop_V128HIto64, mkexpr( src ) ),
4303 mkexpr( frac_mask ) ),
4304 unop( Iop_V128to64, mkexpr( src ) ) ),
4305 zero );
4307 } else if( ( size == Ity_I16 ) || ( size == Ity_I32 ) ) {
4308 return binop( opCmpEQ,
4309 binop( opAND, mkexpr( src ), mkexpr( frac_mask ) ),
4310 zero );
4311 } else {
4312 if (mode64) {
4313 return binop( opCmpEQ,
4314 binop( opAND, mkexpr( src ), mkexpr( frac_mask ) ),
4315 zero );
4316 } else {
4317 /* No support for 64-bit compares in 32-bit mode, need to do upper
4318 * and lower parts using 32-bit compare operators.
4320 return
4321 mkAND1( binop( Iop_CmpEQ32,
4322 binop ( Iop_And32,
4323 unop(Iop_64HIto32, mkexpr( src ) ),
4324 unop(Iop_64HIto32, mkexpr( frac_mask ) ) ),
4325 mkU32 ( 0 ) ),
4326 binop( Iop_CmpEQ32,
4327 binop ( Iop_And32,
4328 unop(Iop_64to32, mkexpr( src ) ),
4329 unop(Iop_64to32, mkexpr( frac_mask ) ) ),
4330 mkU32 ( 0 ) ) );
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,
4342 &zero );
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,
4360 &zero );
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,
4380 &zero );
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,
4388 mkexpr( zero ) ) );
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,
4399 &zero );
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,
4406 mkexpr( zero ) );
4408 /* check fractional part is not zero */
4409 not_zero_frac = unop( Iop_Not1,
4410 fractional_part_compare( size, src, frac_mask,
4411 mkexpr( zero ) ) );
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,
4423 &zero );
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,
4431 mkexpr( zero ) ) );
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 ) ) );
4452 } else
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,
4458 binop( Iop_AndV128,
4459 mkexpr( exp_maskV128 ), src ),
4460 mkexpr( zeroV128 ) ) );
4462 assign( frac_zeroV128,
4463 binop( Iop_CmpEQ32x4,
4464 binop( Iop_AndV128,
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
4474 positive zeros. */
4476 IRTemp result = newTemp( Ity_V128 );
4478 if ( element_size == Ity_I32 ) {
4479 assign( result, binop( Iop_AndV128,
4480 src,
4481 unop( Iop_NotV128,
4482 is_Zero_Vector( element_size, src) ) ) );
4483 } else
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 ) ) );
4506 } else
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,
4512 binop( Iop_AndV128,
4513 mkexpr( exp_maskV128 ), src ),
4514 mkexpr( zeroV128 ) ) );
4516 assign( frac_nonzeroV128,
4517 unop( Iop_NotV128,
4518 binop( Iop_CmpEQ32x4,
4519 binop( Iop_AndV128,
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;
4543 } else
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,
4548 binop( opCmpEQ,
4549 binop( Iop_AndV128, src, mkexpr( exp_maskV128 ) ),
4550 mkexpr( exp_maskV128 ) ) );
4552 /* check fractional part is not zero */
4553 assign( not_zero_fracV128,
4554 unop( Iop_NotV128,
4555 binop( opCmpEQ,
4556 binop( Iop_AndV128, src, mkexpr( frac_maskV128 ) ),
4557 mkexpr( zeroV128 ) ) ) );
4559 return binop( Iop_AndV128, mkexpr( max_expV128 ),
4560 mkexpr( not_zero_fracV128 ) );
4563 #if 0
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 ) );
4596 } else {
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 );
4614 #endif
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 ) {
4634 assign( tmp,
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 ) {
4641 assign( tmp,
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 ) {
4648 assign( tmp,
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 ) {
4655 assign( tmp,
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,
4662 mkexpr( src ) ) ),
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 );
4687 assign(tmp, src);
4689 /* check if input is SNaN, if it is convert to QNaN */
4690 assign( is_SNAN,
4691 mkAND1( is_NaN( Ity_I32, tmp ),
4692 binop( Iop_CmpEQ32,
4693 binop( Iop_And32, mkexpr( tmp ),
4694 mkU32( SNAN_MASK32 ) ),
4695 mkU32( 0 ) ) ) );
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,
4719 unop( Iop_64HIto32,
4720 binop( Iop_And64, mkexpr( intermediateResult ),
4721 mkU64( signbit_mask ) ) ),
4722 mkU8( 31 ) ) );
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,
4727 unop( Iop_Not1,
4728 binop( Iop_CmpEQ32,
4729 binop( Iop_Xor32,
4730 mkexpr( signbit_32 ),
4731 unop( Iop_1Uto32, is_NaN( Ity_I64,
4732 intermediateResult ) ) ),
4733 mkU32( 1 ) ) ) );
4735 assign( negatedResult,
4736 binop( Iop_Or64,
4737 binop( Iop_And64,
4738 mkexpr( intermediateResult ),
4739 mkU64( ~signbit_mask ) ),
4740 binop( Iop_32HLto64,
4741 binop( Iop_Shl32,
4742 unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
4743 mkU8( 31 ) ),
4744 mkU32( 0 ) ) ) );
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 ) ),
4766 mkU8( 31 ) ) );
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,
4771 unop( Iop_Not1,
4772 binop( Iop_CmpEQ32,
4773 binop( Iop_Xor32,
4774 mkexpr( signbit_32 ),
4775 unop( Iop_1Uto32, is_NaN( Ity_I32,
4776 intermediateResult ) ) ),
4777 mkU32( 1 ) ) ) );
4779 assign( negatedResult,
4780 binop( Iop_Or32,
4781 binop( Iop_And32,
4782 mkexpr( intermediateResult ),
4783 mkU32( ~signbit_mask ) ),
4784 binop( Iop_Shl32,
4785 unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
4786 mkU8( 31 ) ) ) );
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 ) ) );
4802 } else
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,
4811 binop( Iop_AndV128,
4812 mkexpr( sign_maskV128 ), mkexpr( not_nan_mask ) ),
4813 value );
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 ) ) ),
4823 binop( Iop_CmpEQ64,
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 ) ),
4904 mkU8( 63 ) ) );
4905 assign( sign_B, binop( Iop_Shr64,
4906 unop( Iop_V128HIto64, mkexpr( src_B ) ),
4907 mkU8( 63 ) ) );
4908 assign( exp_A, binop( Iop_And64,
4909 binop( Iop_Shr64,
4910 unop( Iop_V128HIto64, mkexpr( src_A ) ),
4911 mkU8( 48 ) ),
4912 mkU64( EXP_MASK ) ) );
4913 assign( exp_B, binop( Iop_And64,
4914 binop( Iop_Shr64,
4915 unop( Iop_V128HIto64, mkexpr( src_B ) ),
4916 mkU8( 48 ) ),
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,
4928 binop( Iop_And64,
4929 unop( Iop_V128HIto64,
4930 mkexpr( src_A ) ),
4931 mkU64( MASK ) ),
4932 mkU64( 0 ) ),
4933 binop( Iop_CmpEQ64,
4934 unop( Iop_V128to64, mkexpr( src_A ) ),
4935 mkU64( 0 ) ) );
4936 IRExpr * B_zero = mkAND1( binop( Iop_CmpEQ64,
4937 binop( Iop_And64,
4938 unop( Iop_V128HIto64,
4939 mkexpr( src_B ) ),
4940 mkU64( MASK ) ),
4941 mkU64( 0 ) ),
4942 binop( Iop_CmpEQ64,
4943 unop( Iop_V128to64, mkexpr( src_B ) ),
4944 mkU64( 0 ) ) );
4945 IRExpr * A_B_zero = mkAND1( A_zero, B_zero );
4947 /* Compare numbers */
4948 IRExpr * both_pos = mkAND1( binop( Iop_CmpEQ64, mkexpr( sign_A ),
4949 mkU64( 0 ) ),
4950 binop( Iop_CmpEQ64, mkexpr( sign_B ),
4951 mkU64( 0 ) ) );
4952 IRExpr * both_neg = mkAND1( binop( Iop_CmpEQ64, mkexpr( sign_A ),
4953 mkU64( 1 ) ),
4954 binop( Iop_CmpEQ64, mkexpr( sign_B ),
4955 mkU64( 1 ) ) );
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,
4978 mkAND1( exp_eq,
4979 mkOR1( frac_hi_gt,
4980 mkAND1( frac_hi_eq, frac_lo_gt ) )
4981 ) );
4983 /* src_A and src_B both negative */
4984 IRExpr *neg_cmp = mkOR1( exp_lt,
4985 mkAND1( exp_eq,
4986 mkOR1( frac_hi_lt,
4987 mkAND1( frac_hi_eq, frac_lo_lt ) )
4988 ) );
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 ),
4994 mkOR1( sign_gt,
4995 mkAND1( sign_eq,
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
5013 Int i;
5014 IRExpr * valid_pos_sign;
5015 IRExpr * valid_neg_sign;
5016 IRTemp valid_num[8];
5017 IRTemp digit[7];
5019 valid_pos_sign = binop( Iop_CmpEQ64,
5020 binop( Iop_And64,
5021 mkU64( 0xFFFF ),
5022 unop( Iop_V128to64, mkexpr( src ) ) ),
5023 mkU64( 0x002B ) );
5025 valid_neg_sign = binop( Iop_CmpEQ64,
5026 binop( Iop_And64,
5027 mkU64( 0xFFFF ),
5028 unop( Iop_V128to64, mkexpr( src ) ) ),
5029 mkU64( 0x002D ) );
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,
5039 unop( Iop_V128to64,
5040 binop( Iop_ShrV128,
5041 mkexpr( src ),
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,
5048 mkexpr( digit[i] ),
5049 mkU64( 0x39 ) ),
5050 binop( Iop_CmpLE64U,
5051 mkU64( 0x30 ),
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
5068 * If ps = 0
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];
5083 IRTemp digit[15];
5085 /* check the range of the sign value based on the value of ps */
5086 valid_range = mkOR1(
5087 mkAND1( binop( Iop_CmpEQ64,
5088 mkU64( 1 ),
5089 mkU64( ps ) ),
5090 mkAND1( binop( Iop_CmpLE64U,
5091 binop( Iop_And64,
5092 mkU64( 0xF0 ),
5093 unop( Iop_V128to64,
5094 mkexpr( src ) ) ),
5096 mkU64( 0xF0 ) ),
5097 binop( Iop_CmpLE64U,
5098 mkU64( 0xA0 ),
5099 binop( Iop_And64,
5100 mkU64( 0xF0 ),
5101 unop( Iop_V128to64,
5102 mkexpr( src ) ))))),
5103 binop( Iop_CmpEQ64,
5104 mkU64( 0 ),
5105 mkU64( ps ) ) );
5107 valid_num[0] = newTemp( Ity_I1 );
5108 assign( valid_num[0], mkU1( 1) ); // Assume true to start
5110 if (ps == 0) {
5111 mask_hi = 0x39;
5112 mask_lo = 0x30;
5113 } else {
5114 mask_hi = 0xF9;
5115 mask_lo = 0xF0;
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,
5122 unop( Iop_V128to64,
5123 binop( Iop_ShrV128,
5124 mkexpr( src ),
5125 mkU8( (15-i)*8 ) ) ),
5126 mkU64( 0xFF ) ) );
5128 assign( valid_num[i+1],
5129 mkAND1( mkexpr( valid_num[i] ),
5130 mkAND1( binop( Iop_CmpLE64U,
5131 mkexpr( digit[i] ),
5132 mkU64( mask_hi ) ),
5133 binop( Iop_CmpLE64U,
5134 mkU64( mask_lo ),
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,
5157 pos_lower_gt ) );
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.
5176 assign( valid,
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 );
5192 assign( tsrc, src);
5194 if ( mode64 ) {
5195 return mkAND1( binop( Iop_CmpEQ64,
5196 mkU64( 0 ),
5197 unop( Iop_V128HIto64,
5198 mkexpr( tsrc ) ) ),
5199 binop( Iop_CmpEQ64,
5200 mkU64( 0 ),
5201 unop( Iop_V128to64,
5202 mkexpr( tsrc ) ) ) );
5203 } else {
5204 /* make this work in 32-bit mode */
5205 return mkAND1(
5206 mkAND1( binop( Iop_CmpEQ32,
5207 mkU32( 0 ),
5208 unop( Iop_64HIto32,
5209 unop( Iop_V128HIto64,
5210 mkexpr( tsrc ) ) ) ),
5211 binop( Iop_CmpEQ32,
5212 mkU32( 0 ),
5213 unop( Iop_64to32,
5214 unop( Iop_V128HIto64,
5215 mkexpr( tsrc ) ) ) ) ),
5216 mkAND1( binop( Iop_CmpEQ32,
5217 mkU32( 0 ),
5218 unop( Iop_64HIto32,
5219 unop( Iop_V128to64,
5220 mkexpr( tsrc ) ) ) ),
5221 binop( Iop_CmpEQ32,
5222 mkU32( 0 ),
5223 unop( Iop_64to32,
5224 unop( Iop_V128to64,
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,
5240 mkU64( 6 ),
5241 binop( Iop_And64,
5242 unop( Iop_V128to64,
5243 binop( Iop_ShrV128,
5244 src,
5245 unop( Iop_64to8, mkexpr( shift ) ) ) ),
5246 mkU64( 0xF ) ) );
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
5266 * next call.
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*/ ),
5288 bcd_string0,
5289 binop( Iop_32HLto64, mkU32( 0 ),
5290 carry_in ) ) ) );
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*/ ),
5298 bcd_string1,
5299 binop( Iop_Shr64,
5300 mkexpr( bcd_result0 ),
5301 mkU8( 32 ) ) ) ) );
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*/ ),
5308 bcd_string2,
5309 binop( Iop_Shr64,
5310 mkexpr( bcd_result1 ),
5311 mkU8( 32 ) ) ) ) );
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*/ ),
5318 bcd_string3,
5319 binop( Iop_Shr64,
5320 mkexpr( bcd_result2 ),
5321 mkU8( 32 ) ) ) ) );
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.
5326 assign( bcd_result,
5327 binop( Iop_64HLtoV128,
5328 binop( Iop_Or64,
5329 binop( Iop_And64,
5330 mkU64( 0xFFFFFFFF ), mkexpr (bcd_result2 ) ),
5331 binop( Iop_Shl64,
5332 mkexpr (bcd_result3 ), mkU8( 32 ) ) ),
5333 binop( Iop_Or64,
5334 binop( Iop_And64,
5335 mkU64( 0xFFFFFFFF ), mkexpr (bcd_result0 ) ),
5336 binop( Iop_Shl64,
5337 mkexpr (bcd_result1 ), mkU8( 32 ) ) ) ) );
5338 return bcd_result;
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.
5355 assign( result_low,
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 ),
5361 upper_byte,
5362 mkU64( 0 ) ) ) );
5364 assign( result_hi,
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 ),
5370 upper_byte,
5371 mkU64( 1 ) ) ) );
5374 assign( result,
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.
5397 assign( result_low,
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 ),
5402 mkU64( 0 ) ) ) );
5404 assign( result_hi,
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 ),
5409 mkU64( 1 ) ) ) );
5411 assign( result,
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 );
5423 assign( result,
5424 binop( Iop_ShlV128,
5425 binop( Iop_64HLtoV128,
5426 mkU64( 0 ),
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,
5432 src ),
5433 unop( Iop_V128to64,
5434 src ) ) ) ),
5435 mkU8( 4 ) ) );
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);
5446 assign( result,
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,
5452 src ),
5453 unop( Iop_V128to64,
5454 src ) ) ) );
5456 return mkexpr( result );
5459 static IRExpr * vector_convert_floattobf16 ( const VexAbiInfo* vbi,
5460 IRExpr *src ) {
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
5463 halfwords. */
5465 IRTemp resultHi = newTemp( Ity_I64);
5466 IRTemp resultLo = newTemp( Ity_I64);
5468 assign( resultHi,
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 ) ) ) );
5475 assign( resultLo,
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,
5486 IRExpr *src ) {
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
5489 32-bit floats. */
5490 IRTemp resultHi = newTemp( Ity_I64);
5491 IRTemp resultLo = newTemp( Ity_I64);
5493 assign( resultHi,
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 ) ) ) );
5500 assign( resultLo,
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,
5511 IRExpr *src ){
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);
5516 assign( result,
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,
5528 IRExpr *flag ) {
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);
5536 assign( result,
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,
5548 IRExpr *flag ) {
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);
5556 assign( result,
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);
5578 assign( result,
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 );
5612 IRExpr *srcA_hi;
5613 IRExpr *srcB_hi;
5614 IRExpr *srcC_hi;
5615 IRExpr *srcA_lo;
5616 IRExpr *srcB_lo;
5617 IRExpr *srcC_lo;
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 );
5626 assign( result_hi,
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 ) ) );
5633 assign( result_lo,
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. */
5648 d->nFxState = 4;
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);
5667 return;
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,
5677 UInt inst_class,
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
5687 8-bit masks. */
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);
5693 IRDirty* d;
5694 UInt instruction = mask_inst & 0xFF; /* Instruction is lower 8-bits. */
5695 IREffect AT_fx;
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(
5706 IRExpr_GSPTR(),
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) {
5716 case XVI4GER8:
5717 case XVI8GER4:
5718 case XVI16GER2:
5719 case XVI16GER2S:
5720 case XVF16GER2:
5721 case XVBF16GER2:
5722 case XVF32GER:
5723 AT_fx = Ifx_Write;
5724 break;
5725 case XVI4GER8PP:
5726 case XVI8GER4PP:
5727 case XVI8GER4SPP:
5728 case XVI16GER2PP:
5729 case XVI16GER2SPP:
5730 case XVBF16GER2PP:
5731 case XVBF16GER2PN:
5732 case XVBF16GER2NP:
5733 case XVBF16GER2NN:
5734 case XVF16GER2PP:
5735 case XVF16GER2PN:
5736 case XVF16GER2NP:
5737 case XVF16GER2NN:
5738 case XVF32GERPP:
5739 case XVF32GERPN:
5740 case XVF32GERNP:
5741 case XVF32GERNN:
5742 AT_fx = Ifx_Modify;
5743 break;
5744 default:
5745 vassert(0); /* Unknown instruction */
5748 switch(inst_class) {
5749 case MATRIX_4BIT_INT_GER:
5751 d = unsafeIRDirty_0_N (
5752 0/*regparms*/,
5753 "vsx_matrix_4bit_ger_dirty_helper",
5754 fnptr_to_fnentry( vbi, &vsx_matrix_4bit_ger_dirty_helper ),
5755 args );
5756 break;
5758 case MATRIX_8BIT_INT_GER:
5760 d = unsafeIRDirty_0_N (
5761 0/*regparms*/,
5762 "vsx_matrix_8bit_ger_dirty_helper",
5763 fnptr_to_fnentry( vbi, &vsx_matrix_8bit_ger_dirty_helper ),
5764 args );
5765 break;
5767 case MATRIX_16BIT_INT_GER:
5769 d = unsafeIRDirty_0_N (
5770 0/*regparms*/,
5771 "vsx_matrix_16bit_ger_dirty_helper",
5772 fnptr_to_fnentry( vbi, &vsx_matrix_16bit_ger_dirty_helper ),
5773 args );
5774 break;
5776 case MATRIX_16BIT_FLOAT_GER:
5778 d = unsafeIRDirty_0_N (
5779 0/*regparms*/,
5780 "vsx_matrix_16bit_float_ger_dirty_helper",
5781 fnptr_to_fnentry( vbi, &vsx_matrix_16bit_float_ger_dirty_helper ),
5782 args );
5783 break;
5785 case MATRIX_32BIT_FLOAT_GER:
5787 d = unsafeIRDirty_0_N (
5788 0/*regparms*/,
5789 "vsx_matrix_32bit_float_ger_dirty_helper",
5790 fnptr_to_fnentry( vbi, &vsx_matrix_32bit_float_ger_dirty_helper ),
5791 args );
5792 break;
5794 default:
5795 vex_printf("ERROR: Unkown inst_class = %u in vsx_matrix_ger()\n",
5796 inst_class);
5797 return;
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,
5808 IRExpr *srcB,
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);
5824 UInt start_i;
5825 IRDirty* d;
5826 ULong combined_args;
5827 UInt instruction = mask_inst & 0xFF; /* Instruction is lower 8-bits. */
5828 IREffect AT_fx;
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. */
5845 start_i = 0;
5846 combined_args = (mask_inst << 8) | (start_i << 4) | AT;
5848 IRExpr** args1 = mkIRExprVec_7(
5849 IRExpr_GSPTR(),
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) {
5859 case XVF64GER:
5860 AT_fx = Ifx_Write;
5861 break;
5862 case XVF64GERPP:
5863 case XVF64GERPN:
5864 case XVF64GERNP:
5865 case XVF64GERNN:
5866 AT_fx = Ifx_Modify;
5867 break;
5868 default:
5869 vassert(0); /* Unknown instruction */
5872 d = unsafeIRDirty_0_N (
5873 0/*regparms*/,
5874 "vsx_matrix_64bit_float_ger_dirty_helper",
5875 fnptr_to_fnentry( vbi, &vsx_matrix_64bit_float_ger_dirty_helper ),
5876 args1 );
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) );
5883 start_i = 2;
5884 combined_args = (mask_inst << 8) | (start_i << 4) | AT;
5886 IRExpr** args2 = mkIRExprVec_7(
5887 IRExpr_GSPTR(),
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 (
5894 0/*regparms*/,
5895 "vsx_matrix_64bit_float_ger_dirty_helper",
5896 fnptr_to_fnentry( vbi, &vsx_matrix_64bit_float_ger_dirty_helper ),
5897 args2 );
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
5913 state VSX register.
5915 IRTemp src_hi = newTemp( Ity_I64);
5916 IRTemp src_lo = newTemp( Ity_I64);
5918 IRDirty* d;
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(
5928 IRExpr_GSPTR(),
5929 mkexpr( src_hi ),
5930 mkexpr( src_lo ),
5931 mkU32( reg_offset ),
5932 mkU64( IMM ) );
5934 switch( opc2 ) {
5935 case 0x394: // xxgenpcvbm
5936 d = unsafeIRDirty_0_N (
5937 0 /*regparms*/,
5938 "vector_gen_pvc_byte_mask_dirty_helper",
5939 fnptr_to_fnentry( vbi,
5940 &vector_gen_pvc_byte_mask_dirty_helper ),
5941 args);
5942 break;
5944 case 0x395: // xxgenpcvhm
5945 d = unsafeIRDirty_0_N (
5946 0 /*regparms*/,
5947 "vector_gen_pvc_hword_mask_dirty_helper",
5948 fnptr_to_fnentry( vbi,
5949 &vector_gen_pvc_hword_mask_dirty_helper ),
5950 args);
5951 break;
5953 case 0x3B4: // xxgenpcvwm
5954 d = unsafeIRDirty_0_N (
5955 0 /*regparms*/,
5956 "vector_gen_pvc_word_mask_dirty_helper",
5957 fnptr_to_fnentry( vbi,
5958 &vector_gen_pvc_word_mask_dirty_helper ),
5959 args);
5960 break;
5962 case 0x3B5: // xxgenpcvdm
5963 d = unsafeIRDirty_0_N (
5964 0 /*regparms*/,
5965 "vector_gen_pvc_dword_mask_dirty_helper",
5966 fnptr_to_fnentry( vbi,
5967 &vector_gen_pvc_dword_mask_dirty_helper ),
5968 args);
5969 break;
5970 default:
5971 vex_printf("ERROR: Unkown instruction = %u in vector_gen_pvc_mask()\n",
5972 opc2);
5973 return;
5976 d->nFxState = 1;
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(
6037 mkOR1( gt_word3,
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
6051 float. */
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));
6058 u.f = f;
6059 return u.i;
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
6066 VSCR[NJ] bit.
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 */
6096 assign( VSCR_NJ,
6097 unop( Iop_1Sto64,
6098 unop( Iop_32to1,
6099 binop( Iop_Shr32,
6100 getGST( PPC_GST_VSCR ),
6101 mkU8( 16 ) ) ) ) );
6103 assign ( VSCR_NJ_mask, binop( Iop_64HLtoV128,
6104 mkexpr( VSCR_NJ ) ,
6105 mkexpr( VSCR_NJ ) ) );
6107 /* Create the masks to do the rounding of dnorm values and absolute
6108 value of zero. */
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,
6118 binop( Iop_OrV128,
6119 binop( Iop_AndV128,
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 ),
6128 binop( Iop_AndV128,
6129 src,
6130 mkexpr( ones_maskV128 ) ) ) );
6132 /* If the VSCR[NJ] bit is 1, then clear the denormalized values,
6133 otherwise just return the input unchanged. */
6134 assign( resultV128,
6135 binop( Iop_OrV128,
6136 binop( Iop_AndV128,
6137 mkexpr( VSCR_NJ_mask ),
6138 mkexpr( adj_valueV128 ) ),
6139 binop( Iop_AndV128,
6140 unop( Iop_NotV128, mkexpr( VSCR_NJ_mask ) ),
6141 src ) ) );
6143 return mkexpr(resultV128);
6146 /*------------------------------------------------------------*/
6147 /* Transactional memory helpers
6149 *------------------------------------------------------------*/
6151 static ULong generate_TMreason( UInt failure_code,
6152 UInt persistant,
6153 UInt nest_overflow,
6154 UInt tm_exact )
6156 ULong tm_err_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 */
6179 return tm_err_code;
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. */
6211 switch (opc2) {
6212 case 0xDB: // brh Byte-Reverse half word X-form
6213 DIP("brh r%u,r%u\n", rA_addr, rS_addr);
6214 assign( tmp_0,
6215 binop( Iop_And64, mkexpr( rS ), mkU64( 0xFF00FF00FF00FF00 ) ) );
6216 assign( tmp_1,
6217 binop( Iop_And64, mkexpr( rS ), mkU64( 0x00FF00FF00FF00FF ) ) );
6218 assign( result,
6219 binop( Iop_Or64,
6220 binop( Iop_Shr64, mkexpr( tmp_0 ), mkU8( 8 ) ),
6221 binop( Iop_Shl64, mkexpr( tmp_1 ), mkU8( 8 ) ) ) );
6222 break;
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);
6229 assign( tmp_0,
6230 binop( Iop_And64, mkexpr( rS ), mkU64( 0xFF000000FF000000 ) ) );
6231 assign( tmp_1,
6232 binop( Iop_And64, mkexpr( rS ), mkU64( 0x00FF000000FF0000 ) ) );
6233 assign( tmp_2,
6234 binop( Iop_And64, mkexpr( rS ), mkU64( 0x0000FF000000FF00 ) ) );
6235 assign( tmp_3,
6236 binop( Iop_And64, mkexpr( rS ), mkU64( 0x000000FF000000FF ) ) );
6237 assign( result,
6238 binop( Iop_Or64,
6239 binop( Iop_Or64,
6240 binop( Iop_Shl64, mkexpr( tmp_3 ), mkU8( 24 ) ),
6241 binop( Iop_Shl64, mkexpr( tmp_2 ), mkU8( 8 ) ) ),
6242 binop( Iop_Or64,
6243 binop( Iop_Shr64, mkexpr( tmp_1 ), mkU8( 8 ) ),
6244 binop( Iop_Shr64, mkexpr( tmp_0 ), mkU8( 24 ) ) )
6245 ) );
6246 break;
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);
6258 assign( tmp_0,
6259 binop( Iop_And64, mkexpr( rS ), mkU64( 0xFF00000000000000 ) ) );
6260 assign( tmp_1,
6261 binop( Iop_And64, mkexpr( rS ), mkU64( 0x00FF000000000000 ) ) );
6262 assign( tmp_2,
6263 binop( Iop_And64, mkexpr( rS ), mkU64( 0x0000FF0000000000 ) ) );
6264 assign( tmp_3,
6265 binop( Iop_And64, mkexpr( rS ), mkU64( 0x000000FF00000000 ) ) );
6266 assign( tmp_4,
6267 binop( Iop_And64, mkexpr( rS ), mkU64( 0x00000000FF000000 ) ) );
6268 assign( tmp_5,
6269 binop( Iop_And64, mkexpr( rS ), mkU64( 0x0000000000FF0000 ) ) );
6270 assign( tmp_6,
6271 binop( Iop_And64, mkexpr( rS ), mkU64( 0x000000000000FF00 ) ) );
6272 assign( tmp_7,
6273 binop( Iop_And64, mkexpr( rS ), mkU64( 0x00000000000000FF ) ) );
6274 assign( result,
6275 binop( Iop_Or64,
6276 binop( Iop_Or64,
6277 binop( Iop_Or64,
6278 binop( Iop_Shl64, mkexpr( tmp_7 ), mkU8( 56 ) ),
6279 binop( Iop_Shl64, mkexpr( tmp_6 ), mkU8( 40 ) ) ),
6280 binop( Iop_Or64,
6281 binop( Iop_Shl64, mkexpr( tmp_5 ), mkU8( 24 ) ),
6282 binop( Iop_Shl64, mkexpr( tmp_4 ), mkU8( 8 ) ) ) ),
6283 binop( Iop_Or64,
6284 binop( Iop_Or64,
6285 binop( Iop_Shr64, mkexpr( tmp_3 ), mkU8( 8 ) ),
6286 binop( Iop_Shr64, mkexpr( tmp_2 ), mkU8( 24 ) ) ),
6287 binop( Iop_Or64,
6288 binop( Iop_Shr64, mkexpr( tmp_1 ), mkU8( 40 ) ),
6289 binop( Iop_Shr64, mkexpr( tmp_0 ), mkU8( 56 ) ) ) )
6290 ) );
6291 break;
6294 default:
6295 vex_printf("dis_byte_reverse(ppc): unrecognized instruction\n");
6296 return False;
6299 putIReg( rA_addr, mkexpr( result ) );
6300 return True;
6304 Integer Arithmetic Instructions
6306 static Bool dis_int_mult_add ( UInt prefix, UInt theInstr )
6308 /* VA-Form */
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 );
6324 IRExpr* carryout;
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. */
6331 PREFIX_CHECK
6333 switch (opc2) {
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,
6349 mkexpr( tmpHi ),
6350 unop( Iop_1Sto64,
6351 unop( Iop_64to1,
6352 binop( Iop_Shr64,
6353 mkexpr( rC ),
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,
6362 mkexpr( tmp2Hi ),
6363 unop( Iop_1Uto64, carryout ) ) );
6364 break;
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,
6385 mkexpr( tmpHi ),
6386 unop( Iop_1Uto64, carryout ) ) );
6387 break;
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 ) ) );
6397 break;
6399 default:
6400 vex_printf("dis_int_mult(ppc): unrecognized instruction\n");
6401 return False;
6404 putIReg( rD_addr, mkexpr(rD) );
6406 return True;
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
6427 if ( !is_prefix ) {
6428 assign( value, mkSzExtendS16( ty, si1 ));
6430 } else {
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) );
6440 switch (opc1) {
6441 /* D-Form */
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);
6449 DIPn(is_prefix);
6450 assign( tmp, mkexpr( value ) );
6452 } else {
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 ) ) );
6458 if ( R == 0 )
6459 assign( rT, mkexpr( tmp ) );
6460 else
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 ) ),
6466 mkexpr( tmp ) ) );
6468 break;
6470 default:
6471 vex_printf("dis_int_arith_prefix(ppc)(opc1)\n");
6472 return False;
6475 putIReg( rT_addr, mkexpr(rT) );
6477 return True;
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);
6498 Bool do_rc = False;
6500 /* There is no prefixed version of these instructions. */
6501 PREFIX_CHECK
6503 assign( rA, getIReg(rA_addr) );
6504 assign( rB, getIReg(rB_addr) ); // XO-Form: rD, rA, rB
6506 switch (opc1) {
6507 /* D-Form */
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*/ );
6515 break;
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
6525 flag_rC = 1;
6526 break;
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) );
6534 } else {
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) ) );
6539 break;
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) );
6546 } else {
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) ) );
6551 break;
6553 case 0x07: // mulli (Multiply Low Immediate, PPC32 p490)
6554 DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
6555 if (mode64)
6556 assign( rD, unop(Iop_128to64,
6557 binop(Iop_MullS64, mkexpr(rA),
6558 mkSzExtendS16(ty, uimm16))) );
6559 else
6560 assign( rD, unop(Iop_64to32,
6561 binop(Iop_MullS32, mkexpr(rA),
6562 mkSzExtendS16(ty, uimm16))) );
6563 break;
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);
6567 // rD = simm16 - rA
6568 assign( rD, binop( mkSzOp(ty, Iop_Sub8),
6569 mkSzExtendS16(ty, uimm16),
6570 mkexpr(rA)) );
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*/ );
6574 break;
6576 /* XO-Form */
6577 case 0x1F:
6578 do_rc = True; // All below record to CR
6580 switch (opc2) {
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) ) );
6587 if (flag_OE) {
6588 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_ADD,
6589 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
6591 break;
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*/ );
6602 if (flag_OE) {
6603 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_ADD,
6604 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
6606 break;
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) );
6621 if (flag_OE) {
6622 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_ADDE,
6623 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
6625 break;
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 */
6637 if (flag_OE == 0) {
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) );
6641 } else {
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");
6646 break;
6649 case 0x0EA: { // addme (Add to Minus One Extended, PPC32 p354)
6650 IRTemp old_xer_ca = newTemp(ty);
6651 IRExpr *min_one;
6652 if (rB_addr != 0) {
6653 vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n");
6654 return False;
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) );
6669 if (flag_OE) {
6670 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_ADDE,
6671 mkexpr(rD), mkexpr(rA), min_one );
6673 break;
6676 case 0x0CA: { // addze (Add to Zero Extended, PPC32 p355)
6677 IRTemp old_xer_ca = newTemp(ty);
6678 if (rB_addr != 0) {
6679 vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n");
6680 return False;
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) );
6693 if (flag_OE) {
6694 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_ADDE,
6695 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
6697 break;
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);
6704 if (mode64) {
6705 /* Note:
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,
6715 divisor) ) );
6716 if (flag_OE) {
6717 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVW,
6718 mkexpr(rD), dividend, divisor );
6720 } else {
6721 assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) );
6722 if (flag_OE) {
6723 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVW,
6724 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
6727 /* Note:
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. */
6731 break;
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);
6737 if (mode64) {
6738 /* Note:
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,
6746 divisor) ) );
6747 if (flag_OE) {
6748 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVWU,
6749 mkexpr(rD), dividend, divisor );
6751 } else {
6752 assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) );
6753 if (flag_OE) {
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) */
6759 break;
6761 case 0x04B: // mulhw (Multiply High Word, PPC32 p488)
6762 if (flag_OE != 0) {
6763 vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n");
6764 return False;
6766 DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
6767 rD_addr, rA_addr, rB_addr);
6768 if (mode64) {
6769 /* rD[hi32] are undefined: setting them to sign of lo32
6770 - makes set_CR0 happy */
6771 assign( rD, binop(Iop_Sar64,
6772 binop(Iop_Mul64,
6773 mk64lo32Sto64( mkexpr(rA) ),
6774 mk64lo32Sto64( mkexpr(rB) )),
6775 mkU8(32)) );
6776 } else {
6777 assign( rD, unop(Iop_64HIto32,
6778 binop(Iop_MullS32,
6779 mkexpr(rA), mkexpr(rB))) );
6781 break;
6783 case 0x00B: // mulhwu (Multiply High Word Unsigned, PPC32 p489)
6784 if (flag_OE != 0) {
6785 vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n");
6786 return False;
6788 DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
6789 rD_addr, rA_addr, rB_addr);
6790 if (mode64) {
6791 /* rD[hi32] are undefined: setting them to sign of lo32
6792 - makes set_CR0 happy */
6793 assign( rD, binop(Iop_Sar64,
6794 binop(Iop_Mul64,
6795 mk64lo32Uto64( mkexpr(rA) ),
6796 mk64lo32Uto64( mkexpr(rB) ) ),
6797 mkU8(32)) );
6798 } else {
6799 assign( rD, unop(Iop_64HIto32,
6800 binop(Iop_MullU32,
6801 mkexpr(rA), mkexpr(rB))) );
6803 break;
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);
6809 if (mode64) {
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) );
6815 if (flag_OE) {
6816 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_MULLW,
6817 mkexpr(rD),
6818 unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) );
6820 } else {
6821 assign( rD, unop(Iop_64to32,
6822 binop(Iop_MullU32,
6823 mkexpr(rA), mkexpr(rB))) );
6824 if (flag_OE) {
6825 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_MULLW,
6826 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
6829 break;
6831 case 0x068: // neg (Negate, PPC32 p493)
6832 if (rB_addr != 0) {
6833 vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n");
6834 return False;
6836 DIP("neg%s%s r%u,r%u\n",
6837 flag_OE ? "o" : "", flag_rC ? ".":"",
6838 rD_addr, rA_addr);
6839 // rD = (~rA) + 1
6840 assign( rD, binop( mkSzOp(ty, Iop_Add8),
6841 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ),
6842 mkSzImm(ty, 1)) );
6843 if (flag_OE) {
6844 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_NEG,
6845 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
6847 break;
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);
6853 // rD = rB - rA
6854 assign( rD, binop( mkSzOp(ty, Iop_Sub8),
6855 mkexpr(rB), mkexpr(rA)) );
6856 if (flag_OE) {
6857 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_SUBF,
6858 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
6860 break;
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);
6866 // rD = rB - rA
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*/ );
6872 if (flag_OE) {
6873 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_SUBFC,
6874 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
6876 break;
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]
6884 // ==>
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),
6891 mkexpr(old_xer_ca),
6892 mkSzImm(ty, 1))) );
6893 set_XER_CA_CA32( ty, PPCG_FLAG_OP_SUBFE,
6894 mkexpr(rD), mkexpr(rA), mkexpr(rB),
6895 mkexpr(old_xer_ca) );
6896 if (flag_OE) {
6897 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_SUBFE,
6898 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
6900 break;
6903 case 0x0E8: { // subfme (Subtract from -1 Extended, PPC32 p541)
6904 IRTemp old_xer_ca = newTemp(ty);
6905 IRExpr *min_one;
6906 if (rB_addr != 0) {
6907 vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n");
6908 return False;
6910 DIP("subfme%s%s r%u,r%u\n",
6911 flag_OE ? "o" : "", flag_rC ? ".":"",
6912 rD_addr, rA_addr);
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) );
6924 if (flag_OE) {
6925 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_SUBFE,
6926 mkexpr(rD), mkexpr(rA), min_one );
6928 break;
6931 case 0x0C8: { // subfze (Subtract from Zero Extended, PPC32 p542)
6932 IRTemp old_xer_ca = newTemp(ty);
6933 if (rB_addr != 0) {
6934 vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n");
6935 return False;
6937 DIP("subfze%s%s r%u,r%u\n",
6938 flag_OE ? "o" : "", flag_rC ? ".":"",
6939 rD_addr, rA_addr);
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) );
6949 if (flag_OE) {
6950 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_SUBFE,
6951 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
6953 break;
6957 /* 64bit Arithmetic */
6958 case 0x49: // mulhd (Multiply High DWord, PPC64 p539)
6959 if (flag_OE != 0) {
6960 vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n");
6961 return False;
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,
6966 binop(Iop_MullS64,
6967 mkexpr(rA), mkexpr(rB))) );
6969 break;
6971 case 0x9: // mulhdu (Multiply High DWord Unsigned, PPC64 p540)
6972 if (flag_OE != 0) {
6973 vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n");
6974 return False;
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,
6979 binop(Iop_MullU64,
6980 mkexpr(rA), mkexpr(rB))) );
6981 break;
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)) );
6988 if (flag_OE) {
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.
6995 copy_OV_to_OV32();
6996 update_SO();
6998 break;
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)) );
7005 if (flag_OE) {
7006 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVW,
7007 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
7009 break;
7010 /* Note:
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)) );
7020 if (flag_OE) {
7021 set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVWU,
7022 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
7024 break;
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
7031 * <anything> / 0
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
7034 * to 1.
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);
7041 if (mode64) {
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 ) ) );
7046 } else {
7047 dividend = mkexpr( rA );
7048 divisor = mkexpr( rB );
7049 assign( res, binop( Iop_DivU32E, dividend, divisor ) );
7050 assign( rD, mkexpr( res) );
7053 if (flag_OE) {
7054 set_XER_OV_OV32_32( PPCG_FLAG_OP_DIVWEU,
7055 mkexpr(res), dividend, divisor );
7056 update_SO( );
7058 break;
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
7066 * <anything> / 0
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);
7077 if (mode64) {
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 ) ) );
7082 } else {
7083 dividend = mkexpr( rA );
7084 divisor = mkexpr( rB );
7085 assign( res, binop( Iop_DivS32E, dividend, divisor ) );
7086 assign( rD, mkexpr( res) );
7089 if (flag_OE) {
7090 set_XER_OV_OV32_32( PPCG_FLAG_OP_DIVWE,
7091 mkexpr(res), dividend, divisor );
7092 update_SO( );
7094 break;
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
7102 * <anything> / 0
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)) );
7111 if (flag_OE) {
7112 set_XER_OV_64( PPCG_FLAG_OP_DIVDE, mkexpr( rD ),
7113 mkexpr( rA ), mkexpr( rB ) );
7114 copy_OV_to_OV32();
7115 update_SO();
7117 break;
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)) );
7125 if (flag_OE) {
7126 set_XER_OV_64( PPCG_FLAG_OP_DIVDEU, mkexpr( rD ),
7127 mkexpr( rA ), mkexpr( rB ) );
7128 copy_OV_to_OV32();
7129 update_SO();
7131 break;
7133 default:
7134 vex_printf("dis_int_arith(ppc)(opc2)\n");
7135 return False;
7137 break;
7139 default:
7140 vex_printf("dis_int_arith(ppc)(opc1)\n");
7141 return False;
7144 putIReg( rD_addr, mkexpr(rD) );
7146 if (do_rc && flag_rC) {
7147 set_CR0( mkexpr(rD) );
7149 return True;
7152 static Bool dis_modulo_int ( UInt prefix, UInt theInstr )
7154 /* X-Form */
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. */
7164 PREFIX_CHECK
7166 switch (opc1) {
7167 /* X-Form */
7168 case 0x1F:
7169 switch (opc2) {
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 ) );
7184 assign( quotient,
7185 binop( Iop_DivU64, mkexpr( rA ), mkexpr( rB ) ) );
7187 assign( quotientTimesDivisor,
7188 binop( Iop_Mul64,
7189 mkexpr( quotient ),
7190 mkexpr( rB ) ) );
7192 assign( remainder,
7193 binop( Iop_Sub64,
7194 mkexpr( rA ),
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,
7201 binop( Iop_CmpEQ64,
7202 mkexpr( rB ),
7203 mkU64( 0x0 ) ) ) );
7205 assign (rD, binop( Iop_And64,
7206 unop( Iop_Not64, mkexpr( rB_0 ) ),
7207 mkexpr( remainder ) ) );
7208 break;
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
7225 * 64-bit register.
7227 assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) );
7228 assign( rB, unop( Iop_64to32, getIReg( rB_addr ) ) );
7230 } else {
7231 assign( rA, getIReg( rA_addr ) );
7232 assign( rB, getIReg( rB_addr ) );
7235 assign( quotient,
7236 binop( Iop_DivU32, mkexpr( rA ), mkexpr( rB ) ) );
7238 assign( quotientTimesDivisor,
7239 unop( Iop_64to32,
7240 binop( Iop_MullU32,
7241 mkexpr( quotient ),
7242 mkexpr( rB ) ) ) );
7244 assign( remainder,
7245 binop( Iop_Sub32,
7246 mkexpr( rA ),
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,
7253 binop( Iop_CmpEQ32,
7254 mkexpr( rB ),
7255 mkU32( 0x0 ) ) ) );
7257 assign (rD, binop( Iop_32HLto64,
7258 mkU32( 0 ),
7259 binop( Iop_And32,
7260 unop( Iop_Not32, mkexpr( rB_0 ) ),
7261 mkexpr( remainder ) ) ) );
7262 break;
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 ) ) );
7286 if ( flag_rC )
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
7295 break;
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 ) ) );
7315 if ( flag_rC == 1 )
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
7324 break;
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,
7346 binop( Iop_CmpNE64,
7347 mkexpr( rA ),
7348 mkU64( 0x8000000000000000 ) ) ) );
7349 assign( rB_0, binop( Iop_CmpEQ64,
7350 mkexpr( rB ),
7351 mkU64( 0x0 ) ) );
7353 assign( rB_1, binop( Iop_CmpEQ64,
7354 mkexpr( rB ),
7355 mkU64( 0x1 ) ) );
7357 assign( rB_m1, binop( Iop_CmpEQ64,
7358 mkexpr( rB ),
7359 mkU64( 0xFFFFFFFFFFFFFFFF ) ) );
7361 assign( rA_m1, binop( Iop_CmpEQ64,
7362 mkexpr( rA ),
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:
7370 0x80000000 % -1
7371 <anything> % 0
7372 result is undefined. Force result to zero to match the
7373 HW behaviour. */
7375 assign( resultis0,
7376 binop( Iop_Or64,
7377 binop( Iop_Or64,
7378 /* -1 % 1 */
7379 binop( Iop_And64,
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 ) ) ),
7384 binop( Iop_Or64,
7385 binop( Iop_And64,
7386 unop( Iop_Not64,
7387 mkexpr( rA2_63 ) ),
7388 unop ( Iop_1Sto64,
7389 mkexpr( rB_m1 ) ) ),
7390 /* -1 % -1 */
7391 binop( Iop_And64,
7392 unop( Iop_1Sto64, mkexpr( rA_m1 ) ),
7393 unop( Iop_1Sto64, mkexpr( rB_m1 ) )
7394 ) ) ) );
7396 /* The following remainder computation works as long as
7397 * rA != -2^63 and rB != -1.
7399 assign( quotient,
7400 binop( Iop_DivS64, mkexpr( rA ), mkexpr( rB ) ) );
7402 assign( quotientTimesDivisor,
7403 binop( Iop_Mul64,
7404 mkexpr( quotient ),
7405 mkexpr( rB ) ) );
7407 assign( remainder,
7408 binop( Iop_Sub64,
7409 mkexpr( rA ),
7410 mkexpr( quotientTimesDivisor ) ) );
7412 assign( rD, binop( Iop_And64,
7413 mkexpr( remainder ),
7414 unop( Iop_Not64,
7415 mkexpr( resultis0 ) ) ) );
7416 break;
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
7436 * 64-bit register.
7438 assign( rA, unop(Iop_64to32, getIReg(rA_addr) ) );
7439 assign( rB, unop(Iop_64to32, getIReg(rB_addr) ) );
7441 } else {
7442 assign( rA, getIReg(rA_addr) );
7443 assign( rB, getIReg(rB_addr) );
7446 assign( rA2_32, unop( Iop_1Sto32,
7447 binop( Iop_CmpEQ32,
7448 mkexpr( rA ),
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,
7455 mkexpr( rB ),
7456 mkU32( 0x0 ) ) );
7458 assign( rB_1, binop( Iop_CmpEQ32,
7459 mkexpr( rB ),
7460 mkU32( 0x00000001 ) ) );
7462 assign( rB_m1, binop( Iop_CmpEQ32,
7463 mkexpr( rB ),
7464 mkU32( 0xFFFFFFFF ) ) );
7466 assign( rA_m1, binop( Iop_CmpEQ32,
7467 mkexpr( rA ),
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:
7476 0x80000000 % -1
7477 <anything> % 0
7478 result is undefined. Force result to zero to match the
7479 HW beaviour. */
7481 assign( resultis0,
7482 binop( Iop_Or32,
7483 binop( Iop_Or32,
7484 /* -1 % 1 */
7485 binop( Iop_And32,
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 ) ) ),
7491 binop( Iop_Or32,
7492 /* 0x8000000 % -1 */
7493 binop( Iop_And32,
7494 mkexpr( rA2_32 ),
7495 unop( Iop_1Sto32,
7496 mkexpr( rB_m1 ) ) ),
7497 /* -1 % -1 */
7498 binop( Iop_And32,
7499 unop( Iop_1Sto32, mkexpr( rA_m1 ) ),
7500 unop( Iop_1Sto32, mkexpr( rB_m1 ) )
7501 ) ) ) );
7503 /* The following remainder computation works as long as
7504 * rA != -2^31 and rB != -1.
7506 assign( quotient,
7507 binop( Iop_DivS32, mkexpr( rA ), mkexpr( rB ) ) );
7509 assign( quotientTimesDivisor,
7510 unop( Iop_64to32,
7511 binop( Iop_MullS32,
7512 mkexpr( quotient ),
7513 mkexpr( rB ) ) ) );
7515 assign( remainder,
7516 binop( Iop_Sub32,
7517 mkexpr( rA ),
7518 mkexpr( quotientTimesDivisor ) ) );
7520 assign( rD, binop( Iop_32HLto64,
7521 mkU32( 0 ),
7522 binop( Iop_And32,
7523 mkexpr( remainder ),
7524 unop( Iop_Not32,
7525 mkexpr( resultis0 ) ) ) ) );
7526 break;
7529 default:
7530 vex_printf("dis_modulo_int(ppc)(opc2)\n");
7531 return False;
7533 break;
7535 default:
7536 vex_printf("dis_modulo_int(ppc)(opc1)\n");
7537 return False;
7540 putIReg( rD_addr, mkexpr( rD ) );
7542 return True;
7547 Byte Compare Instructions
7549 static Bool dis_byte_cmp ( UInt prefix, UInt theInstr )
7551 /* X-Form */
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. */
7562 PREFIX_CHECK
7564 assign( rA, getIReg(rA_addr) );
7565 assign( rB, getIReg(rB_addr) );
7567 if (opc1 != 0x1F) {
7568 vex_printf("dis_byte_cmp(ppc)(opc1)\n");
7569 return False;
7572 switch (opc2) {
7573 case 0xc0: // cmprb (Compare Ranged Byte)
7575 IRExpr *value;
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,
7582 binop( Iop_And64,
7583 mkexpr( rB ),
7584 mkU64( 0xFF000000 ) ),
7585 mkU8( 24 ) );
7586 lo_1 = binop( Iop_Shr64,
7587 binop( Iop_And64,
7588 mkexpr( rB ),
7589 mkU64( 0xFF0000 ) ) ,
7590 mkU8( 16 ) );
7591 hi_2 = binop( Iop_Shr64,
7592 binop( Iop_And64,
7593 mkexpr( rB ),
7594 mkU64( 0xFF00 ) ),
7595 mkU8( 8 ) );
7596 lo_2 = binop( Iop_And64,
7597 mkexpr( rB ),
7598 mkU64( 0xFF ) );
7599 value = binop( Iop_And64,
7600 mkexpr( rA ),
7601 mkU64( 0xFF ) );
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,
7609 binop( Iop_Shl32,
7610 binop( Iop_Or32,
7611 unop( Iop_1Uto32, inrange_2 ),
7612 binop( Iop_And32,
7613 mkU32 ( L ),
7614 unop( Iop_1Uto32, inrange_1 ) ) ),
7615 mkU8( 2 ) ),
7616 BF );
7618 break;
7620 case 0xE0: // cmpeqb (Compare Equal Byte)
7622 Int i;
7623 IRTemp tmp[9];
7624 IRExpr *value;
7626 DIP("cmpeqb %u,r%u,r%u\n", BF, rA_addr, rB_addr);
7628 value = binop( Iop_And64,
7629 mkexpr( rA ),
7630 mkU64( 0xFF ) );
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,
7638 unop( Iop_1Uto32,
7639 binop( Iop_CmpEQ64,
7640 value,
7641 binop( Iop_And64,
7642 binop( Iop_Shr64,
7643 mkexpr( rB ),
7644 mkU8( i*8 ) ),
7645 mkU64( 0xFF ) ) ) ),
7646 mkexpr( tmp[i] ) ) );
7649 putGST_field( PPC_GST_CR,
7650 binop( Iop_Shl32,
7651 unop( Iop_1Uto32,
7652 mkNOT1( binop( Iop_CmpEQ32,
7653 mkexpr( tmp[8] ),
7654 mkU32( 0 ) ) ) ),
7655 mkU8( 2 ) ),
7656 BF );
7658 break;
7660 default:
7661 vex_printf("dis_byte_cmp(ppc)(opc2)\n");
7662 return False;
7664 return True;
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. */
7677 PREFIX_CHECK
7679 if ( opc1 != 0x1F ) {
7680 vex_printf("dis_modulo_int(ppc)(opc1)\n");
7681 return False;
7684 switch (opc2) {
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.
7696 * 0b01 Reserved.
7698 * For our purposes, we will just assume the contition is always
7699 * immediately satisfied.
7701 break;
7702 default:
7703 vex_printf("dis_int_misc(ppc)(opc2)\n");
7704 return False;
7707 return True;
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);
7728 IRExpr *b;
7730 /* There is no prefixed version of these instructions. */
7731 PREFIX_CHECK
7733 if (!mode64 && flag_L==1) { // L==1 invalid for 32 bit.
7734 vex_printf("dis_int_cmp(ppc)(flag_L)\n");
7735 return False;
7738 if (( b22 != 0 ) && ( opc2 != 0x080 ) ) { // setb case exception
7739 vex_printf("dis_int_cmp(ppc)(b22)\n");
7740 return False;
7743 switch (opc1) {
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 );
7748 if (flag_L == 1) {
7749 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
7750 } else {
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() );
7756 break;
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 );
7761 if (flag_L == 1) {
7762 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
7763 } else {
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() );
7769 break;
7771 /* X Form */
7772 case 0x1F:
7773 if (b0 != 0) {
7774 vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n");
7775 return False;
7777 b = getIReg(rB_addr);
7779 switch (opc2) {
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);
7789 if (flag_L == 1) {
7790 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
7791 } else {
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() );
7797 break;
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);
7808 if (flag_L == 1) {
7809 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
7810 } else {
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() );
7816 break;
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
7822 otherwise. */
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
7836 * by bfa.
7838 assign( cr0, binop( Iop_And32,
7839 binop( Iop_Shr32,
7840 mkexpr( cr ),
7841 mkU8( (7-bfa)*4 ) ),
7842 mkU32( 0x8 ) ) );
7843 assign( cr1, binop( Iop_And32,
7844 binop( Iop_Shr32,
7845 mkexpr( cr ),
7846 mkU8( (7-bfa)*4 ) ),
7847 mkU32( 0x4 ) ) );
7848 assign( result, binop( Iop_Or64,
7849 unop( Iop_1Sto64,
7850 binop( Iop_CmpEQ32,
7851 mkexpr( cr0 ),
7852 mkU32( 0x8 ) ) ),
7853 binop( Iop_32HLto64,
7854 mkU32( 0 ),
7855 unop( Iop_1Uto32,
7856 binop( Iop_CmpEQ32,
7857 mkexpr( cr1 ),
7858 mkU32( 0x4 ) ) ) ) ) );
7859 if ( ty == Ity_I64 )
7860 putIReg( rT_addr, mkexpr( result ) );
7861 else
7862 putIReg( rT_addr, unop( Iop_64to32, mkexpr(result ) ) );
7864 break;
7865 default:
7866 vex_printf("dis_int_cmp(ppc)(opc2)\n");
7867 return False;
7869 break;
7871 default:
7872 vex_printf("dis_int_cmp(ppc)(opc1)\n");
7873 return False;
7876 return True;
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);
7898 Bool do_rc = False;
7900 /* There is no prefixed version of these instructions. */
7901 PREFIX_CHECK
7903 assign( rS, getIReg(rS_addr) );
7904 assign( rB, getIReg(rB_addr) );
7906 switch (opc1) {
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
7912 flag_rC = 1;
7913 break;
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
7920 flag_rC = 1;
7921 break;
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)) );
7927 break;
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)) );
7933 break;
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)) );
7939 break;
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)) );
7945 break;
7947 /* X Form */
7948 case 0x1F:
7950 opc2 = IFIELD( theInstr, 2, 9 );
7952 switch ( opc2 ) {
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 ) );
7967 if ( flag_rC ) {
7968 set_CR0( mkexpr( rA ) );
7970 return True;
7972 default:
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 );
7980 switch (opc2) {
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)));
7986 break;
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),
7993 mkexpr(rB))));
7994 break;
7996 case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371)
7997 if (rB_addr!=0) {
7998 vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n");
7999 return False;
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);
8007 break;
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))) );
8016 break;
8018 case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397
8019 if (rB_addr!=0) {
8020 vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n");
8021 return False;
8023 DIP("extsb%s r%u,r%u\n",
8024 flag_rC ? ".":"", rA_addr, rS_addr);
8025 if (mode64)
8026 assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) );
8027 else
8028 assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) );
8029 break;
8031 case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398)
8032 if (rB_addr!=0) {
8033 vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n");
8034 return False;
8036 DIP("extsh%s r%u,r%u\n",
8037 flag_rC ? ".":"", rA_addr, rS_addr);
8038 if (mode64)
8039 assign( rA, unop(Iop_16Sto64,
8040 unop(Iop_64to16, mkexpr(rS))) );
8041 else
8042 assign( rA, unop(Iop_16Sto32,
8043 unop(Iop_32to16, mkexpr(rS))) );
8044 break;
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))) );
8052 break;
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))) );
8060 break;
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) );
8066 } else {
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)) );
8072 break;
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))));
8079 break;
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)) );
8086 break;
8089 /* 64bit Integer Logical Instructions */
8090 case 0x3DA: // extsw (Extend Sign Word, PPC64 p430)
8091 if (rB_addr!=0) {
8092 vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n");
8093 return False;
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))));
8097 break;
8099 case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401)
8100 if (rB_addr!=0) {
8101 vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n");
8102 return False;
8104 DIP("cntlzd%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr);
8105 assign(rA, unop(Iop_ClzNat64, mkexpr(rS)));
8106 break;
8108 case 0x1FC: // cmpb (Power6: compare bytes)
8109 DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
8111 if (mode64)
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) )
8116 )) );
8117 else
8118 assign( rA, unop( Iop_V128to32,
8119 binop( Iop_CmpEQ8x16,
8120 unop( Iop_32UtoV128, mkexpr(rS) ),
8121 unop( Iop_32UtoV128, mkexpr(rB) )
8122 )) );
8123 break;
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
8133 if (mode64)
8134 assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
8135 else
8136 assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) );
8138 putIReg( rS_addr, mkexpr(rA));
8139 return True;
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);
8149 if (mode64)
8150 assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) );
8151 else
8152 assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) );
8154 putFReg( rS_addr, mkexpr(frA));
8155 return True;
8157 case 0x1FA: // popcntd (population count doubleword)
8159 vassert(mode64);
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) );
8163 return True;
8165 case 0x17A: // popcntw (Population Count Words)
8167 DIP("popcntw r%u,r%u\n", rA_addr, rS_addr);
8168 if (mode64) {
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)));
8177 } else {
8178 IRTemp result = gen_POPCOUNT(ty, rS, WORD);
8179 putIReg( rA_addr, mkexpr(result) );
8181 return True;
8183 case 0x7A: // popcntb (Population Count Byte)
8185 DIP("popcntb r%u,r%u\n", rA_addr, rS_addr);
8187 if (mode64) {
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),
8196 mkexpr(resultLo)));
8197 } else {
8198 IRTemp result = gen_POPCOUNT(ty, rS, BYTE);
8199 putIReg( rA_addr, mkexpr(result) );
8201 return True;
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
8213 int i;
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 );
8224 assign( idx_tmp,
8225 binop( Iop_And64, mkU64( BPERMD_IDX_MASK ), rS_expr ) );
8226 assign( idx_LT64,
8227 binop( Iop_CmpLT64U, mkexpr( idx_tmp ), mkU64( 64 ) ) );
8228 assign( idx,
8229 binop( Iop_And8,
8230 unop( Iop_1Sto8,
8231 mkexpr(idx_LT64) ),
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 ) ) ) );
8240 assign( perm_bit,
8241 binop( Iop_And64,
8242 mkexpr( idx_LT64_ity64 ),
8243 binop( Iop_Shr64,
8244 binop( Iop_And64,
8245 mkU64( BPERMD_BIT_MASK ),
8246 binop( Iop_Shl64,
8247 mkexpr( rB ),
8248 mkexpr( idx ) ) ),
8249 mkU8( 63 ) ) ) );
8250 res = binop( Iop_Or64,
8251 res,
8252 binop( Iop_Shl64,
8253 mkexpr( perm_bit ),
8254 mkU8( i ) ) );
8255 rS_expr = binop( Iop_Shr64, rS_expr, mkU8( 8 ) );
8257 putIReg(rA_addr, res);
8258 return True;
8261 default:
8262 vex_printf("dis_int_logic(ppc)(opc2)\n");
8263 return False;
8265 break;
8267 default:
8268 vex_printf("dis_int_logic(ppc)(opc1)\n");
8269 return False;
8272 putIReg( rA_addr, mkexpr(rA) );
8274 if (do_rc && flag_rC) {
8275 set_CR0( mkexpr(rA) );
8277 return True;
8281 Integer Parity Instructions
8283 static Bool dis_int_parity ( UInt prefix, UInt theInstr )
8285 /* X-Form */
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. */
8317 PREFIX_CHECK
8319 if (opc1 != 0x1f || rB_addr || b0) {
8320 vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n");
8321 return False;
8324 assign( rS, getIReg(rS_addr) );
8326 switch (opc2) {
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))),
8333 mkexpr(iTot1)) );
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))),
8337 mkexpr(iTot2)) );
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))),
8341 mkexpr(iTot3)) );
8342 if (mode64) {
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))),
8346 mkexpr(iTot4)) );
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))),
8350 mkexpr(iTot5)) );
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))),
8354 mkexpr(iTot6)) );
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))),
8358 mkexpr(iTot7)) );
8359 assign( rA, unop(Iop_32Uto64,
8360 binop(Iop_And32, mkexpr(iTot8), mkU32(1))) );
8361 } else
8362 assign( rA, mkexpr(iTot4) );
8364 break;
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))),
8370 mkexpr(iTot1)) );
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))),
8374 mkexpr(iTot2)) );
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))),
8378 mkexpr(iTot3)) );
8379 assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) );
8381 if (mode64) {
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))),
8387 mkexpr(iTot5)) );
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))),
8391 mkexpr(iTot6)) );
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))),
8395 mkexpr(iTot7)) );
8396 assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ),
8397 assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) );
8398 } else
8399 assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) );
8400 break;
8401 default:
8402 vex_printf("dis_int_parity(ppc)(opc2)\n");
8403 return False;
8406 putIReg( rA_addr, mkexpr(rA) );
8408 return True;
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);
8435 IRExpr *r;
8436 UInt mask32;
8437 ULong mask64;
8439 /* There is no prefixed version of these instructions. */
8440 PREFIX_CHECK
8442 assign( rS, getIReg(rS_addr) );
8443 assign( rB, getIReg(rB_addr) );
8445 switch (opc1) {
8446 case 0x14: {
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);
8450 if (mode64) {
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))) );
8458 assign( rA,
8459 binop(Iop_Or64,
8460 binop(Iop_And64, mkexpr(rot), mkU64(mask64)),
8461 binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) );
8463 else {
8464 // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask);
8465 mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
8466 r = ROTL(mkexpr(rS), mkU8(sh_imm));
8467 assign( rA,
8468 binop(Iop_Or32,
8469 binop(Iop_And32, mkU32(mask32), r),
8470 binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) );
8472 break;
8475 case 0x15: {
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);
8481 if (mode64) {
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);
8490 assign( rTmp, r );
8491 r = NULL;
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)) );
8496 else {
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)) );
8511 else {
8512 /* General case. */
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)),
8519 mkU32(mask32)) );
8522 break;
8525 case 0x17: {
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);
8529 if (mode64) {
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)) );
8541 } else {
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,
8546 ROTL(mkexpr(rS),
8547 unop(Iop_32to8, mkexpr(rB))),
8548 mkU32(mask32)) );
8550 break;
8553 /* 64bit Integer Rotates */
8554 case 0x1E: {
8555 msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1);
8556 sh_imm |= b1 << 5;
8558 vassert( msk_imm < 64 );
8559 vassert( sh_imm < 64 );
8561 switch (opc2) {
8562 case 0x4: {
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)) );
8572 break;
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)) );
8578 break;
8580 break;
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)) );
8588 break;
8589 // later: deal with special case: (msk_imm==0) => SHL(sh_imm)
8591 Hmm... looks like this'll do the job more simply:
8592 r = SHL(rS, sh_imm)
8593 m = ~(1 << (63-msk_imm))
8594 assign(rA, r & m);
8597 case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558)
8598 if (mode64
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)) );
8605 } else {
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)) );
8612 break;
8614 case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559)
8615 if (mode64
8616 && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) {
8617 /* special-case the ,n,63-n form as that is just
8618 shift-left by n */
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)) );
8622 } else {
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)) );
8629 break;
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))) );
8642 break;
8644 default:
8645 vex_printf("dis_int_rot(ppc)(opc2)\n");
8646 return False;
8648 break;
8651 default:
8652 vex_printf("dis_int_rot(ppc)(opc1)\n");
8653 return False;
8656 putIReg( rA_addr, mkexpr(rA) );
8658 if (flag_rC) {
8659 set_CR0( mkexpr(rA) );
8661 return True;
8666 Integer Load Instructions
8668 static Bool dis_int_load_ds_form_prefix ( UInt prefix,
8669 UInt theInstr )
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;
8682 UInt R = 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 ) );
8694 putIReg( rT_addr,
8695 unop(Iop_32Sto64, load( Ity_I32, mkexpr( EA ) ) ) );
8696 return True;
8698 } else if (opc1 == 0x39) { // pld
8699 pDIP( is_prefix, "ld r%u,%llu(r%u)", rT_addr, immediate_val, rA_addr);
8700 DIPn( is_prefix);
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 ) ) );
8706 return True;
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 ) ) );
8721 break;
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");
8727 return False;
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 ) );
8733 break;
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 );
8739 putIReg( rT_addr,
8740 unop(Iop_32Sto64, load( Ity_I32, mkexpr( EA ) ) ) );
8741 break;
8743 default:
8744 vex_printf("dis_int_load_ds_form_prefix(ppc)(0x3A, opc2)\n");
8745 return False;
8747 return True;
8749 return False;
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 );
8763 UInt size = 0;
8764 ULong immediate_val = 0;
8765 UInt R = 0;
8766 IRExpr* val;
8768 if (opc1 == 0x22) {
8769 // byte loads
8770 size = Ity_I8;
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
8777 size = Ity_I16;
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
8784 size = Ity_I16;
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
8791 size = Ity_I32;
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
8797 // word load
8798 size = Ity_I64;
8800 if (!is_prefix)
8801 assign( EA, calculate_prefix_EA( prefix, theInstr,
8802 rA_addr, ptype, DQFORM_IMMASK,
8803 &immediate_val, &R ) );
8805 else
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
8814 details. */
8815 switch (opc1) {
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) );
8821 break;
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 ) );
8828 break;
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 ) );
8835 break;
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) );
8841 break;
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
8850 * implemented.
8852 //trap if EA misaligned on 16 byte address
8853 if (mode64) {
8854 if (host_endness == VexEndnessBE) {
8855 assign(high, load(ty, mkexpr( EA ) ) );
8856 assign(low, load(ty, binop( Iop_Add64,
8857 mkexpr( EA ),
8858 mkU64( 8 ) ) ) );
8859 } else {
8860 assign(low, load(ty, mkexpr( EA ) ) );
8861 assign(high, load(ty, binop( Iop_Add64,
8862 mkexpr( EA ),
8863 mkU64( 8 ) ) ) );
8865 } else {
8866 assign(high, load(ty, binop( Iop_Add32,
8867 mkexpr( EA ),
8868 mkU32( 4 ) ) ) );
8869 assign(low, load(ty, binop( Iop_Add32,
8870 mkexpr( EA ),
8871 mkU32( 12 ) ) ) );
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) );
8879 } else {
8880 putIReg( rT_addr, mkexpr( high) );
8881 putIReg( rT_addr+1, mkexpr( low) );
8883 break;
8886 default:
8887 vex_printf("dis_int_load_prefix(ppc)(opc1)\n");
8888 return False;
8890 return True;
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);
8907 IRExpr* val;
8909 /* There is no prefixed version of these instructions. */
8910 PREFIX_CHECK
8912 switch (opc1) {
8913 case 0x1F: // register offset
8914 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
8915 break;
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 ) );
8920 break;
8921 default: // immediate offset
8922 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
8923 break;
8926 switch (opc1) {
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");
8930 return False;
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) );
8936 break;
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");
8941 return False;
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) );
8947 break;
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");
8952 return False;
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) );
8958 break;
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");
8963 return False;
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) );
8969 break;
8971 /* X Form */
8972 case 0x1F:
8973 if (b0 != 0) {
8974 vex_printf("dis_int_load(ppc)(Ox1F,b0)\n");
8975 return False;
8978 switch (opc2) {
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");
8983 return False;
8985 val = load(Ity_I8, mkexpr(EA));
8986 putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
8987 putIReg( rA_addr, mkexpr(EA) );
8988 break;
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) );
8994 break;
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");
8999 return False;
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) );
9005 break;
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) );
9011 break;
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");
9016 return False;
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) );
9022 break;
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) );
9028 break;
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");
9033 return False;
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) );
9039 break;
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) );
9045 break;
9048 /* 64bit Loads */
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");
9052 return False;
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) );
9057 break;
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)) );
9062 break;
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");
9067 return False;
9069 DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
9070 putIReg( rD_addr,
9071 unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
9072 putIReg( rA_addr, mkexpr(EA) );
9073 break;
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);
9077 putIReg( rD_addr,
9078 unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
9079 break;
9081 default:
9082 vex_printf("dis_int_load(ppc)(opc2)\n");
9083 return False;
9085 break;
9087 default:
9088 vex_printf("dis_int_load(ppc)(opc1)\n");
9089 return False;
9091 return True;
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. */
9111 switch(opc2) {
9112 case 0x0:
9113 case 0x1:
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 ) );
9125 if (IX == 0) {
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 ) ) ) );
9136 } else {
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 ) ) ) );
9149 putVSReg( XT_addr,
9150 binop( Iop_OrV128,
9151 binop( Iop_AndV128, mkexpr( tmp ), mkexpr( mask) ),
9152 mkexpr( new_elements ) ) );
9153 break;
9155 case 0x2:
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);
9162 assign( result,
9163 unop( Iop_ReinterpF64asI64,
9164 unop( Iop_F32toF64,
9165 unop( Iop_ReinterpI32asF32,
9166 mkU32( IMM32 ) ) ) ) );
9167 putVSReg( XT_addr, binop( Iop_64HLtoV128,
9168 mkexpr( result ), mkexpr( result ) ) );
9170 break;
9172 case 0x3:
9173 /* VSX Vector Splat Immediate Word 8RR:D-form */
9174 DIP("xxspltiw %u,%u\n", XT_addr, IMM32);
9176 putVSReg( XT_addr,
9177 binop( Iop_64HLtoV128,
9178 binop( Iop_32HLto64,
9179 mkU32( IMM32 ), mkU32( IMM32 ) ),
9180 binop( Iop_32HLto64,
9181 mkU32( IMM32 ), mkU32( IMM32 ) ) ) );
9182 break;
9183 default:
9184 vex_printf("dis_vector_splat_imm_prefix (opc2)\n");
9185 return False;
9188 return True;
9192 VSX Vector Permute Extended 8RR:D-form
9194 static Bool dis_vector_permute_prefix ( UInt prefix, UInt theInstr,
9195 const VexAbiInfo* vbi )
9197 #define MAX_ELE 16
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 );
9205 Int i;
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 ) );
9223 switch(opc2) {
9224 case 0:
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 ),
9235 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(). */
9245 if ( i >= 8) {
9246 assign( eidx[i],
9247 binop( Iop_Sub64,
9248 mkU64( 31 ),
9249 binop( Iop_And64,
9250 mkexpr( eidx_mask ),
9251 binop( Iop_Shr64,
9252 unop( Iop_V128HIto64, mkexpr( rXC ) ),
9253 mkU8( (i - 8)*8 ) ) ) ) );
9254 assign( result_mask[i],
9255 unop( Iop_1Sto64,
9256 binop( Iop_CmpEQ64,
9257 mkU64( UIM ),
9258 binop( Iop_And64,
9259 mkexpr ( cmp_mask ),
9260 // bits 0:2 of ith byte
9261 binop( Iop_Shr64,
9262 unop( Iop_V128HIto64,
9263 mkexpr( rXC ) ),
9264 mkU8( (i - 8)*8 + 5 ) ) )
9265 ) ) );
9266 } else {
9267 assign( eidx[i],
9268 binop( Iop_Sub64,
9269 mkU64( 31 ),
9270 binop( Iop_And64,
9271 mkexpr( eidx_mask ),
9272 binop( Iop_Shr64,
9273 unop( Iop_V128to64, mkexpr( rXC ) ),
9274 mkU8( i*8 ) ) ) ) );
9275 assign( result_mask[i],
9276 unop( Iop_1Sto64,
9277 binop( Iop_CmpEQ64,
9278 mkU64( UIM ),
9279 binop( Iop_And64,
9280 mkexpr ( cmp_mask ),
9281 // bits 0:2 of ith byte
9282 binop( Iop_Shr64,
9283 unop( Iop_V128to64,
9284 mkexpr( rXC ) ),
9285 mkU8( i*8 + 5 ) ) ) ) ) );
9288 assign( byte[i],
9289 binop( Iop_And64,
9290 mkexpr( result_mask[i] ),
9291 extractBytefromV256( rXA, rXB, eidx[i] ) ) );
9293 assign( result[i], insert_field_into_vector( result[i+1],
9294 mkU64( i ),
9295 mkexpr( byte[i] ),
9296 mkU64( 0xFF ) ) );
9298 putVSReg( rXT_addr, mkexpr( result[0] ) );
9300 break;
9302 case 1:
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);
9307 putVSReg( rXT_addr,
9308 vector_evaluate_inst ( vbi, mkexpr( rXA ), mkexpr( rXB ),
9309 mkexpr( rXC ), mkU64( IMM ) ) );
9311 break;
9313 default:
9314 vex_printf("dis_vector_permute_prefix(ppc)(opc2)\n");
9315 return False;
9318 return True;
9319 #undef MAX_ELE
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
9354 position. */
9356 assign( rXA, getVSReg( rXA_addr ) );
9357 assign( rXB, getVSReg( rXB_addr ) );
9358 assign( rXC, getVSReg( rXC_addr ) );
9360 assign( mask_gen,
9361 binop( Iop_64HLtoV128,
9362 mkU64( 0xFFFFFFFFFFFFFFFFULL),
9363 mkU64( 0xFFFFFFFFFFFFFFFFULL) ) );
9365 switch(opc2) {
9366 case 0:
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);
9371 assign( bit_mask,
9372 binop( Iop_ShrV128,
9373 binop( Iop_AndV128,
9374 mkexpr( rXC ),
9375 binop( Iop_64HLtoV128,
9376 mkU64( 0x8080808080808080ULL ),
9377 mkU64( 0x8080808080808080ULL ) ) ),
9378 mkU8 ( 7 ) ) );
9379 assign( mask,
9380 binop( Iop_OrV128,
9381 binop( Iop_MullEven8Ux16,
9382 mkexpr( mask_gen ),
9383 mkexpr( bit_mask ) ),
9384 binop( Iop_ShlV128,
9385 MK_Iop_MullOdd8Ux16(
9386 mkexpr( mask_gen ),
9387 mkexpr( bit_mask ) ),
9388 mkU8( 8 ) ) ) );
9389 break;
9391 case 1:
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);
9396 assign( bit_mask,
9397 binop( Iop_ShrV128,
9398 binop( Iop_AndV128,
9399 mkexpr( rXC ),
9400 binop( Iop_64HLtoV128,
9401 mkU64( 0x8000800080008000ULL ),
9402 mkU64( 0x8000800080008000ULL ) ) ),
9403 mkU8 ( 15 ) ) );
9404 assign( mask,
9405 binop( Iop_OrV128,
9406 binop( Iop_MullEven16Ux8,
9407 mkexpr( mask_gen ),
9408 mkexpr( bit_mask ) ),
9409 binop( Iop_ShlV128,
9410 MK_Iop_MullOdd16Ux8(
9411 mkexpr( mask_gen ),
9412 mkexpr( bit_mask ) ),
9413 mkU8( 16 ) ) ) );
9414 break;
9416 case 2:
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);
9421 assign( bit_mask,
9422 binop( Iop_ShrV128,
9423 binop( Iop_AndV128,
9424 mkexpr( rXC ),
9425 binop( Iop_64HLtoV128,
9426 mkU64( 0x8000000080000000ULL ),
9427 mkU64( 0x8000000080000000ULL ) ) ),
9428 mkU8 ( 31 ) ) );
9429 assign( mask,
9430 binop( Iop_OrV128,
9431 binop( Iop_MullEven32Ux4,
9432 mkexpr( mask_gen ),
9433 mkexpr( bit_mask ) ),
9434 binop( Iop_ShlV128,
9435 MK_Iop_MullOdd32Ux4(
9436 mkexpr( mask_gen ),
9437 mkexpr( bit_mask ) ),
9438 mkU8( 32 ) ) ) );
9439 break;
9441 case 3:
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 */
9447 assign( mask,
9448 binop( Iop_64HLtoV128,
9449 unop( Iop_1Sto64,
9450 unop( Iop_64to1,
9451 binop( Iop_Shr64,
9452 unop( Iop_V128HIto64,
9453 mkexpr( rXC ) ),
9454 mkU8( 63) ) ) ),
9455 unop( Iop_1Sto64,
9456 unop( Iop_64to1,
9457 binop( Iop_Shr64,
9458 unop( Iop_V128to64,
9459 mkexpr( rXC ) ),
9460 mkU8( 63) ) ) ) ) );
9461 break;
9463 default:
9464 vex_printf("dis_vector_blend_prefix (opc2)\n");
9465 return False;
9467 putVSReg( rXT_addr, binop( Iop_OrV128,
9468 binop( Iop_AndV128,
9469 unop( Iop_NotV128, mkexpr( mask ) ),
9470 mkexpr( rXA ) ),
9471 binop( Iop_AndV128,
9472 mkexpr( mask ),
9473 mkexpr( rXB ) ) ) );
9474 return True;
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));
9498 if (opc1 == 0x3C) {
9499 // force opc2 to 2 to map pstq to stq inst
9500 b0 = 0;
9501 b1 = 1;
9502 assign( EA, calculate_prefix_EA( prefix, theInstr, rA_addr,
9503 ptype, DSFORM_IMMASK, &immediate_val,
9504 &R ) );
9505 } else if (opc1 == 0x3D) {
9506 // force opc2 to 0 to map pstd to std inst
9507 b0 = 0;
9508 b1 = 0;
9509 assign( EA, calculate_prefix_EA( prefix, theInstr, rA_addr,
9510 ptype, DFORM_IMMASK, &immediate_val,
9511 &R ) );
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 ) );
9521 } else {
9522 return False;
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)
9531 if (!mode64)
9532 return False;
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) );
9537 break;
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
9542 here. */
9543 if (!mode64)
9544 return False;
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) );
9549 break;
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 );
9559 if (mode64) {
9560 if (host_endness == VexEndnessBE) {
9562 /* upper 64-bits */
9563 assign( EA_hi, mkexpr(EA));
9565 /* lower 64-bits */
9566 assign( EA_lo, binop(Iop_Add64, mkexpr(EA), mkU64(8)));
9568 } else {
9569 /* upper 64-bits */
9570 assign( EA_hi, binop(Iop_Add64, mkexpr(EA), mkU64(8)));
9572 /* lower 64-bits */
9573 assign( EA_lo, mkexpr(EA));
9575 } else {
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
9585 store. */
9586 if (is_prefix &&( host_endness == VexEndnessLE )) {
9587 // LE and pstq
9588 store( mkexpr(EA_hi), getIReg( rS_addr+1 ) );
9589 store( mkexpr(EA_lo), mkexpr(rS) );
9590 } else {
9591 store( mkexpr(EA_hi), mkexpr(rS) );
9592 store( mkexpr(EA_lo), getIReg( rS_addr+1 ) );
9594 break;
9596 default:
9597 vex_printf("dis_int_store_ds_prefix(ppc)(opc1)\n");
9598 return False;
9600 return True;
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 ) );
9622 switch (opc1) {
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)) );
9627 break;
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)) );
9633 break;
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)) );
9639 break;
9641 default:
9642 vex_printf("dis_int_store_prefix(ppc)(opc1)\n");
9643 return False;
9645 return True;
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. */
9666 PREFIX_CHECK
9668 assign( rB, getIReg(rB_addr) );
9669 assign( rS, getIReg(rS_addr) );
9671 switch (opc1) {
9672 case 0x1F: // register offset
9673 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
9674 break;
9676 /* fallthrough */
9677 default: // immediate offset
9678 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
9679 break;
9682 switch (opc1) {
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");
9686 return False;
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)) );
9691 break;
9693 case 0x2D: // sthu (Store HW, Update, PPC32 p524)
9694 if (rA_addr == 0) {
9695 vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n");
9696 return False;
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)) );
9701 break;
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)) );
9708 break;
9710 case 0x25: // stwu (Store W, Update, PPC32 p534)
9711 if (rA_addr == 0) {
9712 vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n");
9713 return False;
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)) );
9718 break;
9720 /* X Form : all these use EA_indexed */
9721 case 0x1F:
9722 if (b0 != 0) {
9723 vex_printf("dis_int_store(ppc)(0x1F,b0)\n");
9724 return False;
9727 switch (opc2) {
9728 case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511)
9729 if (rA_addr == 0) {
9730 vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n");
9731 return False;
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)) );
9736 break;
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)) );
9741 break;
9743 case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525)
9744 if (rA_addr == 0) {
9745 vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n");
9746 return False;
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)) );
9751 break;
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)) );
9756 break;
9758 case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535)
9759 if (rA_addr == 0) {
9760 vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n");
9761 return False;
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)) );
9766 break;
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)) );
9771 break;
9774 /* 64bit Stores */
9775 case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584)
9776 if (rA_addr == 0) {
9777 vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n");
9778 return False;
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) );
9783 break;
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) );
9788 break;
9790 default:
9791 vex_printf("dis_int_store(ppc)(opc2)\n");
9792 return False;
9794 break;
9796 default:
9797 vex_printf("dis_int_store(ppc)(opc1)\n");
9798 return False;
9800 return True;
9806 Integer Load/Store Multiple Instructions
9808 static Bool dis_int_ldst_mult ( UInt prefix, UInt theInstr )
9810 /* D-Form */
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);
9821 UInt r = 0;
9822 UInt ea_off = 0;
9823 IRExpr* irx_addr;
9825 /* There is no prefixed version of these instructions. */
9826 PREFIX_CHECK
9828 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
9830 switch (opc1) {
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");
9834 return False;
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 ),
9840 False) );
9841 ea_off += 4;
9843 break;
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)) );
9850 ea_off += 4;
9852 break;
9854 default:
9855 vex_printf("dis_int_ldst_mult(ppc)(opc1)\n");
9856 return False;
9858 return True;
9864 Integer Load/Store String Instructions
9866 static
9867 void generate_lsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32
9868 IRTemp EA, // EA
9869 Int rD, // first dst register
9870 Int maxBytes ) // 32 or 128
9872 Int i, shift = 24;
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)),
9883 Ijk_Boring,
9884 mkSzConst( ty, nextInsnAddr()), OFFB_CIA ));
9885 /* when crossing into a new dest register, set it to zero. */
9886 if ((i % 4) == 0) {
9887 rD++; if (rD == 32) rD = 0;
9888 putIReg(rD, mkSzImm(ty, 0));
9889 shift = 24;
9891 /* rD |= (8Uto32(*(EA+i))) << shift */
9892 vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
9893 putIReg(
9894 rD,
9895 mkWidenFrom32(
9896 ty,
9897 binop(
9898 Iop_Or32,
9899 mkNarrowTo32(ty, getIReg(rD)),
9900 binop(
9901 Iop_Shl32,
9902 unop(
9903 Iop_8Uto32,
9904 load( Ity_I8,
9905 binop( mkSzOp(ty,Iop_Add8),
9906 e_EA, mkSzImm(ty,i)))
9908 mkU8(toUChar(shift))
9911 /*Signed*/False
9914 shift -= 8;
9918 static
9919 void generate_stsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32
9920 IRTemp EA, // EA
9921 Int rS, // first src register
9922 Int maxBytes ) // 32 or 128
9924 Int i, shift = 24;
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)),
9935 Ijk_Boring,
9936 mkSzConst( ty, nextInsnAddr() ), OFFB_CIA ));
9937 /* check for crossing into a new src register. */
9938 if ((i % 4) == 0) {
9939 rS++; if (rS == 32) rS = 0;
9940 shift = 24;
9942 /* *(EA+i) = 32to8(rS >> shift) */
9943 vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
9944 store(
9945 binop( mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)),
9946 unop( Iop_32to8,
9947 binop( Iop_Shr32,
9948 mkNarrowTo32( ty, getIReg(rS) ),
9949 mkU8( toUChar(shift) )))
9951 shift -= 8;
9955 static Bool dis_int_ldst_str ( UInt prefix, UInt theInstr, /*OUT*/Bool* stopHere )
9957 /* X-Form */
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. */
9972 PREFIX_CHECK
9974 *stopHere = False;
9976 if (opc1 != 0x1F || b0 != 0) {
9977 vex_printf("dis_int_ldst_str(ppc)(opc1)\n");
9978 return False;
9981 switch (opc2) {
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] */
9990 putIReg( rD_addr,
9991 load(Ity_I32, mkexpr(t_EA)) );
9992 putIReg( (rD_addr+1) % 32,
9993 load(Ity_I32,
9994 binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) );
9995 } else {
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 );
9999 *stopHere = True;
10001 return True;
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
10007 do so. */
10008 if (rD_addr == rA_addr || rD_addr == rB_addr)
10009 return False;
10010 if (rD_addr == 0 && rA_addr == 0)
10011 return False;
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 );
10017 *stopHere = True;
10018 return True;
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) );
10030 } else {
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 );
10034 *stopHere = True;
10036 return True;
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 );
10044 *stopHere = True;
10045 return True;
10047 default:
10048 vex_printf("dis_int_ldst_str(ppc)(opc2)\n");
10049 return False;
10051 return True;
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) );
10072 } else {
10073 if ((BO >> 1) & 1) { // ctr == 0 ?
10074 assign( ok, unop( Iop_1Sto32,
10075 binop( mkSzOp(ty, Iop_CmpEQ8),
10076 getGST( PPC_GST_CTR ),
10077 mkSzImm(ty,0))) );
10078 } else { // ctr != 0 ?
10079 assign( ok, unop( Iop_1Sto32,
10080 binop( mkSzOp(ty, Iop_CmpNE8),
10081 getGST( PPC_GST_CTR ),
10082 mkSzImm(ty,0))) );
10085 return mkexpr(ok);
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 )
10096 Int where;
10097 IRTemp res = newTemp(Ity_I32);
10098 IRTemp cr_bi = newTemp(Ity_I32);
10100 if ((BO >> 4) & 1) {
10101 assign( res, mkU32(1) );
10102 } else {
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) );
10111 } else {
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;
10141 Addr64 tgt = 0;
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. */
10151 PREFIX_CHECK
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 );
10157 return True;
10160 /* The default what-next. Individual cases can override it. */
10161 dres->whatNext = Dis_StopHere;
10162 vassert(dres->jk_StopHere == Ijk_INVALID);
10164 switch (opc1) {
10165 case 0x12: // b (Branch, PPC32 p360)
10166 if (flag_AA) {
10167 tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) );
10168 } else {
10169 tgt = mkSzAddr( ty, guest_CIA_curr_instr +
10170 (Long)extend_s_26to64(LI_u26) );
10172 if (mode64) {
10173 DIP("b%s%s 0x%llx\n",
10174 flag_LK ? "l" : "", flag_AA ? "a" : "", tgt);
10175 } else {
10176 DIP("b%s%s 0x%x\n",
10177 flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt);
10180 if (flag_LK) {
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) );
10193 break;
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);
10199 if (!(BO & 0x4)) {
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 ) );
10212 assign( do_branch,
10213 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
10215 if (flag_AA) {
10216 tgt = mkSzAddr(ty, extend_s_16to64(BD_u16));
10217 } else {
10218 tgt = mkSzAddr(ty, guest_CIA_curr_instr +
10219 (Long)extend_s_16to64(BD_u16));
10221 if (flag_LK)
10222 putGST( PPC_GST_LR, e_nia );
10224 stmt( IRStmt_Exit(
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 );
10231 break;
10233 case 0x13:
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);
10239 return False;
10242 switch (opc2) {
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");
10246 return False;
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 ));
10256 if (flag_LK)
10257 putGST( PPC_GST_LR, e_nia );
10259 stmt( IRStmt_Exit(
10260 binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)),
10261 Ijk_Boring,
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) );
10271 break;
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) {
10276 DIP("blr\n");
10277 vanilla_return = True;
10278 } else {
10279 DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
10282 if (!(BO & 0x4)) {
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 ) );
10291 assign( do_branch,
10292 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
10294 assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 ));
10296 if (flag_LK)
10297 putGST( PPC_GST_LR, e_nia );
10299 stmt( IRStmt_Exit(
10300 binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)),
10301 Ijk_Boring,
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) );
10314 break;
10316 default:
10317 vex_printf("dis_int_branch(ppc)(opc2)\n");
10318 return False;
10320 break;
10322 default:
10323 vex_printf("dis_int_branch(ppc)(opc1)\n");
10324 return False;
10327 return True;
10331 * PC relative instruction
10333 static Bool dis_pc_relative ( UInt prefix, UInt theInstr )
10335 /* DX-Form */
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. */
10346 PREFIX_CHECK
10348 if ( opc1 != 0x13) {
10349 vex_printf("dis_pc_relative(ppc)(opc1)\n");
10350 return False;
10353 switch (opc2) {
10354 case 0x002: // addpcis (Add PC immediate Shifted DX-form)
10356 IRExpr* nia = mkSzImm(ty, nextInsnAddr());
10357 IRExpr* result;
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 ) );
10367 } else {
10368 vassert( ty == Ity_I64 );
10369 result = binop( Iop_Add64, nia, mkU64( D << 16 ) );
10372 putIReg( rT_addr, result);
10374 break;
10376 default:
10377 vex_printf("dis_pc_relative(ppc)(opc2)\n");
10378 return False;
10381 return True;
10385 Condition Register Logical Instructions
10387 static Bool dis_cond_logic ( UInt prefix, UInt theInstr )
10389 /* XL-Form */
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. */
10404 PREFIX_CHECK
10406 if (opc1 != 19 || b0 != 0) {
10407 vex_printf("dis_cond_logic(ppc)(opc1)\n");
10408 return False;
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");
10415 return False;
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) );
10420 } else {
10421 assign( crbA, getCRbit(crbA_addr) );
10422 if (crbA_addr == crbB_addr)
10423 crbB = crbA;
10424 else
10425 assign( crbB, getCRbit(crbB_addr) );
10427 switch (opc2) {
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)) );
10431 break;
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,
10435 mkexpr(crbA),
10436 unop(Iop_Not32, mkexpr(crbB))) );
10437 break;
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))) );
10442 break;
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))) );
10447 break;
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))) );
10452 break;
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)) );
10456 break;
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,
10460 mkexpr(crbA),
10461 unop(Iop_Not32, mkexpr(crbB))) );
10462 break;
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)) );
10466 break;
10467 default:
10468 vex_printf("dis_cond_logic(ppc)(opc2)\n");
10469 return False;
10472 putCRbit( crbD_addr, mkexpr(crbD) );
10474 return True;
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;
10483 IROp Iop_1XtoX;
10485 /* There is no prefixed version of these instructions. */
10486 vassert( !prefix_instruction( prefixInstr ) );
10488 switch (opc2) {
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,
10496 getCRbit( BI ),
10497 mkU32( 1 ) ) ) );
10498 break;
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,
10507 getCRbit( BI ),
10508 mkU32( 1 ) ) ) );
10509 break;
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),
10517 mkSzImm( ty, -1 ),
10518 unop( Iop_1XtoX,
10519 binop( Iop_CmpEQ32,
10520 getCRbit( BI ),
10521 mkU32( 1 ) ) ) ) );
10522 break;
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),
10530 mkSzImm( ty, -1 ),
10531 unop( Iop_1XtoX,
10532 binop( Iop_CmpNE32,
10533 getCRbit( BI ),
10534 mkU32( 1 ) ) ) ) );
10535 break;
10537 default:
10538 vex_printf("dis_set_bool_condition(ppc)(opc2)\n");
10539 return False;
10542 return True;
10546 Trap instructions
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
10553 instructions. */
10554 static Bool do_trap ( UChar TO,
10555 IRExpr* argL0, IRExpr* argR0, Addr64 cia )
10557 IRTemp argL, argR;
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;
10576 if (is32bit) {
10577 vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 );
10578 vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 );
10579 } else {
10580 vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 );
10581 vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 );
10582 vassert( mode64 );
10585 if ((TO & b11100) == b11100 || (TO & b00111) == b00111) {
10586 /* Unconditional trap. Just do the exit without
10587 testing the arguments. */
10588 stmt( IRStmt_Exit(
10589 binop(opCMPEQ, const0, const0),
10590 Ijk_SigTRAP,
10591 mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia),
10592 OFFB_CIA
10594 return True; /* unconditional trap */
10597 if (is32bit) {
10598 argL = newTemp(Ity_I32);
10599 argR = newTemp(Ity_I32);
10600 } else {
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);
10611 cond = const0;
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);
10632 stmt( IRStmt_Exit(
10633 binop(opCMPNE, cond, const0),
10634 Ijk_SigTRAP,
10635 mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia),
10636 OFFB_CIA
10638 return False; /* not an unconditional trap */
10641 static Bool dis_trapi ( UInt prefix, UInt theInstr,
10642 /*OUT*/DisResult* dres )
10644 /* D-Form */
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. */
10655 PREFIX_CHECK
10657 switch (opc1) {
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 ),
10663 cia );
10664 if (TO == 4) {
10665 DIP("tweqi r%u,%d\n", rA_addr, (Int)simm16);
10666 } else {
10667 DIP("tw%di r%u,%d\n", TO, rA_addr, (Int)simm16);
10669 break;
10670 case 0x02: // tdi
10671 if (!mode64)
10672 return False;
10673 uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia );
10674 if (TO == 4) {
10675 DIP("tdeqi r%u,%d\n", rA_addr, (Int)simm16);
10676 } else {
10677 DIP("td%di r%u,%d\n", TO, rA_addr, (Int)simm16);
10679 break;
10680 default:
10681 return False;
10684 if (uncond) {
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;
10692 return True;
10695 static Bool dis_trap ( UInt prefix, UInt theInstr,
10696 /*OUT*/DisResult* dres )
10698 /* X-Form */
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. */
10708 PREFIX_CHECK
10710 if (ifieldBIT0(theInstr) != 0)
10711 return False;
10713 switch (opc2) {
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),
10720 cia );
10721 if (TO == 4) {
10722 DIP("tweq r%u,r%u\n", rA_addr, rB_addr);
10723 } else {
10724 DIP("tw%d r%u,r%u\n", TO, rA_addr, rB_addr);
10726 break;
10727 case 0x044: // td (Trap Doubleword, PPC64 p534)
10728 if (!mode64)
10729 return False;
10730 uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia );
10731 if (TO == 4) {
10732 DIP("tdeq r%u,r%u\n", rA_addr, rB_addr);
10733 } else {
10734 DIP("td%d r%u,r%u\n", TO, rA_addr, rB_addr);
10736 break;
10737 default:
10738 return False;
10741 if (uncond) {
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;
10749 return True;
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. */
10764 PREFIX_CHECK
10766 if ((theInstr != 0x44000002) // sc
10767 && (theInstr != 0x44000001)) { // scv
10768 vex_printf("dis_syslink(ppc)(theInstr)\n");
10769 return False;
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)
10777 DIP("sc\n");
10778 put_syscall_flag( mkU32(SC_FLAG) );
10779 } else if (theInstr == 0x44000001) {
10780 if (allow_scv) { // scv
10781 DIP("scv\n");
10782 put_syscall_flag( mkU32(SCV_FLAG) );
10783 } else {
10784 if (sigill_diag)
10785 vex_printf("The scv instruction is not supported in this environment per the HWCAPS2 capability flags.\n");
10786 return False;
10788 } else {
10789 /* Unknown instruction */
10790 return False;
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;
10805 return True;
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. */
10839 PREFIX_CHECK
10841 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
10843 switch (opc1) {
10844 /* XL-Form */
10845 case 0x13: // isync (Instruction Synchronize, PPC32 p432)
10846 if (opc2 != 0x096) {
10847 vex_printf("dis_memsync(ppc)(0x13,opc2)\n");
10848 return False;
10850 if (b11to25 != 0 || b0 != 0) {
10851 vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n");
10852 return False;
10854 DIP("isync\n");
10855 stmt( IRStmt_MBE(Imbe_Fence) );
10856 break;
10858 /* X-Form */
10859 case 0x1F:
10860 switch (opc2) {
10861 case 0x356: // eieio or mbar (Enforce In-Order Exec of I/O, PPC32 p394)
10862 if (M0 == 0) {
10863 if (b11to20 != 0 || b0 != 0) {
10864 vex_printf("dis_memsync(ppc)(eieio,b11to20|b0)\n");
10865 return False;
10867 DIP("eieio\n");
10868 } else {
10869 if (b11to20 != 0 || b0 != 0) {
10870 vex_printf("dis_memsync(ppc)(mbar,b11to20|b0)\n");
10871 return False;
10873 DIP("mbar %u\n", M0);
10875 /* Insert a memory fence, just to be on the safe side. */
10876 stmt( IRStmt_MBE(Imbe_Fence) );
10877 break;
10879 case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458)
10880 IRTemp res;
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) );
10895 break;
10898 case 0x034: { // lbarx (Load Word and Reserve Indexed)
10899 IRTemp res;
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) );
10911 break;
10914 case 0x074: { // lharx (Load Word and Reserve Indexed)
10915 IRTemp res;
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) );
10930 break;
10933 case 0x096: {
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);
10938 IRTemp resSC;
10939 if (b0 != 1) {
10940 vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
10941 return False;
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());
10960 /* Note:
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? */
10964 break;
10967 case 0x2B6: {
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);
10972 IRTemp resSC;
10973 if (b0 != 1) {
10974 vex_printf("dis_memsync(ppc)(stbcx.,b0)\n");
10975 return False;
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());
10991 /* Note:
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? */
10995 break;
10998 case 0x2D6: {
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);
11003 IRTemp resSC;
11004 if (b0 != 1) {
11005 vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
11006 return False;
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());
11025 /* Note:
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? */
11029 break;
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
11043 necessary.
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.
11051 sync = sync 0
11052 lwsync = sync 1
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");
11059 return False;
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");
11068 return False;
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) );
11075 break;
11077 /* 64bit Memsync */
11078 case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473)
11079 IRTemp res;
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. */
11084 if (!mode64)
11085 return False;
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) );
11096 break;
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);
11102 IRTemp resSC;
11103 if (b0 != 1) {
11104 vex_printf("dis_memsync(ppc)(stdcx.,b0)\n");
11105 return False;
11107 if (!mode64)
11108 return False;
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());
11126 /* Note:
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? */
11130 break;
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
11148 if (mode64) {
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*/) );
11155 } else {
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*/) );
11162 } else {
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) );
11172 break;
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);
11179 IRTemp resSC;
11180 if (b0 != 1) {
11181 vex_printf("dis_memsync(ppc)(stqcx.,b0)\n");
11182 return False;
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);
11196 if (mode64) {
11197 if (host_endness == VexEndnessBE) {
11198 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_hi) ) );
11199 store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ),
11200 mkexpr(rS_lo) );
11201 } else {
11202 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_lo) ) );
11203 store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ),
11204 mkexpr(rS_hi) );
11206 } else {
11207 stmt( stmt_load( resSC, binop( Iop_Add32,
11208 mkexpr(EA),
11209 mkU32(4) ),
11210 mkexpr(rS_hi) ) );
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) ),
11218 mkU8(1)));
11219 putCR0(0, getXER_SO());
11220 break;
11223 default:
11224 vex_printf("dis_memsync(ppc)(opc2)\n");
11225 return False;
11227 break;
11229 default:
11230 vex_printf("dis_memsync(ppc)(opc1)\n");
11231 return False;
11233 return True;
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);
11260 IRExpr* e_tmp;
11262 /* There is no prefixed version of these instructions. */
11263 PREFIX_CHECK
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) {
11271 switch (opc2) {
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
11279 for y in 32 .. 63
11281 e_tmp =
11282 binop( Iop_And32,
11283 binop( Iop_Shl32,
11284 mkexpr(rS_lo32),
11285 unop( Iop_32to8,
11286 binop(Iop_And32,
11287 mkexpr(rB_lo32), mkU32(31)))),
11288 unop( Iop_Not32,
11289 binop( Iop_Sar32,
11290 binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)),
11291 mkU8(31))) );
11292 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
11293 break;
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:
11301 amt = rB & 63
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,
11310 mkexpr(rS_lo32),
11311 unop( Iop_32to8,
11312 IRExpr_ITE( mkexpr(outofrange),
11313 mkU32(31),
11314 mkexpr(sh_amt)) ) );
11315 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) );
11317 /* Set CA bit */
11318 set_XER_CA_CA32( ty, PPCG_FLAG_OP_SRAW,
11319 mkexpr(rA),
11320 mkWidenFrom32(ty, mkexpr(rS_lo32), True),
11321 mkWidenFrom32(ty, mkexpr(sh_amt), True ),
11322 mkWidenFrom32(ty, getXER_CA_32(), True) );
11324 if (allow_isa_3_0)
11325 /* copy CA to CA32 */
11326 putXER_CA32( unop(Iop_32to8, getXER_CA_32()));
11327 break;
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);
11334 if (mode64) {
11335 assign( rA, binop(Iop_Sar64,
11336 binop(Iop_Shl64, getIReg(rS_addr),
11337 mkU8(32)),
11338 mkU8(32 + sh_imm)) );
11339 } else {
11340 assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32),
11341 mkU8(sh_imm)) );
11344 /* Set CA bit */
11345 set_XER_CA_CA32( ty, PPCG_FLAG_OP_SRAWI,
11346 mkexpr(rA),
11347 mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True),
11348 mkSzImm(ty, sh_imm),
11349 mkWidenFrom32(ty, getXER_CA_32(), /* Syned */False) );
11351 if (allow_isa_3_0)
11352 /* copy CA to CA32 */
11353 putXER_CA32( unop(Iop_32to8, getXER_CA_32()));
11354 break;
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
11363 for y in 32 .. 63
11365 e_tmp =
11366 binop(
11367 Iop_And32,
11368 binop( Iop_Shr32,
11369 mkexpr(rS_lo32),
11370 unop( Iop_32to8,
11371 binop(Iop_And32, mkexpr(rB_lo32),
11372 mkU32(31)))),
11373 unop( Iop_Not32,
11374 binop( Iop_Sar32,
11375 binop(Iop_Shl32, mkexpr(rB_lo32),
11376 mkU8(26)),
11377 mkU8(31))));
11378 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
11379 break;
11382 /* 64bit Shifts */
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
11390 for y in 64 ..
11392 assign( rA,
11393 binop(
11394 Iop_And64,
11395 binop( Iop_Shl64,
11396 mkexpr(rS),
11397 unop( Iop_64to8,
11398 binop(Iop_And64, mkexpr(rB), mkU64(63)))),
11399 unop( Iop_Not64,
11400 binop( Iop_Sar64,
11401 binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
11402 mkU8(63)))) );
11403 break;
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);
11409 /* amt = rB & 127
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)) );
11416 assign( rA,
11417 binop( Iop_Sar64,
11418 mkexpr(rS),
11419 unop( Iop_64to8,
11420 IRExpr_ITE( mkexpr(outofrange),
11421 mkU64(63),
11422 mkexpr(sh_amt)) ))
11424 /* Set CA bit */
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) );
11429 if (allow_isa_3_0)
11430 /* copy CA to CA32 */
11431 putXER_CA32( unop(Iop_32to8, getXER_CA_32()));
11432 break;
11435 case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571)
11436 sh_imm |= b1<<5;
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)) );
11442 /* Set CA bit */
11443 set_XER_CA_CA32( ty, PPCG_FLAG_OP_SRADI,
11444 mkexpr(rA),
11445 getIReg(rS_addr),
11446 mkU64(sh_imm),
11447 mkWidenFrom32(ty, getXER_CA_32(), /* Syned */False) );
11449 if (allow_isa_3_0)
11450 /* copy CA to CA32 */
11451 putXER_CA32( unop(Iop_32to8, getXER_CA_32()));
11452 break;
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
11461 for y in 64 .. 127
11463 assign( rA,
11464 binop(
11465 Iop_And64,
11466 binop( Iop_Shr64,
11467 mkexpr(rS),
11468 unop( Iop_64to8,
11469 binop(Iop_And64, mkexpr(rB), mkU64(63)))),
11470 unop( Iop_Not64,
11471 binop( Iop_Sar64,
11472 binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
11473 mkU8(63)))) );
11474 break;
11476 default:
11477 vex_printf("dis_int_shift(ppc)(opc2)\n");
11478 return False;
11480 } else {
11481 vex_printf("dis_int_shift(ppc)(opc1)\n");
11482 return False;
11485 putIReg( rA_addr, mkexpr(rA) );
11487 if (flag_rC) {
11488 set_CR0( mkexpr(rA) );
11490 return True;
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);
11510 return
11511 binop(Iop_Or32,
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)),
11515 mkU32(0x000000FF))
11519 static Bool dis_int_ldst_rev ( UInt prefix, UInt theInstr )
11521 /* X-Form */
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. */
11536 PREFIX_CHECK
11538 if (opc1 != 0x1F || b0 != 0) {
11539 vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n");
11540 return False;
11543 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
11545 switch (opc2) {
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) );
11553 break;
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) );
11561 break;
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)));
11574 else
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) );
11587 break;
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)) );
11594 break;
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) );
11600 break;
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 ) ) );
11614 break;
11617 default:
11618 vex_printf("dis_int_ldst_rev(ppc)(opc2)\n");
11619 return False;
11621 return True;
11627 Processor Control Instructions
11629 static Bool dis_proc_ctl ( const VexAbiInfo* vbi, UInt prefix, UInt theInstr )
11631 UChar opc1 = ifieldOPC(theInstr);
11633 /* X-Form */
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 );
11639 /* XFX-Form */
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. */
11654 PREFIX_CHECK
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);
11668 return False;
11671 switch (opc2) {
11672 /* X-Form */
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");
11676 return False;
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 ),
11682 crfD );
11684 // Clear XER[0-3]
11685 putXER_SO( mkU8(0) );
11686 putXER_OV( mkU8(0) );
11687 putXER_CA( mkU8(0) );
11688 break;
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");
11700 return False;
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 */
11710 assign( tmp,
11711 binop( Iop_Or32,
11712 binop( Iop_Or32, mkexpr ( OV ), mkexpr ( OV32 ) ),
11713 binop( Iop_Or32, mkexpr ( CA ), mkexpr ( CA32 ) )
11714 ) );
11716 putGST_field( PPC_GST_CR, mkexpr( tmp ), crfD );
11717 break;
11720 case 0x013:
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) );
11729 break;
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) );
11735 break;
11737 /* not decodable */
11738 return False;
11740 /* XFX-Form */
11741 case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470)
11743 switch (SPR) { // Choose a register...
11744 case 0x1:
11745 DIP("mfxer r%u\n", rD_addr);
11746 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ),
11747 /* Signed */False) );
11748 break;
11749 case 0x3: // 131
11750 DIP("mfspr r%u (DSCR)\n", rD_addr);
11751 putIReg( rD_addr, getGST( PPC_GST_DSCR) );
11752 break;
11753 case 0x8:
11754 DIP("mflr r%u\n", rD_addr);
11755 putIReg( rD_addr, getGST( PPC_GST_LR ) );
11756 break;
11757 case 0x9:
11758 DIP("mfctr r%u\n", rD_addr);
11759 putIReg( rD_addr, getGST( PPC_GST_CTR ) );
11760 break;
11761 case 0x80: // 128
11762 DIP("mfspr r%u (TFHAR)\n", rD_addr);
11763 putIReg( rD_addr, getGST( PPC_GST_TFHAR) );
11764 break;
11765 case 0x81: // 129
11766 DIP("mfspr r%u (TFIAR)\n", rD_addr);
11767 putIReg( rD_addr, getGST( PPC_GST_TFIAR) );
11768 break;
11769 case 0x82: // 130
11770 DIP("mfspr r%u (TEXASR)\n", rD_addr);
11771 putIReg( rD_addr, getGST( PPC_GST_TEXASR) );
11772 break;
11773 case 0x83: // 131
11774 DIP("mfspr r%u (TEXASRU)\n", rD_addr);
11775 putIReg( rD_addr, getGST( PPC_GST_TEXASRU) );
11776 break;
11777 case 0x9F: // 159
11778 DIP("mfspr r%u (PSPB)\n", rD_addr);
11779 putIReg( rD_addr, getGST( PPC_GST_PSPB) );
11780 break;
11781 case 0x380: // 896
11782 DIP("mfspr r%u (PPR)\n", rD_addr);
11783 putIReg( rD_addr, getGST( PPC_GST_PPR) );
11784 break;
11785 case 0x382: // 898
11786 DIP("mfspr r%u (PPR)32\n", rD_addr);
11787 putIReg( rD_addr, getGST( PPC_GST_PPR32) );
11788 break;
11789 case 0x100:
11790 DIP("mfvrsave r%u\n", rD_addr);
11791 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ),
11792 /* Signed */False) );
11793 break;
11795 case 0x103:
11796 DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr);
11797 putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) );
11798 break;
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(
11805 val,
11806 0/*regparms*/,
11807 "ppcg_dirtyhelper_MFTB",
11808 fnptr_to_fnentry(vbi,
11809 &ppcg_dirtyhelper_MFTB),
11810 args );
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)) );
11816 break;
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(
11824 val,
11825 0/*regparms*/,
11826 "ppcg_dirtyhelper_MFTB",
11827 fnptr_to_fnentry(vbi,
11828 &ppcg_dirtyhelper_MFTB),
11829 args );
11830 /* execute the dirty call, dumping the result in val. */
11831 stmt( IRStmt_Dirty(d) );
11832 putIReg( rD_addr,
11833 mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)),
11834 /* Signed */False) );
11835 break;
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(
11843 val,
11844 0/*regparms*/,
11845 "ppcg_dirtyhelper_MFTB",
11846 fnptr_to_fnentry(vbi,
11847 &ppcg_dirtyhelper_MFTB),
11848 args );
11849 /* execute the dirty call, dumping the result in val. */
11850 stmt( IRStmt_Dirty(d) );
11851 putIReg( rD_addr,
11852 mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(val)),
11853 /* Signed */False) );
11854 break;
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(
11863 val,
11864 0/*regparms*/,
11865 "ppc32g_dirtyhelper_MFSPR_287",
11866 fnptr_to_fnentry
11867 (vbi, &ppc32g_dirtyhelper_MFSPR_287),
11868 args
11870 /* execute the dirty call, dumping the result in val. */
11871 stmt( IRStmt_Dirty(d) );
11872 putIReg( rD_addr,
11873 mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
11874 DIP("mfspr r%u,%u", rD_addr, SPR);
11875 break;
11878 default:
11879 vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR);
11880 return False;
11882 break;
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(
11888 val,
11889 0/*regparms*/,
11890 "ppcg_dirtyhelper_MFTB",
11891 fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB),
11892 args );
11893 /* execute the dirty call, dumping the result in val. */
11894 stmt( IRStmt_Dirty(d) );
11896 switch (TBR) {
11897 case 269:
11898 DIP("mftbu r%u", rD_addr);
11899 putIReg( rD_addr,
11900 mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)),
11901 /* Signed */False) );
11902 break;
11903 case 268:
11904 DIP("mftb r%u", rD_addr);
11905 putIReg( rD_addr, (mode64) ? mkexpr(val) :
11906 unop(Iop_64to32, mkexpr(val)) );
11907 break;
11908 case 284:
11909 DIP("mftbl r%u", rD_addr);
11910 putIReg( rD_addr,
11911 mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(val)),
11912 /* Signed */False) );
11913 break;
11914 default:
11915 return False; /* illegal instruction */
11917 break;
11920 case 0x090: {
11921 // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477)
11922 // b20==1: mtocrf (Move to One Cond Reg Field)
11923 Int cr;
11924 UChar shft;
11925 if (b11 != 0)
11926 return False;
11927 if (b20 == 1) {
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. */
11931 switch (CRM) {
11932 case 0x01: case 0x02: case 0x04: case 0x08:
11933 case 0x10: case 0x20: case 0x40: case 0x80:
11934 break;
11935 default:
11936 return False;
11939 DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf",
11940 CRM, rS_addr);
11941 /* Write to each field specified by CRM */
11942 for (cr = 0; cr < 8; cr++) {
11943 if ((CRM & (1 << (7-cr))) == 0)
11944 continue;
11945 shft = 4*(7-cr);
11946 putGST_field( PPC_GST_CR,
11947 binop(Iop_Shr32,
11948 mkNarrowTo32(ty, mkexpr(rS)),
11949 mkU8(shft)), cr );
11951 break;
11954 case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483)
11956 switch (SPR) { // Choose a register...
11957 case 0x1:
11958 DIP("mtxer r%u\n", rS_addr);
11959 putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) );
11960 break;
11961 case 0x3:
11962 DIP("mtspr r%u (DSCR)\n", rS_addr);
11963 putGST( PPC_GST_DSCR, mkexpr(rS) );
11964 break;
11965 case 0x8:
11966 DIP("mtlr r%u\n", rS_addr);
11967 putGST( PPC_GST_LR, mkexpr(rS) );
11968 break;
11969 case 0x9:
11970 DIP("mtctr r%u\n", rS_addr);
11971 putGST( PPC_GST_CTR, mkexpr(rS) );
11972 break;
11973 case 0x100:
11974 DIP("mtvrsave r%u\n", rS_addr);
11975 putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) );
11976 break;
11977 case 0x80: // 128
11978 DIP("mtspr r%u (TFHAR)\n", rS_addr);
11979 putGST( PPC_GST_TFHAR, mkexpr(rS) );
11980 break;
11981 case 0x81: // 129
11982 DIP("mtspr r%u (TFIAR)\n", rS_addr);
11983 putGST( PPC_GST_TFIAR, mkexpr(rS) );
11984 break;
11985 case 0x82: // 130
11986 DIP("mtspr r%u (TEXASR)\n", rS_addr);
11987 putGST( PPC_GST_TEXASR, mkexpr(rS) );
11988 break;
11989 case 0x9F: // 159
11990 DIP("mtspr r%u (PSPB)\n", rS_addr);
11991 putGST( PPC_GST_PSPB, mkexpr(rS) );
11992 break;
11993 case 0x380: // 896
11994 DIP("mtspr r%u (PPR)\n", rS_addr);
11995 putGST( PPC_GST_PPR, mkexpr(rS) );
11996 break;
11997 case 0x382: // 898
11998 DIP("mtspr r%u (PPR32)\n", rS_addr);
11999 putGST( PPC_GST_PPR32, mkexpr(rS) );
12000 break;
12001 default:
12002 vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR);
12003 return False;
12005 break;
12007 case 0x33: // mfvsrd
12009 UChar XS = ifieldRegXS( theInstr );
12010 UChar rA_addr = ifieldRegA(theInstr);
12011 IRExpr * high64;
12012 IRTemp vS = newTemp( Ity_V128 );
12013 DIP("mfvsrd r%u,vsr%d\n", rA_addr, XS);
12015 /* XS = SX || S
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 ) );
12026 break;
12029 case 0x73: // mfvsrwz
12031 UChar XS = ifieldRegXS( theInstr );
12032 UChar rA_addr = ifieldRegA(theInstr);
12033 IRExpr * high64;
12034 IRTemp vS = newTemp( Ity_V128 );
12035 DIP("mfvsrwz r%u,vsr%d\n", rA_addr, XS);
12036 /* XS = SX || S
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 ) ) :
12049 unop( Iop_64to32,
12050 binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) ) );
12051 break;
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);
12060 /* XS = SX || S
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) );
12069 if (mode64)
12070 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( rA ), mkU64( 0 ) ) );
12071 else
12072 putVSReg( XT, binop( Iop_64HLtoV128,
12073 binop( Iop_32HLto64,
12074 mkU32( 0 ),
12075 mkexpr( rA ) ),
12076 mkU64( 0 ) ) );
12077 break;
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);
12086 /* XS = SX || S
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
12093 if (mode64)
12094 assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) );
12095 else
12096 assign( rA, getIReg(rA_addr) );
12098 putVSReg( XT, binop( Iop_64HLtoV128,
12099 unop( Iop_32Sto64, mkexpr( rA ) ),
12100 mkU64( 0 ) ) );
12101 break;
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);
12110 /* XS = SX || S
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
12117 if (mode64)
12118 assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) );
12119 else
12120 assign( rA, getIReg(rA_addr) );
12122 putVSReg( XT, binop( Iop_64HLtoV128,
12123 binop( Iop_32HLto64, mkU32( 0 ), mkexpr ( rA ) ),
12124 mkU64( 0 ) ) );
12125 break;
12128 default:
12129 vex_printf("dis_proc_ctl(ppc)(opc2)\n");
12130 return False;
12132 return True;
12137 Cache Management Instructions
12139 static Bool dis_cache_manage ( UInt prefix, UInt theInstr,
12140 DisResult* dres,
12141 UInt allow_isa_3_1,
12142 const VexArchInfo* guest_archinfo )
12144 /* X-Form */
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. */
12159 PREFIX_CHECK
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)
12166 b21to25 = 0;
12168 if (opc1 == 0x1F && opc2 == 0x116 && b21to25 == 0x11)
12169 b21to25 = 0;
12171 if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz
12172 if (b21to25 == 1) {
12173 is_dcbzl = True;
12174 b21to25 = 0;
12175 if (!(guest_archinfo->ppc_dcbzl_szB)) {
12176 vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n");
12177 return False;
12182 if (opc1 != 0x1F || b0 != 0) {
12183 if (0) vex_printf("dis_cache_manage %d %d\n",
12184 opc1, b0);
12185 vex_printf("dis_cache_manage(ppc)(opc1|b0)\n");
12186 return False;
12189 /* stay sane .. */
12190 vassert(lineszB == 16 || lineszB == 32 || lineszB == 64 || lineszB == 128);
12192 switch (opc2) {
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");
12197 //zz break;
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");
12213 return False;
12215 /* nop as far as vex is concerned */
12216 break;
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 */
12221 break;
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 */
12226 break;
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 */
12231 break;
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);
12238 IRExpr* irx_addr;
12239 UInt i;
12240 UInt clearszB;
12241 if (is_dcbzl) {
12242 clearszB = guest_archinfo->ppc_dcbzl_szB;
12243 DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr);
12245 else {
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) );
12252 if (mode64) {
12253 /* Round EA down to the start of the containing block. */
12254 assign( addr, binop( Iop_And64,
12255 mkexpr(EA),
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) );
12262 } else {
12263 /* Round EA down to the start of the containing block. */
12264 assign( addr, binop( Iop_And32,
12265 mkexpr(EA),
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) );
12273 break;
12276 case 0x3D6: {
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),
12287 mkexpr(EA),
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;
12298 break;
12301 default:
12302 vex_printf("dis_cache_manage(ppc)(opc2)\n");
12303 return False;
12305 return True;
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
12335 to zero | 001 | 11
12336 to +infinity | 010 | 10
12337 to -infinity | 011 | 01
12338 to odd | 1xx | xx
12340 return mkU32(8);
12343 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void )
12346 rounding mode | PPC | IR
12347 ------------------------
12348 to nearest | 00 | 00
12349 to zero | 01 | 11
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,
12358 mkexpr(rm_PPC32),
12359 binop( Iop_And32,
12360 binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)),
12361 mkU32(2) ));
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
12366 * mode designator.
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 ),
12387 binop( Iop_And32,
12388 binop( Iop_Shl32, mkexpr( rm_PPC32 ), mkU8( 1 ) ),
12389 mkU32( 2 ) ) );
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.
12405 * Single Pricision
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
12410 * Double Pricision
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,
12417 binop( Iop_Or32,
12418 mkU32( 0x80000000ULL ), Hi32Mask) ) );
12420 assign( exp_zero,
12421 unop( Iop_1Sto8,
12422 binop( Iop_CmpEQ32,
12423 binop( Iop_And32,
12424 unop( Iop_64HIto32,
12425 unop( Iop_ReinterpF64asI64,
12426 value ) ),
12427 Hi32Mask ),
12428 Hi32Mask ) ) );
12429 assign( frac_not_zero,
12430 binop( Iop_Or8,
12431 unop( Iop_1Sto8,
12432 binop( Iop_CmpNE32,
12433 binop( Iop_And32,
12434 unop( Iop_64HIto32,
12435 unop( Iop_ReinterpF64asI64,
12436 value ) ),
12437 mkexpr( frac_mask ) ),
12438 mkU32( 0x0 ) ) ),
12439 unop( Iop_1Sto8,
12440 binop( Iop_CmpNE32,
12441 binop( Iop_And32,
12442 unop( Iop_64to32,
12443 unop( Iop_ReinterpF64asI64,
12444 value ) ),
12445 mkU32( 0xFFFFFFFF ) ),
12446 mkU32( 0x0 ) ) ) ) );
12447 return unop( Iop_8Sto32,
12448 binop( Iop_And8,
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,
12460 binop( Iop_Or32,
12461 binop( Iop_And32,
12462 nan_mask,
12463 unop( Iop_64HIto32,
12464 unop( Iop_ReinterpF64asI64,
12465 value ) ) ),
12466 binop( Iop_And32,
12467 unop( Iop_Not32,
12468 nan_mask ),
12469 unop( Iop_64HIto32,
12470 unop( Iop_ReinterpF64asI64,
12471 unop( Iop_NegF64,
12472 value ) ) ) ) ),
12473 unop( Iop_64to32,
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 ) );
12504 switch (opc1) {
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 );
12508 putFReg( frT_addr,
12509 unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
12510 break;
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)) );
12516 break;
12518 default:
12519 vex_printf("dis_fp_load_prefix(ppc)(opc1)\n");
12520 return False;
12522 return True;
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. */
12545 PREFIX_CHECK
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
12552 bits affected. */
12554 switch (opc1) {
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) );
12558 putFReg( frD_addr,
12559 unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
12560 break;
12562 case 0x31: // lfsu (Load Float Single, Update, PPC32 p442)
12563 if (rA_addr == 0)
12564 return False;
12565 DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
12566 assign( EA, ea_rA_simm(rA_addr, simm16) );
12567 putFReg( frD_addr,
12568 unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
12569 putIReg( rA_addr, mkexpr(EA) );
12570 break;
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)) );
12576 break;
12578 case 0x33: // lfdu (Load Float Double, Update, PPC32 p438)
12579 if (rA_addr == 0)
12580 return False;
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) );
12585 break;
12587 case 0x1F:
12588 if (b0 != 0) {
12589 vex_printf("dis_fp_load(ppc)(instr,b0)\n");
12590 return False;
12593 switch(opc2) {
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))) );
12599 break;
12601 case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443)
12602 if (rA_addr == 0)
12603 return False;
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) );
12606 putFReg( frD_addr,
12607 unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
12608 putIReg( rA_addr, mkexpr(EA) );
12609 break;
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)) );
12615 break;
12617 case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439)
12618 if (rA_addr == 0)
12619 return False;
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) );
12624 break;
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,
12631 mkU32(0),
12632 binop(Iop_Shr32, mkexpr(iLo), mkU8(31))) );
12633 putFReg( frD_addr, unop(Iop_ReinterpI64asF64,
12634 binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) );
12635 break;
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 ) ) );
12645 break;
12648 default:
12649 vex_printf("dis_fp_load(ppc)(opc2)\n");
12650 return False;
12652 break;
12654 default:
12655 vex_printf("dis_fp_load(ppc)(opc1)\n");
12656 return False;
12658 return True;
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. */
12693 switch (opc1) {
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
12700 rounding. */
12701 store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
12702 break;
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) );
12708 break;
12710 default:
12711 vex_printf("dis_fp_store_prefix(ppc)(opc1)\n");
12712 return False;
12714 return True;
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. */
12736 PREFIX_CHECK
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. */
12747 switch (opc1) {
12748 case 0x35: // stfsu (Store Float Single, Update, PPC32 p519)
12749 if (rA_addr == 0)
12750 return False;
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) );
12756 break;
12758 case 0x37: // stfdu (Store Float Double, Update, PPC32 p514)
12759 if (rA_addr == 0)
12760 return False;
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) );
12765 break;
12767 case 0x1F:
12768 if (b0 != 0) {
12769 vex_printf("dis_fp_store(ppc)(instr,b0)\n");
12770 return False;
12772 switch(opc2) {
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 */
12777 store( mkexpr(EA),
12778 unop(Iop_TruncF64asF32, mkexpr(frS)) );
12779 break;
12781 case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520)
12782 if (rA_addr == 0)
12783 return False;
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) );
12789 break;
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) );
12795 break;
12797 case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515)
12798 if (rA_addr == 0)
12799 return False;
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) );
12804 break;
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) );
12810 store( mkexpr(EA),
12811 unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) );
12812 break;
12814 default:
12815 vex_printf("dis_fp_store(ppc)(opc2)\n");
12816 return False;
12818 break;
12820 default:
12821 vex_printf("dis_fp_store(ppc)(opc1)\n");
12822 return False;
12824 return True;
12830 Floating Point Arith Instructions
12832 static Bool dis_fp_arith ( UInt prefix, UInt theInstr )
12834 /* A-Form */
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. */
12861 PREFIX_CHECK
12863 assign( frA, getFReg(frA_addr));
12864 assign( frB, getFReg(frB_addr));
12865 assign( frC, getFReg(frC_addr));
12867 switch (opc1) {
12868 case 0x3B:
12869 switch (opc2) {
12870 case 0x12: // fdivs (Floating Divide Single, PPC32 p407)
12871 if (frC_addr != 0)
12872 return False;
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) ));
12877 break;
12879 case 0x14: // fsubs (Floating Subtract Single, PPC32 p430)
12880 if (frC_addr != 0)
12881 return False;
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) ));
12886 break;
12888 case 0x15: // fadds (Floating Add Single, PPC32 p401)
12889 if (frC_addr != 0)
12890 return False;
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) ));
12895 break;
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)
12900 return False;
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) ));
12906 break;
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)
12911 return False;
12912 DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"",
12913 frD_addr, frB_addr);
12914 { IRExpr* ieee_one
12915 = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
12916 assign( frD, triop( Iop_DivF64r32,
12918 ieee_one, mkexpr(frB) ));
12920 break;
12922 case 0x19: // fmuls (Floating Multiply Single, PPC32 p414)
12923 if (frB_addr != 0)
12924 return False;
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) ));
12929 break;
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)
12935 return False;
12936 DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"",
12937 frD_addr, frB_addr);
12938 assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) );
12939 break;
12941 default:
12942 vex_printf("dis_fp_arith(ppc)(3B: opc2)\n");
12943 return False;
12945 break;
12947 case 0x3F:
12948 switch (opc2) {
12949 case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406)
12950 if (frC_addr != 0)
12951 return False;
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)) );
12955 break;
12957 case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429)
12958 if (frC_addr != 0)
12959 return False;
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)) );
12963 break;
12965 case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400)
12966 if (frC_addr != 0)
12967 return False;
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)) );
12971 break;
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)
12976 return False;
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)) );
12980 break;
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
12998 assign( frD,
12999 IRExpr_ITE(
13000 binop(Iop_CmpEQ32, mkexpr(cc_b0), mkU32(0)),
13001 mkexpr(frC),
13002 mkexpr(frB) ));
13004 /* One of the rare ones which don't mess with FPRF */
13005 set_FPRF = False;
13006 break;
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)
13014 return False;
13015 DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"",
13016 frD_addr, frB_addr);
13017 { IRExpr* ieee_one
13018 = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
13019 assign( frD, triop( Iop_DivF64,
13021 ieee_one, mkexpr(frB) ));
13023 break;
13025 case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413)
13026 if (frB_addr != 0)
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)) );
13031 break;
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)
13036 return False;
13037 DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"",
13038 frD_addr, frB_addr);
13039 assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) );
13040 break;
13042 default:
13043 vex_printf("dis_fp_arith(ppc)(3F: opc2)\n");
13044 return False;
13046 break;
13048 default:
13049 vex_printf("dis_fp_arith(ppc)(opc1)\n");
13050 return False;
13053 putFReg( frD_addr, mkexpr(frD) );
13055 if (set_FPRF) {
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) );
13065 return True;
13071 Floating Point Mult-Add Instructions
13073 static Bool dis_fp_multadd ( UInt prefix, UInt theInstr )
13075 /* A-Form */
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);
13092 IRExpr* rm;
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. */
13106 PREFIX_CHECK
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() );
13112 rm = mkexpr(rmt);
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
13122 precision.
13124 In the negated cases, the negation happens after rounding. */
13126 switch (opc1) {
13127 case 0x3B:
13128 switch (opc2) {
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) ));
13134 break;
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) ));
13141 break;
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) ) );
13151 } else {
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 ) ) );
13163 break;
13165 default:
13166 vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n");
13167 return False;
13169 break;
13171 case 0x3F:
13172 switch (opc2) {
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) ));
13178 break;
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) ));
13185 break;
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) ) );
13195 } else {
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 ) ) );
13207 break;
13209 default:
13210 vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n");
13211 return False;
13213 break;
13215 default:
13216 vex_printf("dis_fp_multadd(ppc)(opc1)\n");
13217 return False;
13220 putFReg( frD_addr, mkexpr(frD) );
13222 if (set_FPRF) {
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) );
13232 return True;
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;
13257 IRExpr * eb_LTE;
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);
13263 if ( sp )
13264 assign( frB_exp_shR, fp_exp_part( Ity_I32, frB_Int ) );
13265 else
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()
13273 * for details.)
13275 if ( sp ) {
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 ) );
13280 } else {
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,
13292 binop( Iop_Shr32,
13293 sp ? mkexpr( frB_Int ) : unop( Iop_64HIto32, mkexpr( frB_Int ) ),
13294 mkU8( 31 ) ),
13295 mkU32( 1 ) );
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
13302 * being set.
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.
13311 if (sp) {
13312 IRTemp frac_part = newTemp(Ity_I32);
13313 assign( frac_part, binop( Iop_And32, mkexpr(frB_Int), mkU32(0x007fffff)) );
13314 frbDenorm
13315 = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
13316 binop( Iop_CmpNE32, mkexpr( frac_part ), mkU32( 0 ) ) );
13317 } else {
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 ),
13325 mkU32( 0 ) );
13326 frbDenorm
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 ),
13334 mkOR1( frbNaN,
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
13349 * Infinity.
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.
13399 if ( sp ) {
13400 assign( frA_exp_shR, fp_exp_part( Ity_I32, frA_int ) );
13401 assign( frB_exp_shR, fp_exp_part( Ity_I32, frB_int ) );
13402 } else{
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
13417 * a NaN:
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.
13424 if ( sp ) {
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 ) );
13429 } else {
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
13436 * a NaN:
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
13461 if ( sp )
13462 assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( Ity_I32, frA_int ) ) );
13463 else
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,
13479 binop( Iop_Sub32,
13480 mkexpr( e_a ),
13481 mkexpr( e_b ) ),
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,
13492 mkexpr( e_a ),
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
13501 * being set.
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;
13514 if (sp) {
13515 fraction_is_nonzero = binop( Iop_CmpNE32, FP_FRAC_PART32(frB_int),
13516 mkU32( 0 ) );
13517 } else {
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 ),
13525 mkU32( 0 ) );
13527 frbDenorm = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ),
13528 mkU32( 0x0 ) ), fraction_is_nonzero );
13531 ////////////////// fg_flag tests END //////////////////////
13533 fe_flag
13534 = mkOR1(
13535 fraNaN,
13536 mkOR1(
13537 mkexpr( fraInf_tmp ),
13538 mkOR1(
13539 mkexpr( frbZero_tmp ),
13540 mkOR1(
13541 frbNaN,
13542 mkOR1(
13543 mkexpr( frbInf_tmp ),
13544 mkOR1( eb_LTE,
13545 mkOR1( eb_GTE,
13546 mkOR1( ea_eb_GTE,
13547 mkOR1( ea_eb_LTE,
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 ),
13554 frbDenorm ) ) );
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,
13572 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. */
13588 PREFIX_CHECK
13590 if (opc1 != 0x3F || b0 != 0 ){
13591 vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
13592 return False;
13594 assign( frB_I64, unop( Iop_ReinterpF64asI64, getFReg( frB_addr ) ) );
13596 switch (opc2) {
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");
13604 return False;
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);
13611 break;
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");
13621 return False;
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.
13628 assign( flags,
13629 binop( Iop_Or32,
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 );
13634 break;
13637 default:
13638 vex_printf("dis_fp_tests(ppc)(opc2)\n");
13639 return False;
13642 return True;
13646 Floating Point Compare Instructions
13648 static Bool dis_fp_cmp ( UInt prefix, UInt theInstr )
13650 /* X-Form */
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. */
13666 PREFIX_CHECK
13668 if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) {
13669 vex_printf("dis_fp_cmp(ppc)(instr)\n");
13670 return False;
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 --------------------------
13682 UN | 0x1 | 0x45
13683 EQ | 0x2 | 0x40
13684 GT | 0x4 | 0x00
13685 LT | 0x8 | 0x01
13688 // ccPPC32 = Shl(1, (~(ccIR>>5) & 2)
13689 // | ((ccIR ^ (ccIR>>6)) & 1)
13690 assign(
13691 ccPPC32,
13692 binop(
13693 Iop_Shl32,
13694 mkU32(1),
13695 unop(
13696 Iop_32to8,
13697 binop(
13698 Iop_Or32,
13699 binop(
13700 Iop_And32,
13701 unop(
13702 Iop_Not32,
13703 binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))
13705 mkU32(2)
13707 binop(
13708 Iop_And32,
13709 binop(
13710 Iop_Xor32,
13711 mkexpr(ccIR),
13712 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))
13714 mkU32(1)
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. */
13729 switch (opc2) {
13730 case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403)
13731 DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
13732 break;
13733 case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402)
13734 DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
13735 break;
13736 default:
13737 vex_printf("dis_fp_cmp(ppc)(opc2)\n");
13738 return False;
13740 return True;
13746 Floating Point Rounding/Conversion Instructions
13748 static Bool dis_fp_round ( UInt prefix, UInt theInstr )
13750 /* X-Form */
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. */
13776 PREFIX_CHECK
13778 if ((!(opc1 == 0x3F || opc1 == 0x3B)) || b16to20 != 0) {
13779 vex_printf("dis_fp_round(ppc)(instr)\n");
13780 return False;
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.
13789 switch (opc2) {
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 ) ) ) );
13795 goto putFR;
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 ) ) ) );
13801 goto putFR;
13803 return True;
13807 switch (opc2) {
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) ));
13811 break;
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);
13815 assign( r_tmp32,
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. */
13820 set_FPRF = False;
13821 break;
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);
13825 assign( r_tmp32,
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. */
13830 set_FPRF = False;
13831 break;
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);
13836 assign( r_tmp32,
13837 binop( Iop_F64toI32U,
13838 opc2 == 0x08F ? mkU32( Irrm_ZERO ) : rm,
13839 mkexpr( frB ) ) );
13840 assign( frD, unop( Iop_ReinterpI64asF64,
13841 unop( Iop_32Uto64, mkexpr(r_tmp32))));
13842 /* FPRF is undefined after fctiwz. Leave unchanged. */
13843 set_FPRF = False;
13844 break;
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);
13849 assign( r_tmp64,
13850 binop(Iop_F64toI64S, rm, mkexpr(frB)) );
13851 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
13852 /* FPRF is undefined after fctid. Leave unchanged. */
13853 set_FPRF = False;
13854 break;
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);
13858 assign( r_tmp64,
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. */
13862 set_FPRF = False;
13863 break;
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);
13869 assign( r_tmp64,
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. */
13873 set_FPRF = False;
13874 break;
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)) );
13879 assign( frD,
13880 binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) );
13881 break;
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 ) ) );
13887 break;
13889 case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim
13890 switch(opc2) {
13891 case 0x188: // frin (Floating Round to Integer Nearest)
13892 DIP("frin%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
13893 assign( r_tmp64,
13894 binop(Iop_F64toI64S, mkU32(Irrm_NEAREST), mkexpr(frB)) );
13895 break;
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);
13898 assign( r_tmp64,
13899 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
13900 break;
13901 case 0x1C8: // frip (Floating Round to Integer Plus)
13902 DIP("frip%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
13903 assign( r_tmp64,
13904 binop(Iop_F64toI64S, mkU32(Irrm_PosINF), mkexpr(frB)) );
13905 break;
13906 case 0x1E8: // frim (Floating Round to Integer Minus)
13907 DIP("frim%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
13908 assign( r_tmp64,
13909 binop(Iop_F64toI64S, mkU32(Irrm_NegINF), mkexpr(frB)) );
13910 break;
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(
13919 binop(Iop_CmpNE8,
13920 unop(Iop_32to8,
13921 binop(Iop_CmpF64,
13922 IRExpr_Const(IRConst_F64(9e18)),
13923 unop(Iop_AbsF64, mkexpr(frB)))),
13924 mkU8(0)),
13925 mkexpr(frB),
13926 IRExpr_ITE(
13927 binop(Iop_CmpNE32,
13928 binop(Iop_Shr32,
13929 unop(Iop_64HIto32,
13930 unop(Iop_ReinterpF64asI64,
13931 mkexpr(frB))),
13932 mkU8(31)),
13933 mkU32(0)),
13934 unop(Iop_NegF64,
13935 unop( Iop_AbsF64,
13936 binop(Iop_I64StoF64, mkU32(0),
13937 mkexpr(r_tmp64)) )),
13938 binop(Iop_I64StoF64, mkU32(0), mkexpr(r_tmp64) )
13941 break;
13943 default:
13944 vex_printf("dis_fp_round(ppc)(opc2)\n");
13945 return False;
13947 putFR:
13948 putFReg( frD_addr, mkexpr(frD) );
13950 if (set_FPRF) {
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) );
13960 return True;
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 );
13976 UInt R = 0;
13977 ULong immediate_val = 0;
13978 UInt opc2;
13980 switch (opc1) {
13981 case 0x6:
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 ) );
13990 switch (opc2) {
13992 case 0:
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 ) ) );
14002 } else {
14003 putVSReg( XTp+1, load( Ity_V128, mkexpr( EA ) ) );
14004 putVSReg( XTp, load( Ity_V128, mkexpr( EA_16 ) ) );
14006 break;
14009 case 1:
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 ) ) );
14026 } else {
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 ) ) );
14032 break;
14035 default:
14036 vex_printf("dis_fp_pair_prefix\n");
14037 return False;
14039 return True;
14041 break;
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 ) ),
14056 mkU64( 0 ) ) );
14057 return True;
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 );
14071 putVSReg( vRT+32,
14072 binop( Iop_64HLtoV128,
14073 unop( Iop_ReinterpF64asI64,
14074 unop( Iop_F32toF64,
14075 unop( Iop_ReinterpI32asF32,
14076 load( Ity_I32, mkexpr( EA ) )
14077 ) ) ),
14078 mkU64( 0 ) ) );
14079 return True;
14082 case 0x32: // plxv0
14083 case 0x33: // plxv1 These are both plxv, but bit 5 is used for TX
14085 IRExpr* irx_addr;
14086 IRTemp word[2];
14087 UInt ea_off = 8;
14088 UChar vRS = ifieldRegDS(theInstr);
14089 UInt T = IFIELD( theInstr, 21, 5);
14090 UInt TX = IFIELD( theInstr, 26, 1);
14092 assign( EA,
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,
14111 mkexpr( word[0] ),
14112 mkexpr( word[1] ) ) );
14113 else
14114 putVSReg( TX*32+T, binop( Iop_64HLtoV128,
14115 mkexpr( word[1] ),
14116 mkexpr( word[0] ) ) );
14117 return True;
14119 break;
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 ) );
14139 } else {
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 ) );
14146 switch(opc2) {
14147 case 0x2: // lxsd, plxsd (Load VSX Scalar Doubleword)
14149 pDIP( is_prefix, "lxsd v%u,%llu(r%u)\n", vRT, immediate_val,
14150 rA_addr );
14151 DIPp( is_prefix, ",%u", R );
14152 putVSReg( vRT+32, binop( Iop_64HLtoV128,
14153 load( Ity_I64, mkexpr( EA ) ),
14154 mkU64( 0 ) ) );
14155 return True;
14157 break;
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,
14162 rA_addr );
14163 DIPp( is_prefix, ",%u", R );
14165 putVSReg( vRT+32,
14166 binop( Iop_64HLtoV128,
14167 unop( Iop_ReinterpF64asI64,
14168 unop( Iop_F32toF64,
14169 unop( Iop_ReinterpI32asF32,
14170 load( Ity_I32, mkexpr( EA ) )
14171 ) ) ),
14172 mkU64( 0 ) ) );
14173 return True;
14175 default:
14176 vex_printf("dis_fp_pair_prefix(ppc) : DS-form wrong opc2\n");
14177 return False;
14179 break;
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
14195 * matching the HW.
14197 putVSReg( vRS+32, binop( Iop_64HLtoV128,
14198 unop( Iop_V128HIto64,
14199 getVSReg( vRS+32 ) ),
14200 mkU64( 0 ) ) );
14201 return True;
14203 break;
14205 case 0x2F:
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 ) );
14227 return True;
14229 break;
14231 case 0x3d: // lxv
14233 IRExpr* irx_addr;
14234 IRTemp word[2];
14235 UInt ea_off = 8;
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,
14259 mkexpr( word[0] ),
14260 mkexpr( word[1] ) ) );
14261 else
14262 putVSReg( TX*32+T, binop( Iop_64HLtoV128,
14263 mkexpr( word[1] ),
14264 mkexpr( word[0] ) ) );
14265 return True;
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
14278 * matching the HW.
14280 putVSReg( vRS+32, binop( Iop_64HLtoV128,
14281 unop( Iop_V128HIto64,
14282 getVSReg( vRS+32 ) ),
14283 mkU64( 0 ) ) );
14284 return True;
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);
14292 assign( EA,
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 ) );
14304 return True;
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 ) ) );
14316 irx_addr
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 ) ) );
14321 } else {
14322 store( mkexpr(EA), unop( Iop_V128to64,
14323 getVSReg( TX*32+T ) ) );
14324 irx_addr
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 ) ) );
14330 return True;
14332 } else {
14333 vex_printf("dis_fp_pair vector load/store (ppc) : DS-form wrong opc2\n");
14334 return False;
14337 break;
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 ) ) );
14356 } else {
14357 putVSReg( XTp+1, load( Ity_V128, mkexpr( EA ) ) );
14358 putVSReg( XTp, load( Ity_V128, mkexpr( EA_16 ) ) );
14360 return True;
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 ) ) );
14386 } else {
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 ) ) );
14392 return True;
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);
14402 UInt XS = 32*SX+S;
14403 UChar vRS = ifieldRegDS(theInstr);
14404 IRTemp tmpV128 = newTemp(Ity_V128);
14405 IRExpr* irx_addr;
14406 UInt ea_off = 8;
14408 DIP("pstxv v%u,%llu(r%u)", vRS, immediate_val, rA_addr );
14409 DIPp( is_prefix, ",%u", R );
14411 assign( tmpV128, getVSReg( XS ) );
14413 assign( EA,
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 ):
14423 mkU32( ea_off ) );
14424 store( irx_addr, unop( Iop_V128to64,
14425 mkexpr( tmpV128 ) ) );
14427 } else {
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 ):
14432 mkU32( ea_off ) );
14433 store( irx_addr, unop( Iop_V128HIto64,
14434 mkexpr( tmpV128 ) ) );
14436 return True;
14439 default:
14440 vex_printf("dis_fp_pair_prefix(ppc)(instr)\n");
14441 return False;
14443 return False;
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);
14463 Bool is_load = 0;
14465 /* There is no prefixed version of these instructions. */
14466 PREFIX_CHECK
14468 switch (opc1) {
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");
14475 return False;
14478 switch(opc2) {
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);
14481 is_load = 1;
14482 break;
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);
14485 break;
14486 default:
14487 vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n");
14488 return False;
14491 if (b0 != 0) {
14492 vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n");
14493 return False;
14495 assign( EA_hi, ea_rAor0_idxd( rA_addr, rB_addr ) );
14496 break;
14497 case 0x39:
14499 opc2 = ifieldOPC0o2(theInstr);
14501 switch(opc2) {
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");
14508 return False;
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 ) );
14513 is_load = 1;
14514 break;
14516 default:
14517 vex_printf("dis_fp_pair(ppc) : DS-form wrong opc2\n");
14518 return False;
14520 break;
14522 case 0x3d:
14524 opc2 = ifieldOPC0o2(theInstr);
14526 switch(opc2) {
14527 case 0x0:
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");
14534 return False;
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 ) );
14539 break;
14541 default:
14542 vex_printf("dis_fp_pair(ppc) : DS-form wrong opc2\n");
14543 return False;
14545 break;
14547 default: // immediate offset
14548 vex_printf("dis_fp_pair(ppc)(instr)\n");
14549 return False;
14552 if (mode64)
14553 assign( EA_lo, binop(Iop_Add64, mkexpr(EA_hi), mkU64(8)) );
14554 else
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) );
14560 if (is_load) {
14561 putFReg( frT_hi_addr, load(Ity_F64, mkexpr(EA_hi)) );
14562 putFReg( frT_lo_addr, load(Ity_F64, mkexpr(EA_lo)) );
14563 } else {
14564 store( mkexpr(EA_hi), mkexpr(frT_hi) );
14565 store( mkexpr(EA_lo), mkexpr(frT_lo) );
14568 return True;
14573 Floating Point Merge Instructions
14575 static Bool dis_fp_merge ( UInt prefix, UInt theInstr )
14577 /* X-Form */
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. */
14588 PREFIX_CHECK
14590 assign( frA, getFReg(frA_addr));
14591 assign( frB, getFReg(frB_addr));
14593 switch (opc2) {
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,
14601 mkexpr(frA) ) ),
14602 unop( Iop_64HIto32,
14603 unop( Iop_ReinterpF64asI64,
14604 mkexpr(frB) ) ) ) ) );
14605 break;
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,
14612 unop( Iop_64to32,
14613 unop( Iop_ReinterpF64asI64,
14614 mkexpr(frA) ) ),
14615 unop( Iop_64to32,
14616 unop( Iop_ReinterpF64asI64,
14617 mkexpr(frB) ) ) ) ) );
14618 break;
14620 default:
14621 vex_printf("dis_fp_merge(ppc)(opc2)\n");
14622 return False;
14625 putFReg( frD_addr, mkexpr(frD) );
14626 return True;
14630 Floating Point Move Instructions
14632 static Bool dis_fp_move ( UInt prefix, UInt theInstr )
14634 /* X-Form */
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);
14645 IRTemp frA;
14646 IRTemp signA;
14647 IRTemp hiD;
14649 /* There is no prefixed version of these instructions. */
14650 PREFIX_CHECK
14652 if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) {
14653 vex_printf("dis_fp_move(ppc)(instr)\n");
14654 return False;
14657 assign( frB, getFReg(frB_addr));
14659 switch (opc2) {
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,
14662 frB_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,
14672 mkexpr(frA))),
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,
14679 binop(Iop_And32,
14680 unop(Iop_64HIto32,
14681 mkexpr(itmpB)), /* frB's high 32 bits */
14682 mkU32(0x7fffffff)),
14683 mkexpr(signA)) );
14685 /* combine hiD/loB into frD */
14686 assign( frD, unop(Iop_ReinterpI64asF64,
14687 binop(Iop_32HLto64,
14688 mkexpr(hiD),
14689 unop(Iop_64to32,
14690 mkexpr(itmpB)))) ); /* frB's low 32 bits */
14691 break;
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) ));
14696 break;
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) );
14701 break;
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) )));
14706 break;
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) ));
14711 break;
14713 default:
14714 vex_printf("dis_fp_move(ppc)(opc2)\n");
14715 return False;
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. */
14723 if (flag_rC) {
14724 putCR321( 1, mkU8(0) );
14725 putCR0( 1, mkU8(0) );
14728 return True;
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. */
14744 PREFIX_CHECK
14746 if (opc1 != 0x3F) {
14747 vex_printf("dis_fp_scr(ppc)(instr)\n");
14748 return False;
14751 switch (opc2) {
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");
14759 return False;
14761 DIP("mtfsb1%s crb%d \n", flag_rC ? ".":"", crbD);
14762 putGST_masked( PPC_GST_FPSCR, mkU64( 1 <<( 31 - crbD ) ),
14763 1ULL << ( 31 - crbD ) );
14764 break;
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);
14773 IRExpr* fpscr_all;
14774 if (b21to22 != 0 || b11to17 != 0 || flag_rC != 0) {
14775 vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n");
14776 return False;
14778 DIP("mcrfs crf%d,crf%d\n", crfD, crfS);
14779 vassert(crfD < 8);
14780 vassert(crfS < 8);
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))),
14784 mkU32(0xF)) );
14785 putGST_field( PPC_GST_CR, mkexpr(tmp), crfD );
14786 break;
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");
14796 return False;
14798 DIP("mtfsb0%s crb%d\n", flag_rC ? ".":"", crbD);
14799 putGST_masked( PPC_GST_FPSCR, mkU64( 0 ), 1ULL << ( 31 - crbD ) );
14800 break;
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");
14812 return False;
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 );
14817 break;
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
14835 = binop( Iop_Or32,
14836 getGST_masked( PPC_GST_FPSCR, (MASK_FPSCR_RN | MASK_FPSCR_C_FPCC) ),
14837 binop( Iop_Or32,
14838 binop( Iop_Shl32,
14839 getC(),
14840 mkU8(63-47) ) ,
14841 binop( Iop_Shl32,
14842 getFPCC(),
14843 mkU8(63-51) ) ) );
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);
14848 putFReg( 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. */
14856 putFReg( frD_addr,
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. */
14874 putFReg( frD_addr,
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. */
14890 putFReg( frD_addr,
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. */
14912 putFReg( frD_addr,
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. */
14928 putFReg( frD_addr,
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
14943 masking. */
14944 putFReg( frD_addr,
14945 unop( Iop_ReinterpI64asF64,
14946 binop( Iop_32HLto64,
14947 binop( Iop_And32, fpscr_upper,
14948 mkU32( 0x7 ) ),
14949 binop( Iop_And32, fpscr_lower,
14950 mkU32( 0x7F0FF ) ) ) ) );
14951 } else {
14952 vex_printf("dis_fp_scr(ppc)(mff**) Unrecognized instruction.\n");
14953 return False;
14955 break;
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 );
14964 Int i;
14965 ULong mask;
14966 UChar Wbit;
14967 #define BFP_MASK_SEED 0x3000000000000000ULL
14968 #define DFP_MASK_SEED 0x7000000000000000ULL
14970 if (GX_level) {
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) );
14975 } else {
14976 Wbit = 0;
14979 if (b25 == 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;
14989 } else {
14990 DIP("mtfsf%s %d,fr%u\n", flag_rC ? ".":"", FM, frB_addr);
14991 // Build 32bit mask from FM:
14992 mask = 0;
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'.
15003 if (Wbit)
15004 mask |= DFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) );
15005 else
15006 mask |= BFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) );
15008 if ((FM & (1<<(7-i))) == 0x2) { //set the FPCC bits
15009 mask |= 0xF000;
15011 if ((FM & (1<<(7-i))) == 0x4) { //set the Floating-Point Class Descriptor (C) bit
15012 mask |= 0x10000;
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 );
15019 break;
15022 default:
15023 vex_printf("dis_fp_scr(ppc)(opc2)\n");
15024 return False;
15026 return True;
15029 /*------------------------------------------------------------*/
15030 /*--- Decimal Floating Point (DFP) Helper functions ---*/
15031 /*------------------------------------------------------------*/
15032 #define DFP_LONG 1
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.
15075 The FPRF[0:4]:
15076 bits[0:4] =
15077 0b00001 Signaling NaN (DFP only)
15078 0b10001 Quite NaN
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,
15120 mkexpr( lmd ),
15121 mkU32( 0 ) ) );
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,
15126 unop( Iop_1Uto32,
15127 mkAND1 (
15128 mkexpr( lmd_zero_true ),
15129 mkAND1 ( binop( Iop_CmpEQ64,
15130 binop( Iop_And64,
15131 mkU64( DFP_T_FIELD_EXTND_MASK ),
15132 unop( Iop_ReinterpD64asI64,
15133 unop( Iop_D128HItoD64,
15134 src ) ) ),
15135 mkU64( 0 ) ),
15136 binop( Iop_CmpEQ64,
15137 unop( Iop_ReinterpD64asI64,
15138 unop( Iop_D128LOtoD64,
15139 src ) ),
15140 mkU64( 0 ) ) ) ) ) );
15142 assign( sign,
15143 unop( Iop_64to32,
15144 binop( Iop_Shr64,
15145 unop( Iop_ReinterpD64asI64,
15146 unop( Iop_D128HItoD64, src ) ),
15147 mkU8( 63 ) ) ) );
15148 } else {
15149 /* generate_store_DFP_FPRF_value, unknown value for irType */
15150 vassert(0);
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 ),
15163 mkexpr( sign ),
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 ) ) );
15168 return;
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
15187 * lmd
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
15212 * is TRUE.
15214 assign( lmd_07_val,
15215 binop( Iop_Or32, binop( Iop_Shl32, lmexp, mkU8( 3 ) ), lmd32 ) );
15216 assign( lmd_8_val,
15217 binop( Iop_Or32,
15218 binop( Iop_Or32,
15219 binop( Iop_And32,
15220 mkexpr( lmexp_00_mask ),
15221 mkU32( 24 ) ),
15222 binop( Iop_And32,
15223 mkexpr( lmexp_01_mask ),
15224 mkU32( 26 ) ) ),
15225 binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 28 ) ) ) );
15226 assign( lmd_9_val,
15227 binop( Iop_Or32,
15228 binop( Iop_Or32,
15229 binop( Iop_And32,
15230 mkexpr( lmexp_00_mask ),
15231 mkU32( 25 ) ),
15232 binop( Iop_And32,
15233 mkexpr( lmexp_01_mask ),
15234 mkU32( 27 ) ) ),
15235 binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 29 ) ) ) );
15237 /* generate the result from the possible LMD values */
15238 return binop( Iop_Or32,
15239 binop( Iop_Or32,
15240 binop( Iop_And32,
15241 mkexpr( lmd_07_mask ),
15242 mkexpr( lmd_07_val ) ),
15243 binop( Iop_And32,
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:
15267 * lmd
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,
15280 gfield_0_4,
15281 mkU32( BITS5(1,0,1,1,1) ) ) ) );
15282 assign( lmd_8_00_mask,
15283 unop( Iop_1Sto32, binop( Iop_CmpEQ32,
15284 gfield_0_4,
15285 mkU32( BITS5(1,1,0,0,0) ) ) ) );
15286 assign( lmd_8_01_mask,
15287 unop( Iop_1Sto32, binop( Iop_CmpEQ32,
15288 gfield_0_4,
15289 mkU32( BITS5(1,1,0,1,0) ) ) ) );
15290 assign( lmd_8_10_mask,
15291 unop( Iop_1Sto32, binop( Iop_CmpEQ32,
15292 gfield_0_4,
15293 mkU32( BITS5(1,1,1,0,0) ) ) ) );
15294 assign( lmd_9_00_mask,
15295 unop( Iop_1Sto32, binop( Iop_CmpEQ32,
15296 gfield_0_4,
15297 mkU32( BITS5(1,1,0,0,1) ) ) ) );
15298 assign( lmd_9_01_mask,
15299 unop( Iop_1Sto32, binop( Iop_CmpEQ32,
15300 gfield_0_4,
15301 mkU32( BITS5(1,1,0,1,1) ) ) ) );
15302 assign( lmd_9_10_mask,
15303 unop( Iop_1Sto32, binop( Iop_CmpEQ32,
15304 gfield_0_4,
15305 mkU32( BITS5(1,1,1,0,1) ) ) ) );
15307 /* Generate the values for each LMD condition, assuming the condition
15308 * is TRUE.
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 ) );
15314 assign( *lmd,
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 ) )
15322 ) ) );
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 );
15340 assign( valid,
15341 AND4( AND4 ( unop( Iop_1Sto32,
15342 binop( Iop_CmpLE32U,
15343 binop( Iop_And32,
15344 bcd_l,
15345 mkU32 ( 0xF ) ),
15346 mkU32( 0x9 ) ) ),
15347 unop( Iop_1Sto32,
15348 binop( Iop_CmpLE32U,
15349 binop( Iop_And32,
15350 binop( Iop_Shr32,
15351 bcd_l,
15352 mkU8 ( DIGIT1_SHR ) ),
15353 mkU32 ( 0xF ) ),
15354 mkU32( 0x9 ) ) ),
15355 unop( Iop_1Sto32,
15356 binop( Iop_CmpLE32U,
15357 binop( Iop_And32,
15358 binop( Iop_Shr32,
15359 bcd_l,
15360 mkU8 ( DIGIT2_SHR ) ),
15361 mkU32 ( 0xF ) ),
15362 mkU32( 0x9 ) ) ),
15363 unop( Iop_1Sto32,
15364 binop( Iop_CmpLE32U,
15365 binop( Iop_And32,
15366 binop( Iop_Shr32,
15367 bcd_l,
15368 mkU8 ( DIGIT3_SHR ) ),
15369 mkU32 ( 0xF ) ),
15370 mkU32( 0x9 ) ) ) ),
15371 AND4 ( unop( Iop_1Sto32,
15372 binop( Iop_CmpLE32U,
15373 binop( Iop_And32,
15374 binop( Iop_Shr32,
15375 bcd_l,
15376 mkU8 ( DIGIT4_SHR ) ),
15377 mkU32 ( 0xF ) ),
15378 mkU32( 0x9 ) ) ),
15379 unop( Iop_1Sto32,
15380 binop( Iop_CmpLE32U,
15381 binop( Iop_And32,
15382 binop( Iop_Shr32,
15383 bcd_l,
15384 mkU8 ( DIGIT5_SHR ) ),
15385 mkU32 ( 0xF ) ),
15386 mkU32( 0x9 ) ) ),
15387 unop( Iop_1Sto32,
15388 binop( Iop_CmpLE32U,
15389 binop( Iop_And32,
15390 binop( Iop_Shr32,
15391 bcd_l,
15392 mkU8 ( DIGIT6_SHR ) ),
15393 mkU32 ( 0xF ) ),
15394 mkU32( 0x9 ) ) ),
15395 unop( Iop_1Sto32,
15396 binop( Iop_CmpLE32U,
15397 binop( Iop_And32,
15398 binop( Iop_Shr32,
15399 bcd_l,
15400 mkU8 ( DIGIT7_SHR ) ),
15401 mkU32 ( 0xF ) ),
15402 mkU32( 0x9 ) ) ) ),
15403 AND4( unop( Iop_1Sto32,
15404 binop( Iop_CmpLE32U,
15405 binop( Iop_And32,
15406 bcd_u,
15407 mkU32 ( 0xF ) ),
15408 mkU32( 0x9 ) ) ),
15409 unop( Iop_1Sto32,
15410 binop( Iop_CmpLE32U,
15411 binop( Iop_And32,
15412 binop( Iop_Shr32,
15413 bcd_u,
15414 mkU8 ( DIGIT1_SHR ) ),
15415 mkU32 ( 0xF ) ),
15416 mkU32( 0x9 ) ) ),
15417 unop( Iop_1Sto32,
15418 binop( Iop_CmpLE32U,
15419 binop( Iop_And32,
15420 binop( Iop_Shr32,
15421 bcd_u,
15422 mkU8 ( DIGIT2_SHR ) ),
15423 mkU32 ( 0xF ) ),
15424 mkU32( 0x9 ) ) ),
15425 unop( Iop_1Sto32,
15426 binop( Iop_CmpLE32U,
15427 binop( Iop_And32,
15428 binop( Iop_Shr32,
15429 bcd_u,
15430 mkU8 ( DIGIT3_SHR ) ),
15431 mkU32 ( 0xF ) ),
15432 mkU32( 0x9 ) ) ) ),
15433 AND4( unop( Iop_1Sto32,
15434 binop( Iop_CmpLE32U,
15435 binop( Iop_And32,
15436 binop( Iop_Shr32,
15437 bcd_u,
15438 mkU8 ( DIGIT4_SHR ) ),
15439 mkU32 ( 0xF ) ),
15440 mkU32( 0x9 ) ) ),
15441 unop( Iop_1Sto32,
15442 binop( Iop_CmpLE32U,
15443 binop( Iop_And32,
15444 binop( Iop_Shr32,
15445 bcd_u,
15446 mkU8 ( DIGIT5_SHR ) ),
15447 mkU32 ( 0xF ) ),
15448 mkU32( 0x9 ) ) ),
15449 unop( Iop_1Sto32,
15450 binop( Iop_CmpLE32U,
15451 binop( Iop_And32,
15452 binop( Iop_Shr32,
15453 bcd_u,
15454 mkU8 ( DIGIT6_SHR ) ),
15455 mkU32 ( 0xF ) ),
15456 mkU32( 0x9 ) ) ),
15457 unop( Iop_1Sto32,
15458 binop( Iop_CmpLE32U,
15459 binop( Iop_And32,
15460 binop( Iop_Shr32,
15461 bcd_u,
15462 mkU8 ( DIGIT7_SHR ) ),
15463 mkU32 ( 0xF ) ),
15464 mkU32( 0x9 ) ) ) ) ) );
15466 return unop( Iop_Not32, mkexpr( valid ) );
15468 #undef DIGIT1_SHR
15469 #undef DIGIT2_SHR
15470 #undef DIGIT3_SHR
15471 #undef DIGIT4_SHR
15472 #undef DIGIT5_SHR
15473 #undef DIGIT6_SHR
15474 #undef DIGIT7_SHR
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,
15487 binop( Iop_Or32,
15488 unop( Iop_1Sto32,
15489 binop( Iop_CmpEQ32, sign, mkU32( 0xA ) ) ),
15490 unop( Iop_1Sto32,
15491 binop( Iop_CmpEQ32, sign, mkU32( 0xC ) ) ) ),
15492 binop( Iop_Or32,
15493 unop( Iop_1Sto32,
15494 binop( Iop_CmpEQ32, sign, mkU32( 0xE ) ) ),
15495 unop( Iop_1Sto32,
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,
15513 invalid_bcd_mask,
15514 unop( Iop_1Sto32,
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,
15523 IRTemp * low_60_l)
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]) */
15536 assign( low_50,
15537 binop( Iop_32HLto64,
15538 binop( Iop_And32,
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
15544 * BCD string.
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])
15553 assign( mid_50,
15554 binop( Iop_32HLto64,
15555 binop( Iop_Or32,
15556 binop( Iop_Shl32,
15557 binop( Iop_And32,
15558 unop( Iop_64HIto32, frBI64_hi ),
15559 mkU32( 0xF ) ),
15560 mkU8( 14 ) ),
15561 binop( Iop_Shr32,
15562 unop( Iop_64to32, frBI64_hi ),
15563 mkU8( 18 ) ) ),
15564 binop( Iop_Or32,
15565 binop( Iop_Shl32,
15566 unop( Iop_64to32, frBI64_hi ),
15567 mkU8( 14 ) ),
15568 binop( Iop_Shr32,
15569 unop( Iop_64HIto32, frBI64_lo ),
15570 mkU8( 18 ) ) ) ) );
15572 /* Convert the 50 bit densely packed BCD string to a 60 bit
15573 * BCD string.
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]) | */
15580 assign( top_10,
15581 binop( Iop_32HLto64,
15582 mkU32( 0 ),
15583 binop( Iop_And32,
15584 binop( Iop_Shr32,
15585 unop( Iop_64HIto32, frBI64_hi ),
15586 mkU8( 4 ) ),
15587 mkU32( 0x3FF ) ) ) );
15589 /* Convert the 10 bit densely packed BCD string to a 12 bit
15590 * BCD string.
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,
15599 IRExpr * string )
15601 IRTemp cnt[MAX_DIGITS_IN_STRING + 1];IRTemp flag[MAX_DIGITS_IN_STRING+1];
15602 int digits = MAX_DIGITS_IN_STRING;
15603 int i;
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 );
15613 assign( cnt[i],
15614 binop( Iop_Add8,
15615 mkexpr( cnt[i-1] ),
15616 binop(Iop_And8,
15617 unop( Iop_1Uto8,
15618 binop(Iop_CmpEQ32,
15619 binop(Iop_And32,
15620 string,
15621 mkU32( 0xF <<
15622 ( ( digits - i ) * 4) ) ),
15623 mkU32( 0 ) ) ),
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 */
15629 assign( flag[i],
15630 binop(Iop_Or8,
15631 unop( Iop_1Sto8,
15632 binop(Iop_CmpNE32,
15633 binop(Iop_And32,
15634 string,
15635 mkU32( 0xF <<
15636 ( (digits - i) * 4) ) ),
15637 mkU32( 0 ) ) ),
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,
15646 IRExpr * low_32 )
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 ) ) );
15658 Count_zeros( 2,
15659 mkexpr( num_lmd ),
15660 mkexpr( lmd_flag ),
15661 &num_upper,
15662 &upper_flag,
15663 upper_28 );
15665 Count_zeros( 1,
15666 mkexpr( num_upper ),
15667 mkexpr( upper_flag ),
15668 &num_low,
15669 &low_flag,
15670 low_32 );
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 ) ) );
15698 Count_zeros( 6,
15699 mkexpr( num_lmd ),
15700 mkexpr( lmd_flag ),
15701 &num_top,
15702 &top_flag,
15703 top_12_l );
15705 Count_zeros( 2,
15706 mkexpr( num_top ),
15707 mkexpr( top_flag ),
15708 &num_mid_u,
15709 &mid_u_flag,
15710 binop( Iop_Or32,
15711 binop( Iop_Shl32, mid_60_u, mkU8( 2 ) ),
15712 binop( Iop_Shr32, mid_60_l, mkU8( 30 ) ) ) );
15714 Count_zeros( 1,
15715 mkexpr( num_mid_u ),
15716 mkexpr( mid_u_flag ),
15717 &num_mid_l,
15718 &mid_l_flag,
15719 mid_60_l );
15721 Count_zeros( 2,
15722 mkexpr( num_mid_l ),
15723 mkexpr( mid_l_flag ),
15724 &num_low_u,
15725 &low_u_flag,
15726 binop( Iop_Or32,
15727 binop( Iop_Shl32, low_60_u, mkU8( 2 ) ),
15728 binop( Iop_Shr32, low_60_l, mkU8( 30 ) ) ) );
15730 Count_zeros( 1,
15731 mkexpr( num_low_u ),
15732 mkexpr( low_u_flag ),
15733 &num_low_l,
15734 &low_l_flag,
15735 low_60_l );
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,
15746 binop( Iop_And32,
15747 binop( Iop_Shr32, unop( Iop_64HIto32, val ), mkU8( 26 ) ),
15748 mkU32( 0x1F ) ) );
15750 /* Check for unordered, return all 1'x if true */
15751 return binop( Iop_Or32, /* QNaN check */
15752 unop( Iop_1Sto32,
15753 binop( Iop_CmpEQ32,
15754 mkexpr( gfield0to5 ),
15755 mkU32( 0x1E ) ) ),
15756 unop( Iop_1Sto32, /* SNaN check */
15757 binop( Iop_CmpEQ32,
15758 mkexpr( gfield0to5 ),
15759 mkU32( 0x1F ) ) ) );
15762 #undef AND
15763 #undef AND4
15764 #undef OR
15765 #undef OR3
15766 #undef OR4
15767 #undef NOT
15768 #undef SHR
15769 #undef SHL
15770 #undef BITS5
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. */
15799 PREFIX_CHECK
15801 assign( frA, getDReg( frA_addr ) );
15802 assign( frB, getDReg( frB_addr ) );
15804 switch (opc2) {
15805 case 0x2: // dadd
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 ) ) );
15809 break;
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 ) ) );
15814 break;
15815 case 0x22: // dmul
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 ) ) );
15819 break;
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 ) ) );
15824 break;
15827 putDReg( frS_addr, mkexpr( frS ) );
15829 if (flag_rC && clear_CR1) {
15830 putCR321( 1, mkU8( 0 ) );
15831 putCR0( 1, mkU8( 0 ) );
15834 return True;
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. */
15860 PREFIX_CHECK
15862 assign( frA, getDReg_pair( frA_addr ) );
15863 assign( frB, getDReg_pair( frB_addr ) );
15865 switch (opc2) {
15866 case 0x2: // daddq
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 ) ) );
15870 break;
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 ) ) );
15875 break;
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 ) ) );
15880 break;
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 ) ) );
15885 break;
15888 putDReg_pair( frS_addr, mkexpr( frS ) );
15890 if (flag_rC && clear_CR1) {
15891 putCR321( 1, mkU8( 0 ) );
15892 putCR0( 1, mkU8( 0 ) );
15895 return True;
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. */
15911 PREFIX_CHECK
15913 assign( frA, getDReg( frA_addr ) );
15915 switch (opc2) {
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 ) ) );
15920 break;
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 ) ) );
15925 break;
15928 putDReg( frS_addr, mkexpr( frS ) );
15930 if (flag_rC && clear_CR1) {
15931 putCR321( 1, mkU8( 0 ) );
15932 putCR0( 1, mkU8( 0 ) );
15935 return True;
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. */
15951 PREFIX_CHECK
15953 assign( frA, getDReg_pair( frA_addr ) );
15955 switch (opc2) {
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 ) ) );
15960 break;
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 ) ) );
15965 break;
15968 putDReg_pair( frS_addr, mkexpr( frS ) );
15970 if (flag_rC && clear_CR1) {
15971 putCR321( 1, mkU8( 0 ) );
15972 putCR0( 1, mkU8( 0 ) );
15975 return True;
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 );
15985 IRTemp frB;
15986 IRTemp frS;
15987 Bool clear_CR1 = True;
15989 /* There is no prefixed version of these instructions. */
15990 PREFIX_CHECK
15992 switch (opc2) {
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 ) );
16002 break;
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 ) );
16011 break;
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 ) );
16025 break;
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,
16033 round,
16034 unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ) );
16035 putDReg( frS_addr, mkexpr( frS ) );
16036 break;
16039 if (flag_rC && clear_CR1) {
16040 putCR321( 1, mkU8( 0 ) );
16041 putCR0( 1, mkU8( 0 ) );
16044 return True;
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. */
16062 PREFIX_CHECK
16064 switch (opc2) {
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 ) );
16071 break;
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 ) );
16083 break;
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 ) );
16090 break;
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 ) );
16104 break;
16107 case 0x3E2:
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 ) ) );
16135 putVReg( frS_addr,
16136 unop( Iop_ReinterpI128asV128, mkexpr( tmp128 ) ) );
16138 } else {
16139 vex_printf("ERROR: dis_dfp_fmt_convq unknown opc3 = %d value.\n",
16140 opc3);
16141 return False;
16144 break;
16147 if (flag_rC && clear_CR1) {
16148 putCR321( 1, mkU8( 0 ) );
16149 putCR0( 1, mkU8( 0 ) );
16152 return True;
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. */
16167 PREFIX_CHECK
16169 switch (opc2) {
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 ),
16187 mkexpr( frB ) ) );
16188 putDReg( frS_addr, mkexpr( frS ) );
16189 break;
16190 default:
16191 vex_printf("dis_dfp_round(ppc)(opc2)\n");
16192 return False;
16195 if (flag_rC && clear_CR1) {
16196 putCR321( 1, mkU8( 0 ) );
16197 putCR0( 1, mkU8( 0 ) );
16200 return True;
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. */
16215 PREFIX_CHECK
16217 switch (opc2) {
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 ),
16231 mkexpr( frB ) ) );
16232 putDReg_pair( frS_addr, mkexpr( frS ) );
16233 break;
16234 default:
16235 vex_printf("dis_dfp_roundq(ppc)(opc2)\n");
16236 return False;
16239 if (flag_rC && clear_CR1) {
16240 putCR321( 1, mkU8( 0 ) );
16241 putCR0( 1, mkU8( 0 ) );
16244 return True;
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. */
16262 PREFIX_CHECK
16264 assign( frB, getDReg( frB_addr ) );
16266 switch (opc2) {
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.
16280 assign( TE_I64,
16281 unop( Iop_32Uto64,
16282 binop( Iop_Sub32, mkU32( 397 ),
16283 binop( Iop_And32, mkU32( 0xF ),
16284 unop( Iop_Not32, mkU32( TE_value ) )
16285 ) ) ) );
16287 } else {
16288 assign( TE_I64,
16289 unop( Iop_32Uto64,
16290 binop( Iop_Add32, mkU32( 398 ), mkU32( TE_value ) )
16291 ) );
16294 assign( frA, binop( Iop_InsertExpD64, mkexpr( TE_I64 ),
16295 unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) );
16297 assign( frS, triop( Iop_QuantizeD64,
16298 mkU32( RMC ),
16299 mkexpr( frA ),
16300 mkexpr( frB ) ) );
16301 break;
16303 case 0x3: // dqua
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,
16308 mkU32( RMC ),
16309 mkexpr( frA ),
16310 mkexpr( frB ) ) );
16311 break;
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,
16321 unop( Iop_64to32,
16322 unop( Iop_ReinterpD64asI64,
16323 mkexpr( frA ) ) ) ) );
16324 assign( frS, triop( Iop_SignificanceRoundD64,
16325 mkU32( RMC ),
16326 mkexpr( tmp ),
16327 mkexpr( frB ) ) );
16329 break;
16330 default:
16331 vex_printf("dis_dfp_quantize_sig_rrnd(ppc)(opc2)\n");
16332 return False;
16334 putDReg( frS_addr, mkexpr( frS ) );
16336 if (flag_rC && clear_CR1) {
16337 putCR321( 1, mkU8( 0 ) );
16338 putCR0( 1, mkU8( 0 ) );
16341 return True;
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. */
16359 PREFIX_CHECK
16361 assign( frB, getDReg_pair( frB_addr ) );
16363 switch (opc2) {
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
16371 * 6176 to TE.
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.
16377 assign( TE_I64,
16378 unop( Iop_32Uto64,
16379 binop( Iop_Sub32, mkU32( 6175 ),
16380 binop( Iop_And32, mkU32( 0xF ),
16381 unop( Iop_Not32, mkU32( TE_value ) )
16382 ) ) ) );
16384 } else {
16385 assign( TE_I64,
16386 unop( Iop_32Uto64,
16387 binop( Iop_Add32,
16388 mkU32( 6176 ),
16389 mkU32( TE_value ) ) ) );
16392 assign( frA,
16393 binop( Iop_InsertExpD128, mkexpr( TE_I64 ),
16394 unop( Iop_D64toD128,
16395 unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) ) );
16396 assign( frS, triop( Iop_QuantizeD128,
16397 mkU32( RMC ),
16398 mkexpr( frA ),
16399 mkexpr( frB ) ) );
16400 break;
16401 case 0x3: // dquaq
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,
16406 mkU32( RMC ),
16407 mkexpr( frA ),
16408 mkexpr( frB ) ) );
16409 break;
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,
16418 unop( Iop_64to32,
16419 unop( Iop_ReinterpD64asI64,
16420 unop( Iop_D128HItoD64,
16421 mkexpr( frA ) ) ) ) ) );
16422 assign( frS, triop( Iop_SignificanceRoundD128,
16423 mkU32( RMC ),
16424 mkexpr( tmp ),
16425 mkexpr( frB ) ) );
16427 break;
16428 default:
16429 vex_printf("dis_dfp_quantize_sig_rrndq(ppc)(opc2)\n");
16430 return False;
16432 putDReg_pair( frS_addr, mkexpr( frS ) );
16434 if (flag_rC && clear_CR1) {
16435 putCR321( 1, mkU8( 0 ) );
16436 putCR0( 1, mkU8( 0 ) );
16439 return True;
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. */
16456 PREFIX_CHECK
16458 assign( frA, getDReg( frA_addr ) );
16459 assign( frB, getDReg( frB_addr ) );
16461 switch (opc2) {
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 ) ) );
16467 break;
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,
16473 mkexpr( frA ) ),
16474 mkexpr( frB ) ) );
16475 break;
16476 default:
16477 vex_printf("dis_dfp_extract_insert(ppc)(opc2)\n");
16478 return False;
16481 putDReg( frS_addr, mkexpr( frS ) );
16483 if (flag_rC && clear_CR1) {
16484 putCR321( 1, mkU8( 0 ) );
16485 putCR0( 1, mkU8( 0 ) );
16488 return True;
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. */
16506 PREFIX_CHECK
16508 assign( frB, getDReg_pair( frB_addr ) );
16510 switch (opc2) {
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 ) );
16521 break;
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 ) ),
16528 mkexpr( frB ) ) );
16529 putDReg_pair( frS_addr, mkexpr( frS ) );
16530 break;
16531 default:
16532 vex_printf("dis_dfp_extract_insertq(ppc)(opc2)\n");
16533 return False;
16536 if (flag_rC && clear_CR1) {
16537 putCR321( 1, mkU8( 0 ) );
16538 putCR0( 1, mkU8( 0 ) );
16541 return True;
16544 /* DFP 64-bit comparison instructions */
16545 static Bool dis_dfp_compare( UInt prefix, UInt theInstr ) {
16546 /* X-Form */
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 );
16551 IRTemp frA;
16552 IRTemp frB;
16554 IRTemp ccIR = newTemp( Ity_I32 );
16555 IRTemp ccPPC32 = newTemp( Ity_I32 );
16557 /* There is no prefixed version of these instructions. */
16558 PREFIX_CHECK
16560 /* Note: Differences between dcmpu and dcmpo are only in exception
16561 flag settings, which aren't supported anyway. */
16562 switch (opc1) {
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 ) ) );
16572 break;
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 ) ) );
16581 break;
16582 default:
16583 vex_printf("dis_dfp_compare(ppc)(opc2)\n");
16584 return False;
16587 /* Map compare result from IR to PPC32 */
16589 FP cmp result | PPC | IR
16590 --------------------------
16591 UN | 0x1 | 0x45
16592 EQ | 0x2 | 0x40
16593 GT | 0x4 | 0x00
16594 LT | 0x8 | 0x01
16597 assign( ccPPC32,
16598 binop( Iop_Shl32,
16599 mkU32( 1 ),
16600 unop( Iop_32to8,
16601 binop( Iop_Or32,
16602 binop( Iop_And32,
16603 unop( Iop_Not32,
16604 binop( Iop_Shr32,
16605 mkexpr( ccIR ),
16606 mkU8( 5 ) ) ),
16607 mkU32( 2 ) ),
16608 binop( Iop_And32,
16609 binop( Iop_Xor32,
16610 mkexpr( ccIR ),
16611 binop( Iop_Shr32,
16612 mkexpr( ccIR ),
16613 mkU8( 6 ) ) ),
16614 mkU32( 1 ) ) ) ) ) );
16616 putGST_field( PPC_GST_CR, mkexpr( ccPPC32 ), crfD );
16617 putFPCC( mkexpr( ccPPC32 ) );
16618 return True;
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. */
16650 PREFIX_CHECK
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.
16657 switch (opc1) {
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 ) ) ) );
16669 break;
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 ) ) ) );
16684 break;
16685 default:
16686 vex_printf("dis_dfp_exponent_test(ppc)(opc2)\n");
16687 return False;
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,
16705 unop( Iop_1Sto32,
16706 binop( Iop_CmpEQ32,
16707 mkexpr( gfield_A ),
16708 mkU32( 0x7C000000 ) ) ),
16709 unop( Iop_1Sto32,
16710 binop( Iop_CmpEQ32,
16711 mkexpr( gfield_A ),
16712 mkU32( 0x7E000000 ) )
16713 ) ) );
16714 assign( B_NaN_true, binop(Iop_Or32,
16715 unop( Iop_1Sto32,
16716 binop( Iop_CmpEQ32,
16717 mkexpr( gfield_B ),
16718 mkU32( 0x7C000000 ) ) ),
16719 unop( Iop_1Sto32,
16720 binop( Iop_CmpEQ32,
16721 mkexpr( gfield_B ),
16722 mkU32( 0x7E000000 ) )
16723 ) ) );
16725 /* check for infinity */
16726 assign( A_inf_true,
16727 unop( Iop_1Sto32,
16728 binop( Iop_CmpEQ32,
16729 mkexpr( gfield_A ),
16730 mkU32( 0x78000000 ) ) ) );
16732 assign( B_inf_true,
16733 unop( Iop_1Sto32,
16734 binop( Iop_CmpEQ32,
16735 mkexpr( gfield_B ),
16736 mkU32( 0x78000000 ) ) ) );
16738 assign( finite_number,
16739 unop( Iop_Not32,
16740 binop( Iop_Or32,
16741 binop( Iop_Or32,
16742 mkexpr( A_NaN_true ),
16743 mkexpr( B_NaN_true ) ),
16744 binop( Iop_Or32,
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,
16754 binop( Iop_Or32,
16755 unop( Iop_1Uto32,
16756 binop( Iop_CmpEQ32,
16757 mkexpr( exponent_A ),
16758 mkexpr( exponent_B ) ) ),
16759 binop( Iop_Or32,
16760 binop( Iop_And32,
16761 mkexpr( A_inf_true ),
16762 mkexpr( B_inf_true ) ),
16763 binop( Iop_And32,
16764 mkexpr( A_NaN_true ),
16765 mkexpr( B_NaN_true ) ) ) ) );
16767 assign( cc0, binop( Iop_And32,
16768 mkexpr( finite_number ),
16769 binop( Iop_Shl32,
16770 unop( Iop_1Uto32,
16771 binop( Iop_CmpLT32U,
16772 mkexpr( exponent_A ),
16773 mkexpr( exponent_B ) ) ),
16774 mkU8( 3 ) ) ) );
16776 assign( cc1, binop( Iop_And32,
16777 mkexpr( finite_number ),
16778 binop( Iop_Shl32,
16779 unop( Iop_1Uto32,
16780 binop( Iop_CmpLT32U,
16781 mkexpr( exponent_B ),
16782 mkexpr( exponent_A ) ) ),
16783 mkU8( 2 ) ) ) );
16785 assign( cc2, binop( Iop_Shl32,
16786 binop( Iop_And32,
16787 mkexpr( A_equals_B ),
16788 mkU32( 1 ) ),
16789 mkU8( 1 ) ) );
16791 assign( cc3, binop( Iop_And32,
16792 unop( Iop_Not32, mkexpr( A_equals_B ) ),
16793 binop( Iop_And32,
16794 mkU32( 0x1 ),
16795 binop( Iop_Or32,
16796 binop( Iop_Or32,
16797 mkexpr ( A_inf_true ),
16798 mkexpr ( B_inf_true ) ),
16799 binop( Iop_Or32,
16800 mkexpr ( A_NaN_true ),
16801 mkexpr ( B_NaN_true ) ) )
16802 ) ) );
16804 /* store the condition code */
16805 assign( cc, binop( Iop_Or32,
16806 mkexpr( cc0 ),
16807 binop( Iop_Or32,
16808 mkexpr( cc1 ),
16809 binop( Iop_Or32,
16810 mkexpr( cc2 ),
16811 mkexpr( cc3 ) ) ) ) );
16812 putGST_field( PPC_GST_CR, mkexpr( cc ), crfD );
16813 putFPCC( mkexpr( cc ) );
16814 return True;
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 );
16830 UInt max_exp = 0;
16831 UInt min_exp = 0;
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. */
16865 PREFIX_CHECK
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 * --------------------------
16877 * UN | 0x45
16878 * EQ | 0x40
16879 * GT | 0x00
16880 * LT | 0x01
16883 assign( frA, getDReg( frA_addr ) );
16884 assign( frAI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frA ) ) );
16886 assign( abs_frA, unop( Iop_ReinterpI64asD64,
16887 binop( Iop_And64,
16888 unop( Iop_ReinterpD64asI64,
16889 mkexpr( frA ) ),
16890 mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ) );
16891 assign( gfield_0_4_shift, mkU8( 31 - 5 ) ); // G-field[0:4]
16892 switch (opc1) {
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,
16915 binop( Iop_CmpD64,
16916 mkexpr( abs_frA ),
16917 mkexpr( min_subnormalD64 ) ) );
16919 /* compare absolute value of frA with zero */
16920 assign( ccIR_zero,
16921 binop( Iop_CmpD64,
16922 mkexpr( abs_frA ),
16923 unop( Iop_ReinterpI64asD64,
16924 mkU64( 0x2238000000000000ULL ) ) ) );
16926 /* size = DFP_LONG; JRS: unused */
16927 break;
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
16933 * two instructions
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,
16961 binop( Iop_And64,
16962 unop( Iop_ReinterpD64asI64,
16963 mkexpr( frA ) ),
16964 mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ),
16965 getDReg( frA_addr+1 ) ),
16966 mkexpr( min_subnormalD128 ) ) );
16967 assign( ccIR_zero,
16968 binop( Iop_CmpD128,
16969 binop( Iop_D64HLtoD128,
16970 mkexpr( abs_frA ),
16971 getDReg( frA_addr+1 ) ),
16972 unop( Iop_D64toD128,
16973 unop( Iop_ReinterpI64asD64,
16974 mkU64( 0x0ULL ) ) ) ) );
16976 /* size = DFP_EXTND; JRS:unused */
16977 break;
16978 default:
16979 vex_printf("dis_dfp_class_test(ppc)(opc2)\n");
16980 return False;
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
16985 * operations.
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
16994 * instruction.
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,
17003 unop( Iop_1Sto32,
17004 binop( Iop_CmpEQ32,
17005 binop( Iop_And32,
17006 mkU32( 0x7C000000 ),
17007 mkexpr( gfield ) ),
17008 mkU32( 0x78000000 ) ) ) );
17010 assign( SNaN_true,
17011 unop( Iop_1Sto32,
17012 binop( Iop_CmpEQ32,
17013 binop( Iop_And32,
17014 mkU32( 0x7E000000 ),
17015 mkexpr( gfield ) ),
17016 mkU32( 0x7E000000 ) ) ) );
17018 assign( QNaN_true,
17019 binop( Iop_And32,
17020 unop( Iop_1Sto32,
17021 binop( Iop_CmpEQ32,
17022 binop( Iop_And32,
17023 mkU32( 0x7E000000 ),
17024 mkexpr( gfield ) ),
17025 mkU32( 0x7C000000 ) ) ),
17026 unop( Iop_Not32,
17027 mkexpr( SNaN_true ) ) ) );
17029 assign( zero_true,
17030 binop( Iop_And32,
17031 unop(Iop_1Sto32,
17032 binop( Iop_CmpEQ32,
17033 mkexpr( ccIR_zero ),
17034 mkU32( 0x40 ) ) ), // ccIR code for Equal
17035 unop( Iop_Not32,
17036 binop( Iop_Or32,
17037 mkexpr( infinity_true ),
17038 binop( Iop_Or32,
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,
17046 binop( Iop_And32,
17047 binop( Iop_Or32,
17048 unop( Iop_1Sto32,
17049 binop( Iop_CmpEQ32,
17050 mkexpr( ccIR_subnormal ),
17051 mkU32( 0x40 ) ) ), // ccIR code for Equal
17052 unop( Iop_1Sto32,
17053 binop( Iop_CmpEQ32,
17054 mkexpr( ccIR_subnormal ),
17055 mkU32( 0x1 ) ) ) ), // ccIR code for LT
17056 unop( Iop_Not32,
17057 binop( Iop_Or32,
17058 binop( Iop_Or32,
17059 mkexpr( infinity_true ),
17060 mkexpr( zero_true) ),
17061 binop( Iop_Or32,
17062 mkexpr( QNaN_true ),
17063 mkexpr( SNaN_true ) ) ) ) ) );
17065 /* Normal number is not subnormal, infinity, NaN or Zero */
17066 assign( normal_true,
17067 unop( Iop_Not32,
17068 binop( Iop_Or32,
17069 binop( Iop_Or32,
17070 mkexpr( infinity_true ),
17071 mkexpr( zero_true ) ),
17072 binop( Iop_Or32,
17073 mkexpr( subnormal_true ),
17074 binop( Iop_Or32,
17075 mkexpr( QNaN_true ),
17076 mkexpr( SNaN_true ) ) ) ) ) );
17078 /* Calculate the DCM bit field based on the tests for the specific
17079 * instruction
17081 if (opc2 == 0xC2) { // dtstdc, dtstdcq
17082 /* DCM[0:5] Bit Data Class definition
17083 * 0 Zero
17084 * 1 Subnormal
17085 * 2 Normal
17086 * 3 Infinity
17087 * 4 Quiet NaN
17088 * 5 Signaling NaN
17091 assign( dcm0, binop( Iop_Shl32,
17092 mkexpr( zero_true ),
17093 mkU8( 5 ) ) );
17094 assign( dcm1, binop( Iop_Shl32,
17095 binop( Iop_And32,
17096 mkexpr( subnormal_true ),
17097 mkU32( 1 ) ),
17098 mkU8( 4 ) ) );
17099 assign( dcm2, binop( Iop_Shl32,
17100 binop( Iop_And32,
17101 mkexpr( normal_true ),
17102 mkU32( 1 ) ),
17103 mkU8( 3 ) ) );
17104 assign( dcm3, binop( Iop_Shl32,
17105 binop( Iop_And32,
17106 mkexpr( infinity_true),
17107 mkU32( 1 ) ),
17108 mkU8( 2 ) ) );
17109 assign( dcm4, binop( Iop_Shl32,
17110 binop( Iop_And32,
17111 mkexpr( QNaN_true ),
17112 mkU32( 1 ) ),
17113 mkU8( 1 ) ) );
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,
17119 unop( Iop_1Sto32,
17120 binop( Iop_CmpEQ32,
17121 mkexpr( exponent ),
17122 mkU32( max_exp ) ) ),
17123 unop( Iop_1Sto32,
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,
17134 mkexpr( lmd ),
17135 mkU32( 0 ) ) ) );
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,
17148 binop( Iop_And32,
17149 binop( Iop_And32,
17150 unop( Iop_Not32,
17151 mkexpr( extreme_true ) ),
17152 mkexpr( zero_true ) ),
17153 mkU32( 0x1 ) ),
17154 mkU8( 5 ) ) );
17156 assign( dcm1, binop( Iop_Shl32,
17157 binop( Iop_And32,
17158 binop( Iop_And32,
17159 mkexpr( extreme_true ),
17160 mkexpr( zero_true ) ),
17161 mkU32( 0x1 ) ),
17162 mkU8( 4 ) ) );
17164 assign( dcm2, binop( Iop_Shl32,
17165 binop( Iop_And32,
17166 binop( Iop_Or32,
17167 binop( Iop_And32,
17168 mkexpr( extreme_true ),
17169 mkexpr( normal_true ) ),
17170 mkexpr( subnormal_true ) ),
17171 mkU32( 0x1 ) ),
17172 mkU8( 3 ) ) );
17174 assign( dcm3, binop( Iop_Shl32,
17175 binop( Iop_And32,
17176 binop( Iop_And32,
17177 binop( Iop_And32,
17178 unop( Iop_Not32,
17179 mkexpr( extreme_true ) ),
17180 mkexpr( normal_true ) ),
17181 unop( Iop_1Sto32,
17182 binop( Iop_CmpEQ32,
17183 mkexpr( lmd ),
17184 mkU32( 0 ) ) ) ),
17185 mkU32( 0x1 ) ),
17186 mkU8( 2 ) ) );
17188 assign( dcm4, binop( Iop_Shl32,
17189 binop( Iop_And32,
17190 binop( Iop_And32,
17191 binop( Iop_And32,
17192 unop( Iop_Not32,
17193 mkexpr( extreme_true ) ),
17194 mkexpr( normal_true ) ),
17195 unop( Iop_1Sto32,
17196 binop( Iop_CmpNE32,
17197 mkexpr( lmd ),
17198 mkU32( 0 ) ) ) ),
17199 mkU32( 0x1 ) ),
17200 mkU8( 1 ) ) );
17202 assign( dcm5, binop( Iop_And32,
17203 binop( Iop_Or32,
17204 mkexpr( SNaN_true),
17205 binop( Iop_Or32,
17206 mkexpr( QNaN_true),
17207 mkexpr( infinity_true) ) ),
17208 mkU32( 0x1 ) ) );
17211 /* create DCM field */
17212 assign( DCM_calc,
17213 binop( Iop_Or32,
17214 mkexpr( dcm0 ),
17215 binop( Iop_Or32,
17216 mkexpr( dcm1 ),
17217 binop( Iop_Or32,
17218 mkexpr( dcm2 ),
17219 binop( Iop_Or32,
17220 mkexpr( dcm3 ),
17221 binop( Iop_Or32,
17222 mkexpr( dcm4 ),
17223 mkexpr( dcm5 ) ) ) ) ) ) );
17225 /* Get the sign of the DFP number, ignore sign for QNaN */
17226 assign( sign,
17227 unop( Iop_1Uto32,
17228 binop( Iop_CmpEQ32,
17229 binop( Iop_Shr32,
17230 unop( Iop_64HIto32, mkexpr( frAI64_hi ) ),
17231 mkU8( 63 - 32 ) ),
17232 mkU32( 1 ) ) ) );
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)
17237 * field.
17239 * The field layout is as follows:
17241 * Field Meaning
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,
17248 binop( Iop_Shl32,
17249 mkexpr( sign ),
17250 mkU8( 3 ) ),
17251 binop( Iop_Shl32,
17252 unop( Iop_1Uto32,
17253 binop( Iop_CmpNE32,
17254 binop( Iop_And32,
17255 mkU32( DCM ),
17256 mkexpr( DCM_calc ) ),
17257 mkU32( 0 ) ) ),
17258 mkU8( 1 ) ) ) );
17260 putGST_field( PPC_GST_CR, mkexpr( field ), crfD );
17261 putFPCC( mkexpr( field ) );
17262 return True;
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. */
17283 PREFIX_CHECK
17285 assign( frB, getDReg( frB_addr ) );
17286 assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) );
17288 switch ( opc2 ) {
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 */
17298 Get_lmd( &lmd,
17299 binop( Iop_Shr32,
17300 unop( Iop_64HIto32, mkexpr( frBI64 ) ),
17301 mkU8( 31 - 5 ) ) ); // G-field[0:4]
17303 assign( result,
17304 binop( Iop_32HLto64,
17305 binop( Iop_Or32,
17306 binop( Iop_Shl32, mkexpr( lmd ), mkU8( 28 ) ),
17307 mkexpr( bcd_u ) ),
17308 mkexpr( bcd_l ) ) );
17310 } else {
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 );
17317 if (sp == 2) {
17318 /* Positive sign = 0xC, negative sign = 0xD */
17320 assign( sign,
17321 binop( Iop_Or32,
17322 binop( Iop_Shr32,
17323 unop( Iop_64HIto32, mkexpr( frBI64 ) ),
17324 mkU8( 31 ) ),
17325 mkU32( 0xC ) ) );
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 */
17332 assign( tmp32,
17333 binop( Iop_Xor32,
17334 binop( Iop_Shr32,
17335 unop( Iop_64HIto32, mkexpr( frBI64 ) ),
17336 mkU8( 30 ) ),
17337 mkU32( 0x2 ) ) );
17339 assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) );
17341 } else {
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
17346 * bcd_l to bcd_u.
17348 assign( result,
17349 binop( Iop_32HLto64,
17350 binop( Iop_Or32,
17351 binop( Iop_Shr32,
17352 mkexpr( bcd_l ),
17353 mkU8( 28 ) ),
17354 binop( Iop_Shl32,
17355 mkexpr( bcd_u ),
17356 mkU8( 4 ) ) ),
17357 binop( Iop_Or32,
17358 mkexpr( sign ),
17359 binop( Iop_Shl32,
17360 mkexpr( bcd_l ),
17361 mkU8( 4 ) ) ) ) );
17364 putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result ) ) );
17365 break;
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 );
17379 if ( s == 0 ) {
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 ) ) );
17385 assign( lmd,
17386 binop( Iop_Shr32,
17387 binop( Iop_And32,
17388 unop( Iop_64HIto32, mkexpr( frBI64 ) ),
17389 mkU32( 0xF0000000 ) ),
17390 mkU8( 28 ) ) );
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,
17403 mkexpr( dbcd_u ),
17404 mkexpr( dbcd_l ) ) ) ) ) );
17405 assign( left_exp,
17406 binop( Iop_Shr32,
17407 binop( Iop_And32,
17408 unop( Iop_64HIto32, mkexpr( without_lmd ) ),
17409 mkU32( 0x60000000 ) ),
17410 mkU8( 29 ) ) );
17412 assign( g0_4,
17413 binop( Iop_Shl32,
17414 Gfield_encoding( mkexpr( left_exp ), mkexpr( lmd ) ),
17415 mkU8( 26 ) ) );
17417 assign( tmp64,
17418 binop( Iop_32HLto64,
17419 binop( Iop_Or32,
17420 binop( Iop_And32,
17421 unop( Iop_64HIto32,
17422 mkexpr( without_lmd ) ),
17423 mkU32( 0x83FFFFFF ) ),
17424 mkexpr( g0_4 ) ),
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,
17439 binop( Iop_Shr32,
17440 unop( Iop_64HIto32,
17441 mkexpr( frBI64 ) ),
17442 mkU8( 4 ) ),
17443 binop( Iop_Or32,
17444 binop( Iop_Shr32,
17445 unop( Iop_64to32,
17446 mkexpr( frBI64 ) ),
17447 mkU8( 4 ) ),
17448 binop( Iop_Shl32,
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. */
17457 assign( sign,
17458 binop( Iop_And32,
17459 unop( Iop_64to32, mkexpr( frBI64 ) ),
17460 mkU32( 0xF ) ) );
17462 assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) );
17463 assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) );
17464 assign( sign_bit,
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,
17472 Generate_inv_mask(
17473 bcd_digit_inval( unop( Iop_64HIto32,
17474 mkexpr( frBI64 ) ),
17475 binop( Iop_Shr32,
17476 unop( Iop_64to32,
17477 mkexpr( frBI64 ) ),
17478 mkU8( 4 ) ) ),
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. */
17485 assign( tmp64,
17486 unop( Iop_ReinterpD64asI64,
17487 binop( Iop_InsertExpD64,
17488 mkU64( DFP_LONG_BIAS ),
17489 unop( Iop_ReinterpI64asD64,
17490 binop( Iop_32HLto64,
17491 binop( Iop_Or32,
17492 mkexpr( dbcd_u ),
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.
17500 assign( resultD64,
17501 unop( Iop_ReinterpI64asD64,
17502 binop( Iop_32HLto64,
17503 binop( Iop_Or32,
17504 binop( Iop_And32,
17505 mkexpr( valid_mask ),
17506 unop( Iop_64HIto32,
17507 mkexpr( tmp64 ) ) ),
17508 binop( Iop_And32,
17509 mkU32( 0x7C000000 ),
17510 mkexpr( invalid_mask ) ) ),
17511 binop( Iop_Or32,
17512 binop( Iop_And32,
17513 mkexpr( valid_mask ),
17514 unop( Iop_64to32, mkexpr( tmp64 ) ) ),
17515 binop( Iop_And32,
17516 mkU32( 0x0 ),
17517 mkexpr( invalid_mask ) ) ) ) ) );
17518 putDReg( frT_addr, mkexpr( resultD64 ) );
17520 break;
17521 default:
17522 vpanic( "ERROR: dis_dfp_bcd(ppc), undefined opc2 case " );
17523 return False;
17525 return True;
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. */
17545 PREFIX_CHECK
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 ) ) );
17552 switch ( opc2 ) {
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
17564 * the result
17566 Generate_132_bit_bcd_string( mkexpr( frBI64_hi ),
17567 mkexpr( frBI64_lo ),
17568 &top_12_l,
17569 &mid_60_u,
17570 &mid_60_l,
17571 &low_60_u,
17572 &low_60_l );
17574 if ( ( sp == 0 ) || ( sp == 1 ) ) {
17575 /* Unsigned BCD string */
17576 assign( result_hi,
17577 binop( Iop_32HLto64,
17578 binop( Iop_Or32,
17579 binop( Iop_Shl32,
17580 mkexpr( top_12_l ),
17581 mkU8( 24 ) ),
17582 binop( Iop_Shr32,
17583 mkexpr( mid_60_u ),
17584 mkU8( 4 ) ) ),
17585 binop( Iop_Or32,
17586 binop( Iop_Shl32,
17587 mkexpr( mid_60_u ),
17588 mkU8( 28 ) ),
17589 binop( Iop_Shr32,
17590 mkexpr( mid_60_l ),
17591 mkU8( 4 ) ) ) ) );
17593 assign( result_lo,
17594 binop( Iop_32HLto64,
17595 binop( Iop_Or32,
17596 binop( Iop_Shl32,
17597 mkexpr( mid_60_l ),
17598 mkU8( 28 ) ),
17599 mkexpr( low_60_u ) ),
17600 mkexpr( low_60_l ) ) );
17602 } else {
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 );
17609 if ( sp == 2 ) {
17610 /* Positive sign = 0xC, negative sign = 0xD */
17611 assign( sign,
17612 binop( Iop_Or32,
17613 binop( Iop_Shr32,
17614 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
17615 mkU8( 31 ) ),
17616 mkU32( 0xC ) ) );
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.
17624 assign( tmp32,
17625 binop( Iop_Xor32,
17626 binop( Iop_Shr32,
17627 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
17628 mkU8( 30 ) ),
17629 mkU32( 0x2 ) ) );
17631 assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) );
17633 } else {
17634 vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
17637 assign( result_hi,
17638 binop( Iop_32HLto64,
17639 binop( Iop_Or32,
17640 binop( Iop_Shl32,
17641 mkexpr( top_12_l ),
17642 mkU8( 28 ) ),
17643 mkexpr( mid_60_u ) ),
17644 mkexpr( mid_60_l ) ) );
17646 assign( result_lo,
17647 binop( Iop_32HLto64,
17648 binop( Iop_Or32,
17649 binop( Iop_Shl32,
17650 mkexpr( low_60_u ),
17651 mkU8( 4 ) ),
17652 binop( Iop_Shr32,
17653 mkexpr( low_60_l ),
17654 mkU8( 28 ) ) ),
17655 binop( Iop_Or32,
17656 binop( Iop_Shl32,
17657 mkexpr( low_60_l ),
17658 mkU8( 4 ) ),
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 ) ) );
17666 break;
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 );
17691 if ( s == 0 ) {
17692 /* Unsigned BCD string */
17693 assign( sign_bit, mkU32( 0 ) ); // set to zero for unsigned string
17695 assign( bcd_top_8,
17696 binop( Iop_32HLto64,
17697 mkU32( 0 ),
17698 binop( Iop_And32,
17699 binop( Iop_Shr32,
17700 unop( Iop_64HIto32,
17701 mkexpr( frBI64_hi ) ),
17702 mkU8( 24 ) ),
17703 mkU32( 0xFF ) ) ) );
17704 assign( bcd_mid_60,
17705 binop( Iop_32HLto64,
17706 binop( Iop_Or32,
17707 binop( Iop_Shr32,
17708 unop( Iop_64to32,
17709 mkexpr( frBI64_hi ) ),
17710 mkU8( 28 ) ),
17711 binop( Iop_Shl32,
17712 unop( Iop_64HIto32,
17713 mkexpr( frBI64_hi ) ),
17714 mkU8( 4 ) ) ),
17715 binop( Iop_Or32,
17716 binop( Iop_Shl32,
17717 unop( Iop_64to32,
17718 mkexpr( frBI64_hi ) ),
17719 mkU8( 4 ) ),
17720 binop( Iop_Shr32,
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,
17746 binop( Iop_Or32,
17747 bcd_digit_inval( mkU32( 0 ),
17748 unop( Iop_64to32,
17749 mkexpr( bcd_top_8 ) ) ),
17750 binop( Iop_Or32,
17751 bcd_digit_inval( unop( Iop_64HIto32,
17752 mkexpr( bcd_mid_60 ) ),
17753 unop( Iop_64to32,
17754 mkexpr( bcd_mid_60 ) ) ),
17755 bcd_digit_inval( unop( Iop_64HIto32,
17756 mkexpr( bcd_low_60 ) ),
17757 unop( Iop_64to32,
17758 mkexpr( bcd_low_60 ) )
17759 ) ) ) );
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 */
17768 assign( sign,
17769 binop( Iop_And32,
17770 unop( Iop_64to32, mkexpr( frBI64_lo ) ),
17771 mkU32( 0xF ) ) );
17772 assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) );
17773 assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) );
17774 assign( sign_bit,
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 */
17779 assign( bcd_top_8,
17780 binop( Iop_32HLto64,
17781 mkU32( 0x0 ),
17782 binop( Iop_Shr32,
17783 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
17784 mkU8( 28 ) ) ) );
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,
17792 binop( Iop_Shr32,
17793 unop( Iop_64HIto32,
17794 mkexpr( frBI64_lo ) ),
17795 mkU8( 4 ) ),
17796 binop( Iop_Or32,
17797 binop( Iop_Shl32,
17798 unop( Iop_64HIto32,
17799 mkexpr( frBI64_lo ) ),
17800 mkU8( 28 ) ),
17801 binop( Iop_Shr32,
17802 unop( Iop_64to32,
17803 mkexpr( frBI64_lo ) ),
17804 mkU8( 4 ) ) ) ) );
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,
17826 binop( Iop_Or32,
17827 bcd_digit_inval( mkexpr( zero ),
17828 unop( Iop_64to32,
17829 mkexpr( bcd_top_8 ) ) ),
17830 binop( Iop_Or32,
17831 bcd_digit_inval( unop( Iop_64HIto32,
17832 mkexpr( bcd_mid_60 ) ),
17833 unop( Iop_64to32,
17834 mkexpr( bcd_mid_60 ) ) ),
17835 bcd_digit_inval( unop( Iop_64HIto32,
17836 mkexpr( frBI64_lo ) ),
17837 binop( Iop_Shr32,
17838 unop( Iop_64to32,
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
17851 * are all valid.
17853 assign( dfp_significand,
17854 binop( Iop_D64HLtoD128,
17855 unop( Iop_ReinterpI64asD64,
17856 binop( Iop_32HLto64,
17857 binop( Iop_Or32,
17858 mkexpr( sign_bit ),
17859 mkexpr( dbcd_top_l ) ),
17860 binop( Iop_Or32,
17861 binop( Iop_Shl32,
17862 mkexpr( dbcd_mid_u ),
17863 mkU8( 18 ) ),
17864 binop( Iop_Shr32,
17865 mkexpr( dbcd_mid_l ),
17866 mkU8( 14 ) ) ) ) ),
17867 unop( Iop_ReinterpI64asD64,
17868 binop( Iop_32HLto64,
17869 binop( Iop_Or32,
17870 mkexpr( dbcd_low_u ),
17871 binop( Iop_Shl32,
17872 mkexpr( dbcd_mid_l ),
17873 mkU8( 18 ) ) ),
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.
17880 assign( result128,
17881 binop( Iop_InsertExpD128,
17882 mkU64( DFP_EXTND_BIAS ),
17883 mkexpr( dfp_significand ) ) );
17885 assign( tmp_hi,
17886 unop( Iop_ReinterpD64asI64,
17887 unop( Iop_D128HItoD64, mkexpr( result128 ) ) ) );
17889 assign( tmp_lo,
17890 unop( Iop_ReinterpD64asI64,
17891 unop( Iop_D128LOtoD64, mkexpr( result128 ) ) ) );
17893 assign( result_hi,
17894 binop( Iop_32HLto64,
17895 binop( Iop_Or32,
17896 binop( Iop_And32,
17897 mkexpr( valid_mask ),
17898 unop( Iop_64HIto32, mkexpr( tmp_hi ) ) ),
17899 binop( Iop_And32,
17900 mkU32( 0x7C000000 ),
17901 mkexpr( invalid_mask ) ) ),
17902 binop( Iop_Or32,
17903 binop( Iop_And32,
17904 mkexpr( valid_mask ),
17905 unop( Iop_64to32, mkexpr( tmp_hi ) ) ),
17906 binop( Iop_And32,
17907 mkU32( 0x0 ),
17908 mkexpr( invalid_mask ) ) ) ) );
17910 assign( result_lo,
17911 binop( Iop_32HLto64,
17912 binop( Iop_Or32,
17913 binop( Iop_And32,
17914 mkexpr( valid_mask ),
17915 unop( Iop_64HIto32, mkexpr( tmp_lo ) ) ),
17916 binop( Iop_And32,
17917 mkU32( 0x0 ),
17918 mkexpr( invalid_mask ) ) ),
17919 binop( Iop_Or32,
17920 binop( Iop_And32,
17921 mkexpr( valid_mask ),
17922 unop( Iop_64to32, mkexpr( tmp_lo ) ) ),
17923 binop( Iop_And32,
17924 mkU32( 0x0 ),
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 ) ) );
17932 break;
17933 default:
17934 vpanic( "ERROR: dis_dfp_bcdq(ppc), undefined opc2 case " );
17935 break;
17937 return True;
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. */
17963 PREFIX_CHECK
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,
17974 binop( Iop_And32,
17975 unop( Iop_64to32,
17976 unop( Iop_ReinterpD64asI64,
17977 mkexpr( frA ) ) ),
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) );
17985 } else {
17986 vex_printf("dis_dfp_significant_digits(ppc)(opc2) wrong\n");
17987 return False;
17990 switch ( opc1 ) {
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 );
18002 } else {
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
18012 * Long).
18014 Get_lmd( &lmd_B,
18015 binop( Iop_Shr32,
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 ) ) );
18023 assign( B_sig,
18024 binop( Iop_Sub8,
18025 mkU8( DFP_LONG_MAX_SIG_DIGITS ),
18026 Count_leading_zeros_60( mkexpr( lmd_B ),
18027 mkexpr( B_bcd_u ),
18028 mkexpr( B_bcd_l ) ) ) );
18030 assign( BCD_valid,
18031 binop( Iop_Or32,
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
18036 * digit.
18038 assign( Unordered_true,
18039 binop( Iop_Or32,
18040 Check_unordered( mkexpr( frBI64 ) ),
18041 mkexpr( BCD_valid) ) );
18043 break;
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 );
18059 } else {
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
18072 * extended).
18074 Get_lmd( &lmd_B,
18075 binop( Iop_Shr32,
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 ),
18081 &B_top_12_l,
18082 &B_mid_60_u,
18083 &B_mid_60_l,
18084 &B_low_60_u,
18085 &B_low_60_l );
18087 assign( BCD_valid,
18088 binop( Iop_Or32,
18089 binop( Iop_Or32,
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 ) ) ) );
18097 assign( B_sig,
18098 binop( Iop_Sub8,
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
18108 * digit.
18110 assign( Unordered_true,
18111 binop( Iop_Or32,
18112 Check_unordered( mkexpr( frBI64_hi ) ),
18113 mkexpr( BCD_valid) ) );
18115 break;
18118 /* Compare (16 - cnt[0]) against K and set the condition code field
18119 * accordingly.
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,
18130 unop( Iop_1Sto32,
18131 binop( Iop_CmpEQ32,
18132 unop( Iop_8Uto32, mkexpr( K ) ),
18133 unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) );
18134 assign( Lt_true_mask,
18135 unop( Iop_1Sto32,
18136 binop( Iop_CmpLT32U,
18137 unop( Iop_8Uto32, mkexpr( K ) ),
18138 unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) );
18139 assign( Gt_true_mask,
18140 unop( Iop_1Sto32,
18141 binop( Iop_CmpLT32U,
18142 unop( Iop_8Uto32, mkexpr( B_sig ) ),
18143 unop( Iop_8Uto32, mkexpr( K ) ) ) ) );
18145 assign( KisZero_true_mask,
18146 unop( Iop_1Sto32,
18147 binop( Iop_CmpEQ32,
18148 unop( Iop_8Uto32, mkexpr( K ) ),
18149 mkU32( 0 ) ) ) );
18150 assign( KisZero_false_mask,
18151 unop( Iop_1Sto32,
18152 binop( Iop_CmpNE32,
18153 unop( Iop_8Uto32, mkexpr( K ) ),
18154 mkU32( 0 ) ) ) );
18156 assign( field,
18157 binop( Iop_Or32,
18158 binop( Iop_And32,
18159 mkexpr( KisZero_false_mask ),
18160 binop( Iop_Or32,
18161 binop( Iop_And32,
18162 mkexpr( Lt_true_mask ),
18163 mkU32( 0x8 ) ),
18164 binop( Iop_Or32,
18165 binop( Iop_And32,
18166 mkexpr( Gt_true_mask ),
18167 mkU32( 0x4 ) ),
18168 binop( Iop_And32,
18169 mkexpr( Eq_true_mask ),
18170 mkU32( 0x2 ) ) ) ) ),
18171 binop( Iop_And32,
18172 mkexpr( KisZero_true_mask ),
18173 mkU32( 0x4 ) ) ) );
18175 assign( cc, binop( Iop_Or32,
18176 binop( Iop_And32,
18177 mkexpr( Unordered_true ),
18178 mkU32( 0x1 ) ),
18179 binop( Iop_And32,
18180 unop( Iop_Not32, mkexpr( Unordered_true ) ),
18181 mkexpr( field ) ) ) );
18183 putGST_field( PPC_GST_CR, mkexpr( cc ), crfD );
18184 putFPCC( mkexpr( cc ) );
18186 return True;
18188 /*------------------------------------------------------------*/
18189 /*--- AltiVec Instruction Translation ---*/
18190 /*------------------------------------------------------------*/
18193 Altivec Cache Control Instructions (Data Streams)
18195 static Bool dis_av_datastream ( UInt prefix, UInt theInstr )
18197 /* X-Form */
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. */
18209 PREFIX_CHECK
18211 if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) {
18212 vex_printf("dis_av_datastream(ppc)(instr)\n");
18213 return False;
18216 switch (opc2) {
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);
18220 break;
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);
18225 break;
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");
18230 return False;
18232 if (flag_A == 0) {
18233 DIP("dss %d\n", STRM);
18234 } else {
18235 DIP("dssall\n");
18237 break;
18239 default:
18240 vex_printf("dis_av_datastream(ppc)(opc2)\n");
18241 return False;
18243 return True;
18247 AltiVec Processor Control Instructions
18249 static Bool dis_av_procctl ( UInt prefix, UInt theInstr )
18251 /* VX-Form */
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. */
18259 PREFIX_CHECK
18261 if (opc1 != 0x4) {
18262 vex_printf("dis_av_procctl(ppc)(instr)\n");
18263 return False;
18266 switch (opc2) {
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");
18270 return False;
18272 DIP("mfvscr v%d\n", vD_addr);
18273 putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) );
18274 break;
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");
18280 return False;
18282 DIP("mtvscr v%d\n", vB_addr);
18283 assign( vB, getVReg(vB_addr));
18284 putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) );
18285 break;
18287 default:
18288 vex_printf("dis_av_procctl(ppc)(opc2)\n");
18289 return False;
18291 return True;
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
18302 * instruction.
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. */
18315 PREFIX_CHECK
18317 assign( vB, getVReg ( vB_addr ) );
18319 if ( ( opc1 != 0x4 ) && ( opc2 != 0x602 ) ) {
18320 vex_printf("dis_av_extend_sign(ppc)(instr)\n");
18321 return False;
18324 switch ( rA_addr ) {
18325 case 0:
18326 case 1:
18328 UInt i;
18329 IRTemp count[17];
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);
18346 } else {
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,
18369 binop( Iop_And32,
18370 unop( Iop_V128to32,
18371 binop( Iop_ShrV128,
18372 mkexpr( vB ),
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,
18383 binop( Iop_And32,
18384 unop( Iop_V128to32,
18385 binop( Iop_ShrV128,
18386 mkexpr( vB ),
18387 mkU8( i * 8 ) ) ),
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] ),
18394 unop( Iop_1Uto32,
18395 unop( Iop_Not1,
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],
18402 binop( Iop_And32,
18403 unop( Iop_1Uto32,
18404 unop( Iop_Not1,
18405 mkexpr( bit_zero[i] ) ) ),
18406 mkexpr( byte_mask[i] ) ) );
18408 putIReg( rT_addr, unop( Iop_32Uto64, mkexpr( count[16] ) ) );
18409 return True;
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 ) ) );
18417 break;
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,
18424 binop( Iop_Mul64,
18425 unop( Iop_V128HIto64,
18426 mkexpr( vB ) ),
18427 mkU64( 0xFFFFFFFFFFFFFFFF ) ),
18428 binop( Iop_Mul64,
18429 unop( Iop_V128to64,
18430 mkexpr( vB ) ),
18431 mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) );
18432 break;
18434 case 8: // vprtybw, Vector Parity Byte Word
18435 case 9: // vprtybd, Vector Parity Byte Doubleword
18436 case 10: // vprtybq, Vector Parity Byte Quadword
18438 UInt i;
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],
18445 binop( Iop_And32,
18446 unop( Iop_V128to32,
18447 binop( Iop_ShrV128,
18448 mkexpr( vB ),
18449 mkU8( ( 15 - i ) * 8 ) ) ),
18450 mkU32( 0x1 ) ) );
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);
18471 assign( vT,
18472 binop( Iop_64HLtoV128,
18473 binop( Iop_32HLto64,
18474 mkU32( 0 ),
18475 binop( Iop_Xor32,
18476 mkexpr( word_parity[0] ),
18477 mkexpr( word_parity[1] ) ) ),
18478 binop( Iop_32HLto64,
18479 mkU32( 0 ),
18480 binop( Iop_Xor32,
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);
18487 assign( vT,
18488 binop( Iop_64HLtoV128,
18489 mkU64( 0 ),
18490 unop( Iop_32Uto64,
18491 mkXOr4_32( word_parity[0],
18492 word_parity[1],
18493 word_parity[2],
18494 word_parity[3] ) ) ) );
18497 break;
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,
18512 mkexpr( vB ),
18513 binop( Iop_64HLtoV128,
18514 mkU64( 0x0001000100010001 ),
18515 mkU64( 0x0001000100010001 ) ) ) ) );
18516 break;
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 ) ),
18529 mkexpr( vB ) ) );
18531 break;
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 ) ) ) ) );
18553 break;
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 ) ) ) );
18567 break;
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 ) ),
18576 mkexpr( vB ) ) );
18577 break;
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,
18586 unop( Iop_64to1,
18587 binop( Iop_Shr64,
18588 mkexpr( tmp ),
18589 mkU8( 63 ) ) ) ) );
18591 assign( vT, binop( Iop_64HLtoV128, mkexpr( sb ), mkexpr( tmp ) ) );
18593 break;
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");
18603 return False;
18605 assign( vT, unop( Iop_Ctz8x16, mkexpr( vB ) ) );
18607 break;
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");
18616 return False;
18618 assign( vT, unop( Iop_Ctz16x8, mkexpr( vB ) ) );
18620 break;
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");
18629 return False;
18631 assign( vT, unop( Iop_Ctz32x4, mkexpr( vB ) ) );
18633 break;
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");
18642 return False;
18644 assign( vT, unop( Iop_Ctz64x2, mkexpr( vB ) ) );
18646 break;
18648 default:
18649 vex_printf("dis_av_extend_sign(ppc)(Unsupported vector extend sign instruction)\n");
18650 return False;
18653 putVReg( rT_addr, mkexpr( vT ) );
18654 return True;
18658 Vector Rotate Instructions
18660 static Bool dis_av_rotate ( UInt prefix, UInt theInstr )
18662 /* VX-Form */
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 );
18676 IRTemp vA_word[4];
18677 IRTemp left_bits[4];
18678 IRTemp right_bits[4];
18679 IRTemp mb[4];
18680 IRTemp me[4];
18681 IRTemp shift[4];
18682 IRTemp mask[4];
18683 IRTemp tmp_mask[4];
18684 IRTemp invert_mask[4];
18685 IRTemp tmp128[4];
18686 UInt i;
18687 UInt num_words;
18688 UInt word_size;
18689 unsigned long long word_mask;
18691 /* There is no prefixed version of these instructions. */
18692 PREFIX_CHECK
18694 if ( opc1 != 0x4 ) {
18695 vex_printf("dis_av_rotate(ppc)(instr)\n");
18696 return False;
18699 assign( vA, getVReg( vA_addr ) );
18700 assign( vB, getVReg( vB_addr ) );
18702 switch (opc2) {
18703 case 0x85: // vrlwmi, Vector Rotate Left Word then Mask Insert
18704 case 0x185: // vrlwnm, Vector Rotate Left Word then AND with Mask
18705 num_words = 4;
18706 word_size = 32;
18707 assign( field_mask, binop( Iop_64HLtoV128,
18708 mkU64( 0 ),
18709 mkU64( 0x1F ) ) );
18710 word_mask = 0xFFFFFFFF;
18711 break;
18713 case 0x0C5: // vrldmi, Vector Rotate Left Doubleword then Mask Insert
18714 case 0x1C5: // vrldnm, Vector Rotate Left Doubleword then AND with Mask
18715 num_words = 2;
18716 word_size = 64;
18717 assign( field_mask, binop( Iop_64HLtoV128,
18718 mkU64( 0 ),
18719 mkU64( 0x3F ) ) );
18720 word_mask = 0xFFFFFFFFFFFFFFFFULL;
18721 break;
18722 default:
18723 vex_printf("dis_av_rotate(ppc)(opc2)\n");
18724 return False;
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 );
18739 assign( shift[i],
18740 unop( Iop_64to8,
18741 unop( Iop_V128to64,
18742 binop( Iop_AndV128,
18743 binop( Iop_ShrV128,
18744 mkexpr( vB ),
18745 mkU8( (num_words - 1 - i )
18746 * word_size ) ),
18747 mkexpr( field_mask ) ) ) ) );
18749 assign( mb[i], unop( Iop_V128to64,
18750 binop( Iop_AndV128,
18751 binop( Iop_ShrV128,
18752 mkexpr( vB ),
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,
18760 mkexpr( vB ),
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],
18775 unop( Iop_64to8,
18776 binop( Iop_Or64,
18777 binop( Iop_And64, // mb < me
18778 unop( Iop_Not64, mkexpr( invert_mask[i] ) ),
18779 binop( Iop_Add64,
18780 mkU64( 64 - word_size ),
18781 mkexpr( mb[i] ) ) ),
18782 binop( Iop_And64, // me < mb
18783 mkexpr( invert_mask[i] ),
18784 binop( Iop_Add64,
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],
18793 unop( Iop_64to8,
18794 binop( Iop_Or64,
18795 binop( Iop_And64, // mb < me
18796 unop( Iop_Not64, mkexpr( invert_mask[i] ) ),
18797 binop( Iop_Sub64,
18798 mkU64( word_size - 1 ),
18799 mkexpr( me[i] ) ) ),
18800 binop( Iop_And64, // me < mb
18801 mkexpr( invert_mask[i] ),
18802 binop( Iop_Sub64,
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],
18808 binop( Iop_Shl64,
18809 binop( Iop_Shr64,
18810 binop( Iop_Shr64,
18811 binop( Iop_Shl64,
18812 mkU64( 0xFFFFFFFFFFFFFFFF ),
18813 mkexpr( left_bits[i] ) ),
18814 mkexpr( left_bits[i] ) ),
18815 mkexpr( right_bits[i] ) ),
18816 mkexpr( right_bits[i] ) ) );
18818 assign( mask[i],
18819 binop( Iop_64HLtoV128,
18820 mkU64( 0 ),
18821 binop( Iop_Or64,
18822 binop( Iop_And64,
18823 unop( Iop_Not64, mkexpr( invert_mask[i] ) ),
18824 mkexpr( tmp_mask[i] ) ),
18825 binop( Iop_And64,
18826 mkexpr( invert_mask[i] ),
18827 /* Need to make sure mask is only the size
18828 desired word.*/
18829 binop( Iop_And64,
18830 mkU64( word_mask ),
18831 unop( Iop_Not64,
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,
18838 mkexpr( vA ),
18839 binop( Iop_ShlV128,
18840 binop( Iop_64HLtoV128,
18841 mkU64( 0 ),
18842 mkU64( word_mask ) ),
18843 mkU8( ( num_words - 1 - i )
18844 * word_size ) ) ) );
18845 assign( tmp128[i],
18846 binop( Iop_AndV128,
18847 binop( Iop_ShlV128,
18848 mkexpr( mask[i] ),
18849 mkU8( ( num_words - 1 - i) * word_size ) ),
18850 binop( Iop_OrV128,
18851 binop( Iop_ShlV128,
18852 mkexpr( vA_word[i] ),
18853 mkexpr( shift[i] ) ),
18854 binop( Iop_ShrV128,
18855 mkexpr( vA_word[i] ),
18856 unop( Iop_32to8,
18857 binop(Iop_Sub32,
18858 mkU32( word_size ),
18859 unop( Iop_8Uto32,
18860 mkexpr( shift[i] ) ) )
18861 ) ) ) ) );
18864 switch (opc2) {
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,
18871 mkexpr( mask[0] ),
18872 mkU8( 96 ) ),
18873 binop( Iop_ShlV128,
18874 mkexpr( mask[1] ),
18875 mkU8( 64 ) ),
18876 binop( Iop_ShlV128,
18877 mkexpr( mask[2] ),
18878 mkU8( 32 ) ),
18879 mkexpr( mask[3] ) ) ) );
18880 assign( vT, binop( Iop_OrV128,
18881 binop( Iop_AndV128,
18882 mkexpr( src3 ),
18883 mkexpr( mask128 ) ),
18884 mkOr4_V128( tmp128[0], tmp128[1],
18885 tmp128[2], tmp128[3] ) ) );
18886 break;
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,
18893 binop( Iop_OrV128,
18894 binop( Iop_ShlV128,
18895 mkexpr( mask[0] ),
18896 mkU8( 64 ) ),
18897 mkexpr( mask[1] ) ) ) );
18899 assign( vT, binop( Iop_OrV128,
18900 binop( Iop_AndV128,
18901 mkexpr( src3 ),
18902 mkexpr( mask128 ) ),
18903 binop( Iop_OrV128,
18904 mkexpr( tmp128[0] ),
18905 mkexpr( tmp128[1] ) ) ) );
18906 break;
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] ) );
18911 break;
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] ) ) );
18918 break;
18921 putVReg( vT_addr, mkexpr( vT ) );
18922 return True;
18926 AltiVec Vector Extract Element Instructions
18928 static Bool dis_av_insert_element ( UInt prefix, UInt theInstr )
18930 /* VX-Form,
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,
18952 mkU64( 15 ),
18953 mkexpr( rA ) ) );
18955 if ( opc1 != 0x4 ) {
18956 vex_printf("dis_av_insert_element(ppc)(instr)\n");
18957 return False;
18960 switch ( opc2 ) {
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 ),
18972 binop( Iop_And64,
18973 mkU64( 0xF),
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 ) );
18978 putVReg( rVT_addr,
18979 insert_field_into_vector( vTmp, mkexpr( adj_index ),
18980 mkexpr( src), mkU64( 0xFF ) ) );
18982 break;
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 ) );
18997 putVReg( rVT_addr,
18998 insert_field_into_vector( vTmp, mkexpr( rA ),
18999 mkexpr( src), mkU64( 0xFF ) ) );
19001 break;
19003 case 0x04F:
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 ),
19015 binop( Iop_And64,
19016 mkexpr( rA ),
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 ) );
19021 putVReg( rVT_addr,
19022 insert_field_into_vector( vTmp, mkexpr( adj_index ),
19023 mkexpr( src), mkU64( 0xFFFF ) ) );
19025 break;
19027 case 0x14F:
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 ) );
19042 putVReg( rVT_addr,
19043 insert_field_into_vector( vTmp, mkexpr( rA ), mkexpr( src),
19044 mkU64( 0xFFFF ) ) );
19046 break;
19048 case 0x08F:
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 ),
19060 binop( Iop_And64,
19061 mkU64( 0xF ),
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 ) );
19066 putVReg( rVT_addr,
19067 insert_field_into_vector( vTmp, mkexpr( adj_index ),
19068 mkexpr( src), mkU64( 0xFFFFFFFF ) ) );
19070 break;
19072 case 0x18F:
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 ) );
19087 putVReg( rVT_addr,
19088 insert_field_into_vector( vTmp, mkexpr( rA ),
19089 mkexpr( src), mkU64( 0xFFFFFFFF ) ) );
19091 break;
19093 case 0x0CF:
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 ) );
19105 putVReg( rVT_addr,
19106 insert_field_into_vector( vTmp,
19107 mkU64( max_bytes_in_src - 3 - UIM ),
19108 mkexpr( rB), mkU64( 0xFFFFFFFF ) ) );
19110 break;
19112 case 0x1CF:
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 ) );
19124 putVReg( rVT_addr,
19125 insert_field_into_vector( vTmp,
19126 mkU64( max_bytes_in_src - 7 - UIM ),
19127 mkexpr( rB ),
19128 mkU64( 0xFFFFFFFFFFFFFFFFULL ) ) );
19130 break;
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 ) );
19140 putVReg( rVT_addr,
19141 insert_field_into_vector( vTmp,
19142 binop( Iop_Sub64,
19143 mkU64( max_index_in_src ),
19144 mkexpr( rA ) ),
19145 mkexpr( rB ), mkU64( 0xFF ) ) );
19146 break;
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 ) );
19156 putVReg( rVT_addr,
19157 insert_field_into_vector( vTmp, mkexpr( rA ),
19158 mkexpr( rB ), mkU64( 0xFF ) ) );
19159 break;
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 ) );
19170 putVReg( rVT_addr,
19171 insert_field_into_vector( vTmp,
19172 binop( Iop_Sub64,
19173 mkU64( max_index_in_src-1 ),
19174 mkexpr( rA ) ),
19175 mkexpr( rB ), mkU64( 0xFFFF ) ) );
19176 break;
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 ) );
19186 putVReg( rVT_addr,
19187 insert_field_into_vector( vTmp, mkexpr( rA ),
19188 mkexpr( rB ), mkU64( 0xFFFF ) ) );
19189 break;
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 ) );
19200 putVReg( rVT_addr,
19201 insert_field_into_vector( vTmp,
19202 binop( Iop_Sub64,
19203 mkU64( max_index_in_src-3 ),
19204 mkexpr( rA ) ),
19205 mkexpr( rB ), mkU64( 0xFFFFFFFF ) ) );
19206 break;
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 ) );
19216 putVReg( rVT_addr,
19217 insert_field_into_vector( vTmp, mkexpr( rA ),
19218 mkexpr( rB ), mkU64( 0xFFFFFFFF ) ) );
19219 break;
19221 case 0x2CF:
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 ) );
19231 putVReg( rVT_addr,
19232 insert_field_into_vector( vTmp,
19233 binop( Iop_Sub64,
19234 mkU64( max_index_in_src-7 ),
19235 mkexpr( rA ) ),
19236 mkexpr( rB ),
19237 mkU64( 0xFFFFFFFFFFFFFFFFULL ) ) );
19238 break;
19240 case 0x3CF:
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 ) );
19249 putVReg( rVT_addr,
19250 insert_field_into_vector( vTmp, mkexpr( rA ),
19251 mkexpr( rB ),
19252 mkU64( 0xFFFFFFFFFFFFFFFFULL ) ) );
19253 break;
19255 default:
19256 vex_printf("dis_av_extract_element(ppc)(opc2)\n");
19257 return False;
19259 return True;
19263 AltiVec Vector Extract Element Instructions
19265 static Bool dis_av_extract_element ( UInt prefix, UInt theInstr )
19267 /* VX-Form,
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. */
19282 PREFIX_CHECK
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");
19289 return False;
19292 switch ( opc2 ) {
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,
19297 binop( Iop_Sub64,
19298 mkU64( 15 ),
19299 mkexpr( rA ) ),
19300 0xFF ) );
19302 break;
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,
19308 binop( Iop_Sub64,
19309 mkU64( 14 ),
19310 mkexpr( rA ) ),
19311 0xFFFF ) );
19312 break;
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,
19318 binop( Iop_Sub64,
19319 mkU64( 12 ),
19320 mkexpr( rA ) ),
19321 0xFFFFFFFF ) );
19322 break;
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 ) );
19328 break;
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 ) );
19334 break;
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 ) );
19340 break;
19342 default:
19343 vex_printf("dis_av_extract_element(ppc)(opc2)\n");
19344 return False;
19346 putIReg( rT_addr, mkexpr( rT ) );
19347 return True;
19351 * VSX scalar and vector convert instructions
19353 static Bool
19354 dis_vx_conv ( UInt prefix, UInt theInstr, UInt opc2 )
19356 /* XX2-Form */
19357 UChar opc1 = ifieldOPC( theInstr );
19358 UChar XT = ifieldRegXT( theInstr );
19359 UChar XB = ifieldRegXB( theInstr );
19360 IRTemp xB, xB2;
19361 IRTemp b3, b2, b1, b0;
19363 /* There is no prefixed version of these instructions. */
19364 PREFIX_CHECK
19366 xB = xB2 = IRTemp_INVALID;
19368 if (opc1 != 0x3C) {
19369 vex_printf( "dis_vx_conv(ppc)(instr)\n" );
19370 return False;
19373 /* Create and assign temps only as needed for the given instruction. */
19374 switch (opc2) {
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);
19378 assign( xB,
19379 unop( Iop_ReinterpI64asF64,
19380 unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
19381 break;
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);
19387 assign( xB,
19388 unop( Iop_ReinterpI64asF64,
19389 unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
19390 assign( xB2,
19391 unop( Iop_ReinterpI64asF64,
19392 unop( Iop_V128to64, getVSReg( XB ) ) ) );
19393 break;
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);
19399 break;
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 ) ) );
19406 break;
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 ) ) );
19411 break;
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 ) ) ) ) );
19419 break;
19420 case 0x296: // xscvspdpn (non signaling version of xscvpdp)
19421 xB = newTemp(Ity_I32);
19422 assign( xB,
19423 unop( Iop_64HIto32, unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
19424 break;
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
19432 default:
19433 vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
19434 return False;
19438 switch (opc2) {
19439 case 0x2B0:
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);
19443 putVSReg( XT,
19444 binop( Iop_64HLtoV128, binop( Iop_F64toI64S,
19445 mkU32( Irrm_ZERO ),
19446 mkexpr( xB ) ), mkU64( 0 ) ) );
19447 break;
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);
19451 putVSReg( XT,
19452 binop( Iop_64HLtoV128,
19453 unop( Iop_32Sto64,
19454 binop( Iop_F64toI32S,
19455 mkU32( Irrm_ZERO ),
19456 mkexpr( xB ) ) ),
19457 mkU64( 0ULL ) ) );
19458 break;
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);
19462 putVSReg( XT,
19463 binop( Iop_64HLtoV128,
19464 binop( Iop_F64toI64U,
19465 mkU32( Irrm_ZERO ),
19466 mkexpr( xB ) ),
19467 mkU64( 0ULL ) ) );
19468 break;
19469 case 0x270:
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);
19473 putVSReg( XT,
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 ) ) ) ),
19481 mkU64( 0 ) ) );
19482 break;
19483 case 0x2F0:
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);
19487 putVSReg( XT,
19488 binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
19489 binop( Iop_I64StoF64, get_IR_roundingmode(),
19490 mkexpr( xB ) ) ),
19491 mkU64( 0 ) ) );
19492 break;
19493 case 0x250:
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);
19497 putVSReg( XT,
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 ) ) ) ),
19505 mkU64( 0 ) ) );
19506 break;
19507 case 0x2D0:
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);
19511 putVSReg( XT,
19512 binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
19513 binop( Iop_I64UtoF64, get_IR_roundingmode(),
19514 mkexpr( xB ) ) ),
19515 mkU64( 0 ) ) );
19516 break;
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];
19530 IRTemp tmp_64[2];
19532 Int i;
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],
19559 unop( Iop_1Sto32,
19560 unop( Iop_32to1,
19561 binop( Iop_CmpF64,
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],
19576 unop( Iop_1Sto32,
19577 unop( Iop_32to1,
19578 binop( Iop_CmpF64,
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],
19597 unop( Iop_1Sto32,
19598 binop( Iop_CmpEQ32,
19599 mkU32( 0 ),
19600 binop( Iop_CmpF64,
19601 mkexpr( value_f64[i] ),
19602 unop( Iop_ReinterpI64asF64,
19603 mkU64( 0x41DFFFFFFFC00000 ))))));
19605 assign( error_mask[i], binop( Iop_Or32, mkexpr( overflow_mask[i] ),
19606 binop( Iop_Or32,
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],
19613 binop( Iop_Or32,
19614 binop( Iop_And32,
19615 unop( Iop_Not32, mkexpr( nan_mask[i] ) ),
19616 binop( Iop_Or32,
19617 binop( Iop_And32,
19618 mkexpr( overflow_mask[i] ),
19619 mkU32( overflow_value ) ),
19620 binop( Iop_And32,
19621 mkexpr( underflow_mask[i] ),
19622 mkU32( underflow_value ) ) ) ),
19623 binop( Iop_And32,
19624 mkexpr( nan_mask[i] ),
19625 mkU32( 0x80000000 ) ) ) );
19626 } else {
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],
19631 binop( Iop_Or32,
19632 binop( Iop_And32,
19633 unop( Iop_Not32,
19634 mkexpr( underflow_mask[i] ) ),
19635 binop( Iop_Or32,
19636 binop( Iop_And32,
19637 mkexpr( overflow_mask[i] ),
19638 mkU32( overflow_value ) ),
19639 binop( Iop_And32,
19640 mkexpr( nan_mask[i] ),
19641 mkU32( 0x80000000 ) ) ) ),
19642 binop( Iop_And32,
19643 mkexpr( underflow_mask[i] ),
19644 mkU32( underflow_value ) ) ) );
19647 assign( Result_32[i], binop( Iop_Or32,
19648 binop( Iop_And32,
19649 mkexpr( Result_32_tmp[i] ),
19650 unop( Iop_Not32,
19651 mkexpr( error_mask[i] ) ) ),
19652 binop( Iop_And32,
19653 mkexpr( error_value[i] ),
19654 mkexpr( error_mask[i] ) ) ) );
19657 if ( opc2 == 0x1b0 ) {
19658 DIP("xvcvdpsxws v%u,v%u\n", XT, XB);
19660 } else {
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. */
19665 putVSReg( XT,
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] ) ) ) );
19673 break;
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
19705 mkexpr(res3));
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
19710 mkexpr(res2));
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
19715 mkexpr(res1));
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
19720 mkexpr(res0));
19722 putVSReg( XT,
19723 binop( Iop_64HLtoV128,
19724 binop( Iop_32HLto64, b3_result, b2_result ),
19725 binop( Iop_32HLto64, b1_result, b0_result ) ) );
19726 break;
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 ) ) ) ) );
19739 putVSReg( XT,
19740 binop( Iop_64HLtoV128,
19741 binop( Iop_32HLto64,
19742 mkexpr(ResultI32a ),
19743 mkexpr(ResultI32a ) ),
19744 mkU64( 0ULL ) ) );
19745 break;
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 ) ) ) );
19755 putVSReg( XT,
19756 binop( Iop_64HLtoV128,
19757 binop( Iop_32HLto64,
19758 mkexpr(ResultI32b ),
19759 mkexpr(ResultI32b ) ),
19760 mkU64( 0ULL ) ) );
19761 break;
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);
19765 putVSReg( XT,
19766 binop( Iop_64HLtoV128,
19767 binop( Iop_32HLto64,
19768 mkU32( 0 ),
19769 binop( Iop_F64toI32U,
19770 mkU32( Irrm_ZERO ),
19771 mkexpr( xB ) ) ),
19772 mkU64( 0ULL ) ) );
19773 break;
19774 case 0x292: // xscvspdp (VSX Scalar Convert Single-Precision to Double-Precision format, signaling)
19775 DIP("xscvspdp v%u,v%u\n", XT, XB);
19776 putVSReg( XT,
19777 binop( Iop_64HLtoV128,
19778 unop( Iop_ReinterpF64asI64,
19779 unop( Iop_F32toF64,
19780 unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
19781 mkU64( 0ULL ) ) );
19782 break;
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);
19785 putVSReg( XT,
19786 binop( Iop_64HLtoV128,
19787 unop( Iop_ReinterpF64asI64,
19788 unop( Iop_F32toF64,
19789 unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
19790 mkU64( 0ULL ) ) );
19791 break;
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. */
19798 putVSReg( XT,
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 ) ) ) ) ) ) );
19822 break;
19823 case 0x390: // xvcvdpuxds (VSX Vector truncate Double-Precision to integer
19824 // and Convert to Unsigned Integer Doubleword format
19825 // with Saturate)
19826 DIP("xvcvdpuxds v%u,v%u\n", XT, XB);
19827 putVSReg( XT,
19828 binop( Iop_64HLtoV128,
19829 binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
19830 binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
19831 break;
19832 case 0x392: // xvcvspdp (VSX Vector Convert Single-Precision to Double-Precision format)
19833 DIP("xvcvspdp v%u,v%u\n", XT, XB);
19834 putVSReg( XT,
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 ) ) ) ) ) ) );
19844 break;
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);
19848 putVSReg( XT,
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 ) ) ) ) ) );
19858 break;
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);
19862 putVSReg( XT,
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 ) ) ) ) ) );
19872 break;
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);
19876 putVSReg( XT,
19877 binop( Iop_64HLtoV128,
19878 binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
19879 binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
19880 break;
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);
19884 putVSReg( XT,
19885 binop( Iop_64HLtoV128,
19886 unop( Iop_ReinterpF64asI64,
19887 binop( Iop_I64StoF64,
19888 get_IR_roundingmode(),
19889 mkexpr( xB ) ) ),
19890 unop( Iop_ReinterpF64asI64,
19891 binop( Iop_I64StoF64,
19892 get_IR_roundingmode(),
19893 mkexpr( xB2 ) ) ) ) );
19894 break;
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);
19898 putVSReg( XT,
19899 binop( Iop_64HLtoV128,
19900 unop( Iop_ReinterpF64asI64,
19901 binop( Iop_I64UtoF64,
19902 get_IR_roundingmode(),
19903 mkexpr( xB ) ) ),
19904 unop( Iop_ReinterpF64asI64,
19905 binop( Iop_I64UtoF64,
19906 get_IR_roundingmode(),
19907 mkexpr( xB2 ) ) ) ) );
19909 break;
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 ) ) ) ) ) );
19934 putVSReg( XT,
19935 binop( Iop_64HLtoV128,
19936 binop( Iop_32HLto64,
19937 mkexpr( result32hi ),
19938 mkexpr( result32hi ) ),
19939 binop( Iop_32HLto64,
19940 mkexpr( result32lo ),
19941 mkexpr( result32lo ) ) ) );
19943 break;
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 ) ) ) ) ) );
19967 putVSReg( XT,
19968 binop( Iop_64HLtoV128,
19969 binop( Iop_32HLto64,
19970 mkexpr( result32hi ),
19971 mkexpr( result32hi ) ),
19972 binop( Iop_32HLto64,
19973 mkexpr( result32lo ),
19974 mkexpr( result32lo ) ) ) );
19976 break;
19978 case 0x1f0: // xvcvsxwdp (VSX Vector Convert Signed Integer Word to Double-Precision format)
19979 DIP("xvcvsxwdp v%u,v%u\n", XT, XB);
19980 putVSReg( XT,
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 ) ) ) ) ) );
19988 break;
19989 case 0x1d0: // xvcvuxwdp (VSX Vector Convert Unsigned Integer Word to Double-Precision format)
19990 DIP("xvcvuxwdp v%u,v%u\n", XT, XB);
19991 putVSReg( XT,
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 ) ) ) ) ) );
19999 break;
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 ) ) );
20003 break;
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 ) ) );
20007 break;
20009 default:
20010 vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
20011 return False;
20013 return True;
20017 * VSX vector Double Precision Floating Point Arithmetic Instructions
20019 static Bool
20020 dis_vxv_dp_arith ( UInt prefix, UInt theInstr, UInt opc2 )
20022 /* XX3-Form */
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. */
20034 PREFIX_CHECK
20036 if (opc1 != 0x3C) {
20037 vex_printf( "dis_vxv_dp_arith(ppc)(instr)\n" );
20038 return False;
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 ))));
20046 switch (opc2) {
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)
20052 IROp mOp;
20053 const HChar * oper_name;
20054 switch (opc2) {
20055 case 0x1E0:
20056 mOp = Iop_DivF64;
20057 oper_name = "div";
20058 break;
20059 case 0x1C0:
20060 mOp = Iop_MulF64;
20061 oper_name = "mul";
20062 break;
20063 case 0x180:
20064 mOp = Iop_AddF64;
20065 oper_name = "add";
20066 break;
20067 case 0x1A0:
20068 mOp = Iop_SubF64;
20069 oper_name = "sub";
20070 break;
20072 default:
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);
20079 assign( hiResult,
20080 unop( Iop_ReinterpF64asI64,
20081 triop( mOp, rm, mkexpr( frA ), mkexpr( frB ) ) ) );
20082 assign( loResult,
20083 unop( Iop_ReinterpF64asI64,
20084 triop( mOp, rm, mkexpr( frA2 ), mkexpr( frB2 ) ) ) );
20085 putVSReg( XT,
20086 binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
20087 break;
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);
20095 assign( hiResult,
20096 unop( Iop_ReinterpF64asI64,
20097 binop( Iop_SqrtF64, rm, mkexpr( frB ) ) ) );
20098 assign( loResult,
20099 unop( Iop_ReinterpF64asI64,
20100 binop( Iop_SqrtF64, rm, mkexpr( frB2 ) ) ) );
20101 putVSReg( XT,
20102 binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
20103 break;
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 . . .
20111 * XT == FRC
20112 * XA == FRA
20113 * XB == FRB
20115 * and for xvm{add|sub}adp . . .
20116 * XT == FRB
20117 * XA == FRA
20118 * XB == FRC
20120 Bool negate;
20121 IROp mOp = Iop_INVALID;
20122 const HChar * oper_name = NULL;
20123 Bool mdp = False;
20125 switch (opc2) {
20126 case 0x184: case 0x1A4:
20127 case 0x384: case 0x3A4:
20128 mOp = Iop_MAddF64;
20129 oper_name = "add";
20130 mdp = (opc2 & 0x0FF) == 0x0A4;
20131 break;
20133 case 0x1C4: case 0x1E4:
20134 case 0x3C4: case 0x3E4:
20135 mOp = Iop_MSubF64;
20136 oper_name = "sub";
20137 mdp = (opc2 & 0x0FF) == 0x0E4;
20138 break;
20140 default:
20141 vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
20144 switch (opc2) {
20145 case 0x384: case 0x3A4:
20146 case 0x3C4: case 0x3E4:
20147 negate = True;
20148 break;
20149 default:
20150 negate = False;
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",
20157 XT, XA, XB);
20158 assign(frT, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XT ) ) ) );
20159 assign(frT2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XT ) ) ) );
20161 assign( hiResult,
20162 unop( Iop_ReinterpF64asI64,
20163 qop( mOp,
20165 mkexpr( frA ),
20166 mkexpr( mdp ? frT : frB ),
20167 mkexpr( mdp ? frB : frT ) ) ) );
20168 assign( loResult,
20169 unop( Iop_ReinterpF64asI64,
20170 qop( mOp,
20172 mkexpr( frA2 ),
20173 mkexpr( mdp ? frT2 : frB2 ),
20174 mkexpr( mdp ? frB2 : frT2 ) ) ) );
20175 putVSReg( XT,
20176 binop( Iop_64HLtoV128,
20177 mkexpr( negate ? getNegatedResult( hiResult )
20178 : hiResult ),
20179 mkexpr( negate ? getNegatedResult( loResult )
20180 : loResult ) ) );
20181 break;
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.
20201 assign( flagsHi,
20202 binop( Iop_Or32,
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 ) ) ) );
20206 assign( flagsLo,
20207 binop( Iop_Or32,
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 ) ),
20213 crfD );
20214 break;
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.
20239 assign( flagsHi,
20240 binop( Iop_Or32,
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 ) ) ) );
20244 assign( flagsLo,
20245 binop( Iop_Or32,
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 ) ),
20251 crfD );
20252 break;
20255 default:
20256 vex_printf( "dis_vxv_dp_arith(ppc)(opc2)\n" );
20257 return False;
20259 return True;
20263 * VSX vector Single Precision Floating Point Arithmetic Instructions
20265 static Bool
20266 dis_vxv_sp_arith ( UInt prefix, UInt theInstr, UInt opc2 )
20268 /* XX3-Form */
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. */
20282 PREFIX_CHECK
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" );
20289 return False;
20292 switch (opc2) {
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 )) );
20298 break;
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 )) );
20305 break;
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 )) );
20312 break;
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 );
20328 assign( res0,
20329 unop( Iop_ReinterpF32asI32,
20330 unop( Iop_TruncF64asF32,
20331 triop( Iop_DivF64r32, rm, mkexpr( a0 ), mkexpr( b0 ) ) ) ) );
20332 assign( res1,
20333 unop( Iop_ReinterpF32asI32,
20334 unop( Iop_TruncF64asF32,
20335 triop( Iop_DivF64r32, rm, mkexpr( a1 ), mkexpr( b1 ) ) ) ) );
20336 assign( res2,
20337 unop( Iop_ReinterpF32asI32,
20338 unop( Iop_TruncF64asF32,
20339 triop( Iop_DivF64r32, rm, mkexpr( a2 ), mkexpr( b2 ) ) ) ) );
20340 assign( res3,
20341 unop( Iop_ReinterpF32asI32,
20342 unop( Iop_TruncF64asF32,
20343 triop( Iop_DivF64r32, rm, mkexpr( a3 ), mkexpr( b3 ) ) ) ) );
20345 putVSReg( XT,
20346 binop( Iop_64HLtoV128,
20347 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
20348 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
20349 break;
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.
20361 assign( res0,
20362 unop( Iop_ReinterpF32asI32,
20363 unop( Iop_TruncF64asF32,
20364 binop(Iop_SqrtF64, rm, mkexpr( b0 ) ) ) ) );
20365 assign( res1,
20366 unop( Iop_ReinterpF32asI32,
20367 unop( Iop_TruncF64asF32,
20368 binop(Iop_SqrtF64, rm, mkexpr( b1 ) ) ) ) );
20369 assign( res2,
20370 unop( Iop_ReinterpF32asI32,
20371 unop( Iop_TruncF64asF32,
20372 binop(Iop_SqrtF64, rm, mkexpr( b2) ) ) ) );
20373 assign( res3,
20374 unop( Iop_ReinterpF32asI32,
20375 unop( Iop_TruncF64asF32,
20376 binop(Iop_SqrtF64, rm, mkexpr( b3 ) ) ) ) );
20378 putVSReg( XT,
20379 binop( Iop_64HLtoV128,
20380 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
20381 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
20382 break;
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;
20391 Bool msp = False;
20392 Bool negate;
20393 const HChar * oper_name = NULL;
20394 IROp mOp = Iop_INVALID;
20395 switch (opc2) {
20396 case 0x104: case 0x124:
20397 case 0x304: case 0x324:
20398 msp = (opc2 & 0x0FF) == 0x024;
20399 mOp = Iop_MAddF64r32;
20400 oper_name = "madd";
20401 break;
20403 case 0x144: case 0x164:
20404 case 0x344: case 0x364:
20405 msp = (opc2 & 0x0FF) == 0x064;
20406 mOp = Iop_MSubF64r32;
20407 oper_name = "sub";
20408 break;
20410 default:
20411 vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
20414 switch (opc2) {
20415 case 0x304: case 0x324:
20416 case 0x344: case 0x364:
20417 negate = True;
20418 break;
20420 default:
20421 negate = False;
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 );
20432 assign( res0,
20433 unop( Iop_ReinterpF32asI32,
20434 unop( Iop_TruncF64asF32,
20435 qop( mOp,
20437 mkexpr( a0 ),
20438 mkexpr( msp ? t0 : b0 ),
20439 mkexpr( msp ? b0 : t0 ) ) ) ) );
20440 assign( res1,
20441 unop( Iop_ReinterpF32asI32,
20442 unop( Iop_TruncF64asF32,
20443 qop( mOp,
20445 mkexpr( a1 ),
20446 mkexpr( msp ? t1 : b1 ),
20447 mkexpr( msp ? b1 : t1 ) ) ) ) );
20448 assign( res2,
20449 unop( Iop_ReinterpF32asI32,
20450 unop( Iop_TruncF64asF32,
20451 qop( mOp,
20453 mkexpr( a2 ),
20454 mkexpr( msp ? t2 : b2 ),
20455 mkexpr( msp ? b2 : t2 ) ) ) ) );
20456 assign( res3,
20457 unop( Iop_ReinterpF32asI32,
20458 unop( Iop_TruncF64asF32,
20459 qop( mOp,
20461 mkexpr( a3 ),
20462 mkexpr( msp ? t3 : b3 ),
20463 mkexpr( msp ? b3 : t3 ) ) ) ) );
20465 putVSReg( XT,
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 ) ) ) );
20472 break;
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.
20496 assign( flags0,
20497 binop( Iop_Or32,
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 ) ) ) );
20501 assign( flags1,
20502 binop( Iop_Or32,
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 ) ) ) );
20506 assign( flags2,
20507 binop( Iop_Or32,
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 ) ) ) );
20511 assign( flags3,
20512 binop( Iop_Or32,
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,
20517 binop( Iop_Or32,
20518 mkexpr( flags0 ),
20519 binop( Iop_Or32,
20520 mkexpr( flags1 ),
20521 binop( Iop_Or32,
20522 mkexpr( flags2 ),
20523 mkexpr( flags3 ) ) ) ),
20524 crfD );
20525 break;
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.
20551 assign( flags0,
20552 binop( Iop_Or32,
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 ) ) ) );
20556 assign( flags1,
20557 binop( Iop_Or32,
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 ) ) ) );
20561 assign( flags2,
20562 binop( Iop_Or32,
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 ) ) ) );
20566 assign( flags3,
20567 binop( Iop_Or32,
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,
20572 binop( Iop_Or32,
20573 mkexpr( flags0 ),
20574 binop( Iop_Or32,
20575 mkexpr( flags1 ),
20576 binop( Iop_Or32,
20577 mkexpr( flags2 ),
20578 mkexpr( flags3 ) ) ) ),
20579 crfD );
20581 break;
20584 default:
20585 vex_printf( "dis_vxv_sp_arith(ppc)(opc2)\n" );
20586 return False;
20588 return True;
20592 * Vector Population Count/bit matrix transpose
20594 static Bool
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. */
20603 PREFIX_CHECK
20605 assign( vB, getVReg(vRB_addr));
20607 if (opc1 != 0x4) {
20608 vex_printf( "dis_av_count_bitTranspose(ppc)(instr)\n" );
20609 return False;
20612 switch (opc2) {
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 ) ) );
20616 break;
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 ) ) );
20621 break;
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 ) ) );
20626 break;
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 ) ) );
20631 break;
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) );
20653 break;
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) );
20677 break;
20680 case 0x783: // vpopcntw
20682 /* Break vector into 32-bit words and do the population count
20683 * on each word.
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) );
20701 break;
20704 case 0x7C3: // vpopcntd
20706 if (mode64) {
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 ) ) );
20726 } else {
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 ) ) );
20746 break;
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 ) ) );
20752 break;
20754 case 0x5CC: // vbpermd Vector Bit Permute Doubleword
20756 UChar vRA_addr = ifieldRegA( theInstr );
20757 IRTemp vA = newTemp( Ity_V128 );
20758 UInt j;
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];
20765 IRTemp tmp_hi[9];
20766 IRTemp tmp_lo[9];
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],
20788 binop( Iop_And64,
20789 binop( Iop_Shr64,
20790 unop( Iop_V128HIto64,
20791 mkexpr( vB ) ),
20792 mkU8( ( 7 - j ) * 8 ) ),
20793 mkU64( 0xFF ) ) );
20795 assign( index_dword_lo[j],
20796 binop( Iop_And64,
20797 binop( Iop_Shr64,
20798 unop( Iop_V128to64,
20799 mkexpr( vB ) ),
20800 mkU8( ( 7 - j ) * 8 ) ),
20801 mkU64( 0xFF ) ) );
20803 assign( index_dword_hi_valid[j],
20804 unop( Iop_1Sto64,
20805 binop( Iop_CmpLT64U,
20806 mkexpr( index_dword_hi[j] ),
20807 mkU64( 64 ) ) ) );
20809 assign( index_dword_lo_valid[j],
20810 unop( Iop_1Sto64,
20811 binop( Iop_CmpLT64U,
20812 mkexpr( index_dword_lo[j] ),
20813 mkU64( 64 ) ) ) );
20814 assign( pb_dword_hi[j],
20815 binop( Iop_And64,
20816 binop( Iop_Shr64,
20817 unop( Iop_V128HIto64,
20818 mkexpr( vA ) ),
20819 unop( Iop_64to8,
20820 binop( Iop_Sub64,
20821 mkU64( 63 ),
20822 mkexpr( index_dword_hi[j] )
20823 ) ) ),
20824 mkU64( 0x1 ) ) );
20826 assign( pb_dword_lo[j],
20827 binop( Iop_And64,
20828 binop( Iop_Shr64,
20829 unop( Iop_V128to64,
20830 mkexpr( vA ) ),
20831 unop( Iop_64to8,
20832 binop( Iop_Sub64,
20833 mkU64( 63 ),
20834 mkexpr( index_dword_lo[j] )
20835 ) ) ),
20836 mkU64( 0x1 ) ) );
20838 assign( tmp_hi[j+1],
20839 binop( Iop_Or64,
20840 binop( Iop_And64,
20841 mkexpr( index_dword_hi_valid[j] ),
20842 binop( Iop_Shl64,
20843 mkexpr( pb_dword_hi[j] ),
20844 mkU8( 7 - j ) ) ),
20845 mkexpr( tmp_hi[j] ) ) );
20847 assign( tmp_lo[j+1],
20848 binop( Iop_Or64,
20849 binop( Iop_And64,
20850 mkexpr( index_dword_lo_valid[j] ),
20851 binop( Iop_Shl64,
20852 mkexpr( pb_dword_lo[j] ),
20853 mkU8( 7 - j ) ) ),
20854 mkexpr( tmp_lo[j] ) ) );
20857 putVReg( vRT_addr,
20858 binop( Iop_64HLtoV128,
20859 mkexpr( tmp_hi[8] ),
20860 mkexpr( tmp_lo[8] ) ) );
20862 break;
20864 default:
20865 vex_printf("dis_av_count_bitTranspose(ppc)(opc2)\n");
20866 return False;
20867 break;
20869 return True;
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" );
20896 return False;
20899 switch (opc2) {
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,
20913 mkexpr( rS ),
20914 mkexpr( rB ),
20915 mkU64( 1 ) ) );
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 ) ) ) );
20927 assign( rA,
20928 unop( Iop_ClzNat64,
20929 binop( Iop_Or64,
20930 binop( Iop_Shl64,
20931 mkexpr( ones ),
20932 binop( Iop_Sub8,
20933 mkU8( max_bits ),
20934 unop( Iop_64to8,
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,
20951 mkexpr( rS ),
20952 mkexpr( rB ),
20953 mkU64( 0 ) ) );
20955 assign( rA,
20956 binop( Iop_Or64,
20957 binop( Iop_Shl64,
20958 mkexpr( zeros ),
20959 unop( Iop_64to8,
20960 mkexpr( cnt ) ) ),
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 ),
20967 unop( Iop_64to8,
20968 popcnt64( vbi,
20969 mkexpr( rB ) ) ) ) );
20971 assign( rA,
20972 unop( Iop_CtzNat64,
20973 binop( Iop_Or64,
20974 mkexpr( all_ones ), mkexpr( ones ) ) ) );
20976 } else { //pexld
20977 DIP("pexld r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
20978 assign( rA, mkexpr( ones ) );
20980 break;
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 ),
20989 mkexpr( rB ) ) );
20990 assign( rA, mkexpr( ones ) );
20991 break;
20994 default:
20995 vex_printf("dis_logical_mask_bits)(ppc)\n");
20996 return False;
20999 putIReg( rA_addr, mkexpr( rA ) );
21000 return True;
21003 static Bool
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 ) );
21017 if (opc1 != 4) {
21018 vex_printf( "dis_vector_logical_mask_bits(ppc)(instr)\n" );
21019 return False;
21022 assign( vA, getVReg(vRA_addr));
21023 assign( vB, getVReg(vRB_addr));
21025 switch (opc2) {
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");
21042 return False;
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;
21050 byte_mask = 1;
21052 i = 0;
21053 num_bits_hi = 0;
21054 while( i < 64) {
21055 extract_mask_hi = extract_mask_hi | (byte_mask << (63 - i));
21056 i = i + N;
21057 num_bits_hi++;
21060 num_bits_lo = 0;
21061 while( i < 128) {
21062 extract_mask_lo = extract_mask_lo | (byte_mask << (127 - i));
21063 i = i + N;
21064 num_bits_lo++;
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 ),
21075 mkU64( 1 ) ) );
21076 assign( ones_lo, extract_bits_under_mask ( vbi, mkexpr( vB_lo ),
21077 mkU64( extract_mask_lo ),
21078 mkU64( 1 ) ) );
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
21082 IBM numbering */
21083 putIReg( vRT_addr, binop( Iop_Or64,
21084 binop( Iop_Shl64,
21085 mkexpr( ones_hi ),
21086 mkU8( 64 - num_bits_hi ) ),
21087 binop( Iop_Shl64,
21088 mkexpr( ones_lo ),
21089 mkU8( 64 - num_bits_hi
21090 - num_bits_lo ) ) ) );
21092 return True;
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 );
21100 IRTemp zeros[2];
21101 IRTemp ones[2];
21102 IRTemp count[2];
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 ),
21122 mkexpr( vB_hi ),
21123 mkU64( 1 ) ) );
21124 assign( ones[1], extract_bits_under_mask ( vbi, mkexpr( vA_lo ),
21125 mkexpr( vB_lo ),
21126 mkU64( 1 ) ) );
21127 assign( zeros[0], extract_bits_under_mask ( vbi, mkexpr( vA_hi ),
21128 mkexpr( vB_hi ),
21129 mkU64( 0 ) ) );
21130 assign( zeros[1], extract_bits_under_mask ( vbi, mkexpr( vA_lo ),
21131 mkexpr( vB_lo ),
21132 mkU64( 0 ) ) );
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
21136 words. */
21137 putVReg( vRT_addr, binop( Iop_64HLtoV128,
21138 binop( Iop_Or64,
21139 binop( Iop_Shl64,
21140 mkexpr( zeros[0] ),
21141 unop( Iop_64to8,
21142 mkexpr( count[0] ) ) ),
21143 mkexpr( ones[0] ) ),
21144 binop( Iop_Or64,
21145 binop( Iop_Shl64,
21146 mkexpr( zeros[1] ),
21147 unop( Iop_64to8,
21148 mkexpr( count[1] ) ) ),
21149 mkexpr( ones[1] ) ) ) );
21151 break;
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 );
21159 IRTemp ones[2];
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 ),
21172 mkexpr( vB_hi ),
21173 mkU64( 1 ) ) );
21174 assign( ones[1], extract_bits_under_mask ( vbi, mkexpr( vA_lo ),
21175 mkexpr( vB_lo ),
21176 mkU64( 1 ) ) );
21177 putVReg( vRT_addr, binop( Iop_64HLtoV128,
21178 mkexpr( ones[0] ), mkexpr( ones[1] ) ) );
21180 break;
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 );
21188 IRTemp ones[2];
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] ) ) );
21207 break;
21209 case 0x784: // vclzdm,
21211 /* Vector Count Leading Zeros Doubleword under bit mask */
21213 IRTemp extracted_bits[2];
21214 IRTemp clz[2];
21215 IRTemp ones[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,
21241 mkexpr( vA_hi ),
21242 mkexpr( vB_hi ),
21243 mkU64( 1 ) ) );
21245 assign( ones[1], extract_bits_under_mask ( vbi,
21246 mkexpr( vA_lo ),
21247 mkexpr( vB_lo ),
21248 mkU64( 1 ) ) );
21250 assign( cnt_extract_bits[0],
21251 unop( Iop_16to8,
21252 unop( Iop_32to16,
21253 count_bits_under_mask ( vbi,
21254 mkexpr( vA_hi ),
21255 mkexpr( vB_hi ),
21256 mkU64( 1 ) ) ) ) );
21258 assign( cnt_extract_bits[1],
21259 unop( Iop_16to8,
21260 unop( Iop_32to16,
21261 count_bits_under_mask ( vbi,
21262 mkexpr( vA_lo ),
21263 mkexpr( vB_lo ),
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],
21269 binop( Iop_Or64,
21270 binop( Iop_Shr64,
21271 mkU64( 0xFFFFFFFFFFFFFFFF ),
21272 mkexpr( cnt_extract_bits[0] ) ),
21273 binop( Iop_Shl64,
21274 mkexpr( ones[0] ),
21275 binop( Iop_Sub8,
21276 mkU8( max_bits ),
21277 mkexpr( cnt_extract_bits[0] )
21278 ) ) ) );
21280 assign( clz[0],
21281 unop( Iop_Clz64,
21282 mkexpr( extracted_bits[0] ) ) );
21284 assign( extracted_bits[1],
21285 binop( Iop_Or64,
21286 binop( Iop_Shr64,
21287 mkU64( 0xFFFFFFFFFFFFFFFF ),
21288 mkexpr( cnt_extract_bits[1] ) ),
21289 binop( Iop_Shl64,
21290 mkexpr( ones[1] ),
21291 binop( Iop_Sub8,
21292 mkU8( max_bits ),
21293 mkexpr( cnt_extract_bits[1] )
21294 ) ) ) );
21295 assign( clz[1],
21296 unop( Iop_Clz64,
21297 mkexpr( extracted_bits[1] ) ) );
21299 putVReg( vRT_addr, binop( Iop_64HLtoV128,
21300 mkexpr( clz[0] ), mkexpr( clz[1] ) ) );
21301 break;
21304 case 0x7C4: // vctzdm
21306 /* Vector Count Trailing Zeros Doubleword under bit mask */
21307 IRTemp ctz[2];
21308 IRTemp ones[2];
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,
21333 binop( Iop_Shl64,
21334 mkU64( 0xFFFFFFFFFFFFFFFF ),
21335 unop( Iop_64to8,
21336 popcnt64( vbi, mkexpr( vB_hi ) ) ) ) );
21337 assign( all_ones_lo,
21338 binop( Iop_Shl64,
21339 mkU64( 0xFFFFFFFFFFFFFFFF ),
21340 unop( Iop_64to8,
21341 popcnt64( vbi, mkexpr( vB_lo ) ) ) ) );
21343 assign( ones[0],
21344 binop( Iop_Or64,
21345 mkexpr( all_ones_hi ),
21346 extract_bits_under_mask ( vbi,
21347 mkexpr( vA_hi ),
21348 mkexpr( vB_hi ),
21349 mkU64( 1 ) ) ) );
21351 assign( ones[1],
21352 binop( Iop_Or64,
21353 mkexpr( all_ones_lo ),
21354 extract_bits_under_mask ( vbi,
21355 mkexpr( vA_lo ),
21356 mkexpr( vB_lo ),
21357 mkU64( 1 ) ) ) );
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] ) ) );
21364 break;
21367 default:
21368 vex_printf("dis_vector_logical_mask_bits(ppc)(opc2)\n");
21369 return False;
21371 return True;
21374 typedef enum {
21375 PPC_CMP_EQ = 2,
21376 PPC_CMP_GT = 4,
21377 PPC_CMP_GE = 6,
21378 PPC_CMP_LT = 8
21379 } ppc_cmp_t;
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 --------------------------
21391 UN | 0x1 | 0x45
21392 EQ | 0x2 | 0x40
21393 GT | 0x4 | 0x00
21394 LT | 0x8 | 0x01
21396 condcode = Shl(1, (~(ccIR>>5) & 2)
21397 | ((ccIR ^ (ccIR>>6)) & 1)
21399 static IRTemp
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);
21406 assign( condcode,
21407 binop( Iop_Shl32,
21408 mkU32( 1 ),
21409 unop( Iop_32to8,
21410 binop( Iop_Or32,
21411 binop( Iop_And32,
21412 unop( Iop_Not32,
21413 binop( Iop_Shr32,
21414 mkexpr( ccIR ),
21415 mkU8( 5 ) ) ),
21416 mkU32( 2 ) ),
21417 binop( Iop_And32,
21418 binop( Iop_Xor32,
21419 mkexpr( ccIR ),
21420 binop( Iop_Shr32,
21421 mkexpr( ccIR ),
21422 mkU8( 6 ) ) ),
21423 mkU32( 1 ) ) ) ) ) );
21424 return condcode;
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,
21450 binop( Iop_And32,
21451 unop( Iop_64HIto32, mkexpr( frA_I64 ) ),
21452 mkU32( 0x00080000 ) ),
21453 mkU32( 0 ) ) ) );
21454 assign( frB_isSNaN,
21455 mkAND1( mkexpr(frB_isNaN),
21456 binop( Iop_CmpEQ32,
21457 binop( Iop_And32,
21458 unop( Iop_64HIto32, mkexpr( frB_I64 ) ),
21459 mkU32( 0x00080000 ) ),
21460 mkU32( 0 ) ) ) );
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 * <<<<<<<<<>>>>>>>>>>>>>>>>>>
21468 * if frA is a SNaN
21469 * result = frA converted to QNaN
21470 * else if frB is a SNaN
21471 * if (frA is QNan)
21472 * result = frA
21473 * else
21474 * result = frB converted to QNaN
21475 * else if frB is a QNaN
21476 * result = frA
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
21480 * result = frB
21481 * <<<<<<<<<>>>>>>>>>>>>>>>>>>
21484 #define SNAN_MASK 0x0008000000000000ULL
21486 return
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 */
21494 mkexpr(frA_I64),
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 */
21501 mkexpr(frA_I64),
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,
21513 mkexpr( src1 ) ),
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 */
21521 mkexpr( src1 ),
21522 /* else: use src2 */
21523 mkexpr( 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) {
21573 case 0x72:
21574 return "m";
21575 case 0x52:
21576 return "p";
21577 case 0x56:
21578 return "c";
21579 case 0x32:
21580 return "z";
21581 case 0x12:
21582 return "";
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);
21601 IRExpr * hi32;
21602 IRExpr * rxpi_rm;
21603 switch (opc2 & 0x7F) {
21604 case 0x72:
21605 rxpi_rm = mkU32(Irrm_NegINF);
21606 break;
21607 case 0x52:
21608 rxpi_rm = mkU32(Irrm_PosINF);
21609 break;
21610 case 0x56:
21611 rxpi_rm = get_IR_roundingmode();
21612 break;
21613 case 0x32:
21614 rxpi_rm = mkU32(Irrm_ZERO);
21615 break;
21616 case 0x12:
21617 rxpi_rm = mkU32(Irrm_NEAREST);
21618 break;
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,
21627 mkexpr( frB ) ) );
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 */
21634 assign( frD,
21635 IRExpr_ITE(
21636 binop( Iop_CmpNE8,
21637 unop( Iop_32to8,
21638 binop( Iop_CmpF64,
21639 IRExpr_Const( IRConst_F64( 9e18 ) ),
21640 unop( Iop_AbsF64, mkexpr( frB ) ) ) ),
21641 mkU8(0) ),
21642 mkexpr( frB ),
21643 IRExpr_ITE(
21644 binop( Iop_CmpNE32,
21645 binop( Iop_Shr32,
21646 unop( Iop_64HIto32,
21647 mkexpr( frB_I64 ) ),
21648 mkU8( 31 ) ),
21649 mkU32(0) ),
21650 unop( Iop_NegF64,
21651 unop( Iop_AbsF64,
21652 binop( Iop_I64StoF64,
21653 mkU32( 0 ),
21654 mkexpr( intermediateResult ) ) ) ),
21655 binop( Iop_I64StoF64,
21656 mkU32( 0 ),
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) );
21667 assign( is_SNAN,
21668 mkAND1( is_NaN( Ity_I64, frB_I64 ),
21669 binop( Iop_CmpEQ32,
21670 binop( Iop_And32, hi32, mkU32( 0x00080000 ) ),
21671 mkU32( 0 ) ) ) );
21673 return IRExpr_ITE( mkexpr( is_SNAN ),
21674 unop( Iop_ReinterpI64asF64,
21675 binop( Iop_Xor64,
21676 mkU64( SNAN_MASK ),
21677 mkexpr( frB_I64 ) ) ),
21678 mkexpr( frD ));
21682 * Miscellaneous VSX vector instructions
21684 static Bool
21685 dis_vxv_misc ( UInt prefix, UInt theInstr, UInt opc2 )
21687 /* XX3-Form */
21688 UChar opc1 = ifieldOPC( theInstr );
21689 UChar XT = ifieldRegXT( theInstr );
21690 UChar XB = ifieldRegXB( theInstr );
21692 /* There is no prefixed version of these instructions. */
21693 PREFIX_CHECK
21695 if (opc1 != 0x3C) {
21696 vex_printf( "dis_vxv_misc(ppc)(instr)\n" );
21697 return False;
21700 switch (opc2) {
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);
21717 if (!redp) {
21718 assign( sqrtHi,
21719 binop( Iop_SqrtF64,
21721 unop( Iop_ReinterpI64asF64, mkexpr( frB ) ) ) );
21722 assign( sqrtLo,
21723 binop( Iop_SqrtF64,
21725 unop( Iop_ReinterpI64asF64, mkexpr( frB2 ) ) ) );
21727 putVSReg( XT,
21728 binop( Iop_64HLtoV128,
21729 unop( Iop_ReinterpF64asI64,
21730 triop( Iop_DivF64,
21732 ieee_one,
21733 redp ? unop( Iop_ReinterpI64asF64,
21734 mkexpr( frB ) )
21735 : mkexpr( sqrtHi ) ) ),
21736 unop( Iop_ReinterpF64asI64,
21737 triop( Iop_DivF64,
21739 ieee_one,
21740 redp ? unop( Iop_ReinterpI64asF64,
21741 mkexpr( frB2 ) )
21742 : mkexpr( sqrtLo ) ) ) ) );
21743 break;
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 );
21767 if (!resp) {
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 ) ) );
21774 assign( res0,
21775 unop( Iop_ReinterpF32asI32,
21776 unop( Iop_TruncF64asF32,
21777 triop( Iop_DivF64r32,
21779 ieee_one,
21780 resp ? mkexpr( b0 ) : mkexpr( sqrt0 ) ) ) ) );
21781 assign( res1,
21782 unop( Iop_ReinterpF32asI32,
21783 unop( Iop_TruncF64asF32,
21784 triop( Iop_DivF64r32,
21786 ieee_one,
21787 resp ? mkexpr( b1 ) : mkexpr( sqrt1 ) ) ) ) );
21788 assign( res2,
21789 unop( Iop_ReinterpF32asI32,
21790 unop( Iop_TruncF64asF32,
21791 triop( Iop_DivF64r32,
21793 ieee_one,
21794 resp ? mkexpr( b2 ) : mkexpr( sqrt2 ) ) ) ) );
21795 assign( res3,
21796 unop( Iop_ReinterpF32asI32,
21797 unop( Iop_TruncF64asF32,
21798 triop( Iop_DivF64r32,
21800 ieee_one,
21801 resp ? mkexpr( b3 ) : mkexpr( sqrt3 ) ) ) ) );
21802 putVSReg( XT,
21803 binop( Iop_64HLtoV128,
21804 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
21805 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
21806 break;
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 ) ) );
21842 assign( res0,
21843 unop( Iop_ReinterpF32asI32,
21844 unop( Iop_TruncF64asF32,
21845 unop( Iop_ReinterpI64asF64,
21846 get_max_min_fp( a0_I64, b0_I64, isMin ) ) ) ) );
21847 assign( res1,
21848 unop( Iop_ReinterpF32asI32,
21849 unop( Iop_TruncF64asF32,
21850 unop( Iop_ReinterpI64asF64,
21851 get_max_min_fp( a1_I64, b1_I64, isMin ) ) ) ) );
21852 assign( res2,
21853 unop( Iop_ReinterpF32asI32,
21854 unop( Iop_TruncF64asF32,
21855 unop( Iop_ReinterpI64asF64,
21856 get_max_min_fp( a2_I64, b2_I64, isMin ) ) ) ) );
21857 assign( res3,
21858 unop( Iop_ReinterpF32asI32,
21859 unop( Iop_TruncF64asF32,
21860 unop( Iop_ReinterpI64asF64,
21861 get_max_min_fp( a3_I64, b3_I64, isMin ) ) ) ) );
21862 putVSReg( XT,
21863 binop( Iop_64HLtoV128,
21864 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
21865 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
21866 break;
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) ) );
21885 break;
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);
21900 putVSReg( XT,
21901 binop( Iop_64HLtoV128,
21902 binop( Iop_Or64,
21903 binop( Iop_And64,
21904 mkexpr( frA ),
21905 mkU64( SIGN_BIT ) ),
21906 binop( Iop_And64,
21907 mkexpr( frB ),
21908 mkU64( SIGN_MASK ) ) ),
21909 binop( Iop_Or64,
21910 binop( Iop_And64,
21911 mkexpr( frA2 ),
21912 mkU64( SIGN_BIT ) ),
21913 binop( Iop_And64,
21914 mkexpr( frB2 ),
21915 mkU64( SIGN_MASK ) ) ) ) );
21916 break;
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 );
21932 assign( resHi,
21933 binop( Iop_32HLto64,
21934 binop( Iop_Or32,
21935 binop( Iop_And32,
21936 unop(Iop_64to32, mkexpr( a3_I64 ) ),
21937 mkU32( SIGN_BIT32 ) ),
21938 binop( Iop_And32,
21939 unop(Iop_64to32, mkexpr( b3_I64 ) ),
21940 mkU32( SIGN_MASK32) ) ),
21942 binop( Iop_Or32,
21943 binop( Iop_And32,
21944 unop(Iop_64to32, mkexpr( a2_I64 ) ),
21945 mkU32( SIGN_BIT32 ) ),
21946 binop( Iop_And32,
21947 unop(Iop_64to32, mkexpr( b2_I64 ) ),
21948 mkU32( SIGN_MASK32 ) ) ) ) );
21949 assign( resLo,
21950 binop( Iop_32HLto64,
21951 binop( Iop_Or32,
21952 binop( Iop_And32,
21953 unop(Iop_64to32, mkexpr( a1_I64 ) ),
21954 mkU32( SIGN_BIT32 ) ),
21955 binop( Iop_And32,
21956 unop(Iop_64to32, mkexpr( b1_I64 ) ),
21957 mkU32( SIGN_MASK32 ) ) ),
21959 binop( Iop_Or32,
21960 binop( Iop_And32,
21961 unop(Iop_64to32, mkexpr( a0_I64 ) ),
21962 mkU32( SIGN_BIT32 ) ),
21963 binop( Iop_And32,
21964 unop(Iop_64to32, mkexpr( b0_I64 ) ),
21965 mkU32( SIGN_MASK32 ) ) ) ) );
21966 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( resHi ), mkexpr( resLo ) ) );
21967 break;
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 ) ) ) );
21985 } else {
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 ) ) ) );
21992 break;
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,
22013 getVSReg( XB ),
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 ) ) ) );
22026 putVSReg( XT,
22027 binop( Iop_OrV128,
22028 mkexpr( absVal_vector ),
22029 mkexpr( signBit_vector ) ) );
22030 } else {
22031 putVSReg( XT, mkexpr( absVal_vector ) );
22033 break;
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 ) ) ) );
22054 putVSReg( XT,
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 ) ) ) ) );
22062 break;
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);
22071 putVSReg( XT,
22072 binop( Iop_64HLtoV128,
22073 unop( Iop_ReinterpF64asI64,
22074 unop( Iop_NegF64, mkexpr( frB ) ) ),
22075 unop( Iop_ReinterpF64asI64,
22076 unop( Iop_NegF64, mkexpr( frB2 ) ) ) ) );
22077 break;
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);
22096 putVSReg( XT,
22097 binop( Iop_64HLtoV128,
22098 unop( Iop_ReinterpF64asI64, frD_fp_roundHi ),
22099 unop( Iop_ReinterpF64asI64, frD_fp_roundLo ) ) );
22100 break;
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;
22109 IROp op;
22110 if (opc2 != 0x156) {
22111 // Use pre-defined IRop's for vrfi{m|n|p|z}
22112 switch (opc2) {
22113 case 0x112:
22114 insn_suffix = "";
22115 op = Iop_RoundF32x4_RN;
22116 break;
22117 case 0x172:
22118 insn_suffix = "m";
22119 op = Iop_RoundF32x4_RM;
22120 break;
22121 case 0x152:
22122 insn_suffix = "p";
22123 op = Iop_RoundF32x4_RP;
22124 break;
22125 case 0x132:
22126 insn_suffix = "z";
22127 op = Iop_RoundF32x4_RZ;
22128 break;
22130 default:
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) ) );
22136 } else {
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);
22161 putVSReg( XT,
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 ) ) ) );
22170 break;
22173 default:
22174 vex_printf( "dis_vxv_misc(ppc)(opc2)\n" );
22175 return False;
22177 return True;
22182 * VSX Scalar Floating Point Arithmetic Instructions
22184 static Bool
22185 dis_vxs_arith ( UInt prefix, UInt theInstr, UInt opc2 )
22187 /* XX3-Form */
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. */
22197 PREFIX_CHECK
22199 if (opc1 != 0x3C) {
22200 vex_printf( "dis_vxs_arith(ppc)(instr)\n" );
22201 return False;
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.
22211 switch (opc2) {
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,
22218 mkexpr( frA ),
22219 mkexpr( frB ) ) ) ),
22220 mkU64( 0 ) ) );
22221 break;
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,
22228 mkexpr( frA ),
22229 mkexpr( frB ) ) ) ),
22230 mkU64( 0 ) ) );
22231 break;
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,
22236 mkexpr( frA ),
22237 mkexpr( frB ) ) ),
22238 mkU64( 0 ) ) );
22239 break;
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,
22246 mkexpr( frA ),
22247 mkexpr( frB ) ) ) ),
22248 mkU64( 0 ) ) );
22249 break;
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,
22254 mkexpr( frA ),
22255 mkexpr( frB ) ) ),
22256 mkU64( 0 ) ) );
22257 break;
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 ) ) ) );
22267 putVSReg( XT,
22268 binop( Iop_64HLtoV128,
22269 unop( Iop_ReinterpF64asI64,
22270 binop( Iop_RoundF64toF32, rm,
22271 qop( Iop_MAddF64, rm,
22272 mkexpr( frA ),
22273 mkexpr( mdp ? frT : frB ),
22274 mkexpr( mdp ? frB : frT ) ) ) ),
22275 mkU64( 0 ) ) );
22276 break;
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,
22287 mkexpr( frA ),
22288 mkexpr( mdp ? frT : frB ),
22289 mkexpr( mdp ? frB : frT ) ) ),
22290 mkU64( 0 ) ) );
22291 break;
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 ) ) ) );
22302 putVSReg( XT,
22303 binop( Iop_64HLtoV128,
22304 unop( Iop_ReinterpF64asI64,
22305 binop( Iop_RoundF64toF32, rm,
22306 qop( Iop_MSubF64, rm,
22307 mkexpr( frA ),
22308 mkexpr( mdp ? frT : frB ),
22309 mkexpr( mdp ? frB : frT ) ) ) ),
22310 mkU64( 0 ) ) );
22311 break;
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,
22322 mkexpr( frA ),
22323 mkexpr( mdp ? frT : frB ),
22324 mkexpr( mdp ? frB : frT ) ) ),
22325 mkU64( 0 ) ) );
22326 break;
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,
22345 mkexpr( frA ),
22346 mkexpr( mdp ? frT : frB ),
22347 mkexpr( mdp ? frB : frT ) ) ) );
22349 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(maddResult) ),
22350 mkU64( 0 ) ) );
22351 break;
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,
22368 mkexpr( frA ),
22369 mkexpr( mdp ? frT : frB ),
22370 mkexpr( mdp ? frB : frT ) ) ) ) );
22372 putVSReg( XT, binop( Iop_64HLtoV128,
22373 mkexpr( getNegatedResult(maddResult) ),
22374 mkU64( 0 ) ) );
22375 break;
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,
22392 mkexpr( frA ),
22393 mkexpr( mdp ? frT : frB ),
22394 mkexpr( mdp ? frB : frT ) ) ) ) );
22396 putVSReg( XT, binop( Iop_64HLtoV128,
22397 mkexpr( getNegatedResult(msubResult) ),
22398 mkU64( 0 ) ) );
22400 break;
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,
22413 qop( Iop_MSubF64,
22415 mkexpr( frA ),
22416 mkexpr( mdp ? frT : frB ),
22417 mkexpr( mdp ? frB : frT ) ) ));
22419 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(msubResult) ), mkU64( 0 ) ) );
22421 break;
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,
22430 mkexpr( frA ),
22431 mkexpr( frB ) ) ) ),
22432 mkU64( 0 ) ) );
22433 break;
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,
22439 mkexpr( frA ),
22440 mkexpr( frB ) ) ),
22441 mkU64( 0 ) ) );
22442 break;
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,
22447 mkexpr( frA ),
22448 mkexpr( frB ) ) ),
22449 mkU64( 0 ) ) );
22450 break;
22452 case 0x016: // xssqrtsp (VSX Scalar Square Root Single-Precision)
22453 DIP("xssqrtsp v%d,v%d\n", XT, XB);
22454 putVSReg( XT,
22455 binop( Iop_64HLtoV128,
22456 unop( Iop_ReinterpF64asI64,
22457 binop( Iop_RoundF64toF32, rm,
22458 binop( Iop_SqrtF64, rm,
22459 mkexpr( frB ) ) ) ),
22460 mkU64( 0 ) ) );
22461 break;
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,
22467 mkexpr( frB ) ) ),
22468 mkU64( 0 ) ) );
22469 break;
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 );
22480 break;
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.
22495 assign( flags,
22496 binop( Iop_Or32,
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 );
22501 break;
22504 default:
22505 vex_printf( "dis_vxs_arith(ppc)(opc2)\n" );
22506 return False;
22509 return True;
22514 * VSX Floating Point Compare Instructions
22516 static Bool
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 ) );
22522 IRTemp ccPPC32;
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. */
22529 PREFIX_CHECK
22531 if (opc1 != 0x3C) {
22532 vex_printf( "dis_vx_cmp(ppc)(instr)\n" );
22533 return False;
22536 assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
22537 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
22538 switch (opc2) {
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",
22543 crfD, XA, XB);
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 ) );
22547 break;
22549 default:
22550 vex_printf( "dis_vx_cmp(ppc)(opc2)\n" );
22551 return False;
22553 return True;
22556 static void
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);
22565 IRTemp ccIR_hi;
22566 IRTemp ccIR_lo;
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,
22580 mkexpr( frA_hi ),
22581 mkexpr( frB_hi ) ) );
22582 ccIR_lo = get_fp_cmp_CR_val( binop( Iop_CmpF64,
22583 mkexpr( frA_lo ),
22584 mkexpr( frB_lo ) ) );
22586 if (cmp_type != PPC_CMP_GE) {
22587 assign( hiResult,
22588 unop( Iop_1Sto64,
22589 binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( cmp_type ) ) ) );
22590 assign( loResult,
22591 unop( Iop_1Sto64,
22592 binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( cmp_type ) ) ) );
22593 } else {
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.
22609 assign( hiEQlo,
22610 binop( Iop_CmpEQ32,
22611 unop( Iop_64to32, mkexpr( hiResult ) ),
22612 unop( Iop_64to32, mkexpr( loResult ) ) ) );
22613 putVSReg( XT,
22614 binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
22616 assign( all_elem_true,
22617 unop( Iop_1Uto32,
22618 mkAND1( mkexpr( hiEQlo ),
22619 binop( Iop_CmpEQ32,
22620 mkU32( 0xffffffff ),
22621 unop( Iop_64to32,
22622 mkexpr( hiResult ) ) ) ) ) );
22624 assign( all_elem_false,
22625 unop( Iop_1Uto32,
22626 mkAND1( mkexpr( hiEQlo ),
22627 binop( Iop_CmpEQ32,
22628 mkU32( 0 ),
22629 unop( Iop_64to32,
22630 mkexpr( hiResult ) ) ) ) ) );
22631 assign( ccPPC32,
22632 binop( Iop_Or32,
22633 binop( Iop_Shl32, mkexpr( all_elem_false ), mkU8( 1 ) ),
22634 binop( Iop_Shl32, mkexpr( all_elem_true ), mkU8( 3 ) ) ) );
22636 if (flag_rC) {
22637 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), 6 );
22642 * VSX Vector Compare Instructions
22644 static Bool
22645 dis_vvec_cmp( UInt prefix, UInt theInstr, UInt opc2 )
22647 /* XX3-Form */
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. */
22657 PREFIX_CHECK
22659 if (opc1 != 0x3C) {
22660 vex_printf( "dis_vvec_cmp(ppc)(instr)\n" );
22661 return False;
22664 assign( vA, getVSReg( XA ) );
22665 assign( vB, getVSReg( XB ) );
22667 switch (opc2) {
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 ? ".":""),
22671 XT, XA, XB);
22672 do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_EQ);
22673 break;
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 ? ".":""),
22679 XT, XA, XB);
22680 do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GE);
22681 break;
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 ? ".":""),
22687 XT, XA, XB);
22688 do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GT);
22689 break;
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 ? ".":""),
22697 XT, XA, XB);
22698 assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
22699 putVSReg( XT, mkexpr(vD) );
22700 if (flag_rC) {
22701 set_AV_CR6( mkexpr(vD), True );
22703 break;
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 ? ".":""),
22711 XT, XA, XB);
22712 assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
22713 putVSReg( XT, mkexpr(vD) );
22714 if (flag_rC) {
22715 set_AV_CR6( mkexpr(vD), True );
22717 break;
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 ? ".":""),
22725 XT, XA, XB);
22726 assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
22727 putVSReg( XT, mkexpr(vD) );
22728 if (flag_rC) {
22729 set_AV_CR6( mkexpr(vD), True );
22731 break;
22734 default:
22735 vex_printf( "dis_vvec_cmp(ppc)(opc2)\n" );
22736 return False;
22738 return True;
22741 * Miscellaneous VSX Scalar Instructions
22743 static Bool
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" );
22753 return False;
22756 DIP("lxvkq v%u,%u\n", (UInt)XT, uim);
22758 switch( uim ) {
22759 case 0b00001: putVSReg( XT, binop( Iop_64HLtoV128,
22760 mkU64( 0x3FFF000000000000 ),
22761 mkU64( 0x0000000000000000 ) ) );
22762 break;
22763 case 0b00010: putVSReg( XT, binop( Iop_64HLtoV128,
22764 mkU64( 0x4000000000000000 ),
22765 mkU64( 0x0000000000000000 ) ) );
22766 break;
22767 case 0b00011: putVSReg( XT, binop( Iop_64HLtoV128,
22768 mkU64( 0x4000800000000000 ),
22769 mkU64( 0x0000000000000000 ) ) );
22770 break;
22771 case 0b00100: putVSReg( XT, binop( Iop_64HLtoV128,
22772 mkU64( 0x4001000000000000 ),
22773 mkU64( 0x0000000000000000 ) ) );
22774 break;
22775 case 0b00101: putVSReg( XT, binop( Iop_64HLtoV128,
22776 mkU64( 0x4001400000000000 ),
22777 mkU64( 0x0000000000000000 ) ) );
22778 break;
22779 case 0b00110: putVSReg( XT, binop( Iop_64HLtoV128,
22780 mkU64( 0x4001800000000000 ),
22781 mkU64( 0x0000000000000000 ) ) );
22782 break;
22783 case 0b00111: putVSReg( XT, binop( Iop_64HLtoV128,
22784 mkU64( 0x4001C00000000000 ),
22785 mkU64( 0x0000000000000000 ) ) );
22786 break;
22787 case 0b01000: putVSReg( XT, binop( Iop_64HLtoV128,
22788 mkU64( 0x7FFF000000000000 ),
22789 mkU64( 0x0000000000000000 ) ) );
22790 break;
22791 case 0b01001: putVSReg( XT, binop( Iop_64HLtoV128,
22792 mkU64( 0x7FFF800000000000 ),
22793 mkU64( 0x0000000000000000 ) ) );
22794 break;
22795 case 0b10000: putVSReg( XT, binop( Iop_64HLtoV128,
22796 mkU64( 0x8000000000000000 ),
22797 mkU64( 0x0000000000000000 ) ) );
22798 break;
22799 case 0b10001: putVSReg( XT, binop( Iop_64HLtoV128,
22800 mkU64( 0xBFFF000000000000 ),
22801 mkU64( 0x0000000000000000 ) ) );
22802 break;
22803 case 0b10010: putVSReg( XT, binop( Iop_64HLtoV128,
22804 mkU64( 0xC000000000000000 ),
22805 mkU64( 0x0000000000000000 ) ) );
22806 break;
22807 case 0b10011: putVSReg( XT, binop( Iop_64HLtoV128,
22808 mkU64( 0xC000800000000000 ),
22809 mkU64( 0x0000000000000000 ) ) );
22810 break;
22811 case 0b10100: putVSReg( XT, binop( Iop_64HLtoV128,
22812 mkU64( 0xC001000000000000 ),
22813 mkU64( 0x0000000000000000 ) ) );
22814 break;
22815 case 0b10101: putVSReg( XT, binop( Iop_64HLtoV128,
22816 mkU64( 0xC001400000000000 ),
22817 mkU64( 0x0000000000000000 ) ) );
22818 break;
22819 case 0b10110: putVSReg( XT, binop( Iop_64HLtoV128,
22820 mkU64( 0xC001800000000000 ),
22821 mkU64( 0x0000000000000000 ) ) );
22822 break;
22823 case 0b10111: putVSReg( XT, binop( Iop_64HLtoV128,
22824 mkU64( 0xC001C00000000000 ),
22825 mkU64( 0x0000000000000000 ) ) );
22826 break;
22827 case 0b11000: putVSReg( XT, binop( Iop_64HLtoV128,
22828 mkU64( 0xFFFF000000000000 ),
22829 mkU64( 0x0000000000000000 ) ) );
22830 break;
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 */
22837 return True;
22840 static Bool
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. */
22854 PREFIX_CHECK
22856 if (opc1 != 0x3C) {
22857 vex_printf( "dis_vxs_misc(ppc)(instr)\n" );
22858 return False;
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 ) ) ) );
22884 return True;
22887 switch ( opc2 ) {
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,
22909 binop( Iop_And64,
22910 mkexpr( vA_hi ),
22911 mask ),
22912 binop( Iop_And64,
22913 mkexpr( vB_hi ),
22914 mask ) );
22915 /* A exp > B exp */
22916 bit5 = binop( Iop_CmpLT64U,
22917 binop( Iop_And64,
22918 mkexpr( vB_hi ),
22919 mask ),
22920 binop( Iop_And64,
22921 mkexpr( vA_hi ),
22922 mask ) );
22923 /* test equal */
22924 bit6 = binop( Iop_CmpEQ64,
22925 binop( Iop_And64,
22926 mkexpr( vA_hi ),
22927 mask ),
22928 binop( Iop_And64,
22929 mkexpr( vB_hi ),
22930 mask ) );
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,
22937 binop( Iop_Shl32,
22938 unop( Iop_1Uto32, bit4 ),
22939 mkU8( 3) ),
22940 binop( Iop_Or32,
22941 binop( Iop_Shl32,
22942 unop( Iop_1Uto32, bit5 ),
22943 mkU8( 2) ),
22944 binop( Iop_Shl32,
22945 unop( Iop_1Uto32, bit6 ),
22946 mkU8( 1 ) ) ) ) );
22947 assign(CC, binop( Iop_Or32,
22948 binop( Iop_And32,
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 ) );
22955 return True;
22957 break;
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);
22965 putVSReg( XT,
22966 binop( Iop_ShlV128,
22967 binop( Iop_AndV128,
22968 binop( Iop_ShrV128,
22969 mkexpr( vB ),
22970 mkU8( ( 12 - uim ) * 8 ) ),
22971 binop(Iop_64HLtoV128,
22972 mkU64( 0 ),
22973 mkU64( 0xFFFFFFFF ) ) ),
22974 mkU8( ( 32*2 ) ) ) );
22975 break;
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,
22987 mkexpr( vT ),
22988 unop( Iop_NotV128,
22989 binop( Iop_ShlV128,
22990 binop( Iop_64HLtoV128,
22991 mkU64( 0x0 ),
22992 mkU64( 0xFFFFFFFF) ),
22993 mkU8( ( 12 - uim ) * 8 ) ) ) ) );
22995 putVSReg( XT,
22996 binop( Iop_OrV128,
22997 binop( Iop_ShlV128,
22998 binop( Iop_AndV128,
22999 binop( Iop_ShrV128,
23000 mkexpr( vB ),
23001 mkU8( 32 * 2 ) ),
23002 binop( Iop_64HLtoV128,
23003 mkU64( 0 ),
23004 mkU64( 0xFFFFFFFF ) ) ),
23005 mkU8( ( 12 - uim ) * 8 ) ),
23006 mkexpr( tmp ) ) );
23007 break;
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) ),
23022 mkexpr(lo64) ) );
23023 } else {
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));
23030 break;
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,
23047 binop( Iop_And64,
23048 unop( Iop_V128HIto64, mkexpr( vB ) ),
23049 mkU64( 0x7FF0000000000000 ) ),
23050 mkU8 ( 52 ) ) );
23051 } else if (inst_select == 1) {
23052 IRExpr *normal;
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,
23067 binop( Iop_And64,
23068 mkexpr( tmp ),
23069 mkU64( 0xFFFFFFFFFFFFF ) ),
23070 binop( Iop_Shl64,
23071 unop( Iop_1Uto64, normal),
23072 mkU8( 52 ) ) ) );
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
23081 * is undefined.
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 );
23091 return True;
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 );
23106 return True;
23108 } else {
23109 vex_printf( "dis_vxv_scalar_extract_exp_sig invalid inst_select (ppc)(opc2)\n" );
23110 vex_printf("inst_select = %u\n", inst_select);
23111 return False;
23114 break;
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,
23141 binop( Iop_Shr64,
23142 mkexpr( vB_hi ),
23143 mkU8( 63 ) ),
23144 mkU64( 0 ) ) ) );
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))
23158 assign( tmp,
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,
23166 mkexpr( vB_hi ),
23167 mkexpr( tmp ) ) ) ) );
23168 assign( exponent,
23169 binop( Iop_Shr64,
23170 binop( Iop_And64,
23171 mkexpr( vB_hi ),
23172 mkU64( 0x7ff0000000000000 ) ),
23173 mkU8( 52 ) ) );
23174 assign( dnorm, unop( Iop_1Uto64,
23175 mkOR1( is_Denorm( Ity_I64, vB_hi ),
23176 mkAND1( binop( Iop_CmpLT64U,
23177 mkexpr( exponent ),
23178 mkU64( 0x381 ) ),
23179 binop( Iop_CmpNE64,
23180 mkexpr( exponent ),
23181 mkU64( 0x0 ) ) ) ) ) );
23183 } else {
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 ) );
23190 assign( CC,
23191 binop( Iop_Or64,
23192 binop( Iop_And64, /* vB sign bit */
23193 binop( Iop_Shr64,
23194 mkexpr( vB_hi ),
23195 mkU8( 60 ) ),
23196 mkU64( 0x8 ) ),
23197 binop( Iop_Or64,
23198 binop( Iop_Shl64,
23199 unop( Iop_1Uto64,
23200 binop( Iop_CmpNE64,
23201 binop( Iop_And64,
23202 mkexpr( DCM ),
23203 mkU64( DCMX_mask ) ),
23204 mkU64( 0 ) ) ),
23205 mkU8( 1 ) ),
23206 mkexpr( not_sp ) ) ) );
23207 putGST_field( PPC_GST_CR, unop( Iop_64to32, mkexpr( CC ) ), BF );
23208 putFPCC( unop( Iop_64to32, mkexpr( CC ) ) );
23210 return True;
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,
23221 mkexpr(vA)),
23222 mkU64(~VG_PPC_SIGN_MASK) ) );
23223 assign( vecB_unsigned, binop( Iop_And64,
23224 unop( Iop_V128HIto64,
23225 mkexpr(vB) ),
23226 mkU64(VG_PPC_SIGN_MASK) ) );
23227 assign( vec_result, binop( Iop_64HLtoV128,
23228 binop( Iop_Or64,
23229 mkexpr(vecA_signed),
23230 mkexpr(vecB_unsigned) ),
23231 mkU64(0x0ULL)));
23232 putVSReg(XT, mkexpr(vec_result));
23233 break;
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,
23242 mkexpr(vB) ),
23243 mkU64(~VG_PPC_SIGN_MASK) ) );
23244 putVSReg(XT, binop( Iop_64HLtoV128,
23245 mkexpr(BHi_signed), mkU64(0x0ULL) ) );
23246 break;
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,
23261 unop( Iop_Not1,
23262 unop( Iop_32to1,
23263 binop( Iop_Shr32,
23264 unop( Iop_64HIto32,
23265 binop( Iop_And64,
23266 mkexpr(BHi_signed),
23267 mkU64(~VG_PPC_SIGN_MASK) )
23269 mkU8(31) ) ) ) );
23270 assign( BHi_negated,
23271 binop( Iop_Or64,
23272 binop( Iop_32HLto64,
23273 binop( Iop_Shl32,
23274 unop( Iop_1Uto32,
23275 mkexpr(BHi_negated_signbit) ),
23276 mkU8(31) ),
23277 mkU32(0) ),
23278 mkexpr(BHi_unsigned) ) );
23279 assign( vec_result, binop( Iop_64HLtoV128, mkexpr(BHi_negated),
23280 mkU64(0x0ULL)));
23281 putVSReg( XT, mkexpr(vec_result));
23282 break;
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 ) ) );
23296 break;
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);
23311 putVSReg( XT,
23312 binop( Iop_64HLtoV128,
23313 unop( Iop_ReinterpF64asI64, frD_fp_round),
23314 mkU64( 0 ) ) );
23315 break;
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,
23328 XB);
23330 assign( frB,
23331 unop( Iop_ReinterpI64asF64,
23332 unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
23334 if (!redp)
23335 assign( sqrt,
23336 binop( Iop_SqrtF64,
23338 mkexpr(frB) ) );
23339 putVSReg( XT,
23340 binop( Iop_64HLtoV128,
23341 unop( Iop_ReinterpF64asI64,
23342 binop( Iop_RoundF64toF32, rm,
23343 triop( Iop_DivF64,
23345 ieee_one,
23346 redp ? mkexpr( frB ) :
23347 mkexpr( sqrt ) ) ) ),
23348 mkU64( 0 ) ) );
23349 break;
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);
23362 assign( frB,
23363 unop( Iop_ReinterpI64asF64,
23364 unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
23366 if (!redp)
23367 assign( sqrt,
23368 binop( Iop_SqrtF64,
23370 mkexpr(frB) ) );
23371 putVSReg( XT,
23372 binop( Iop_64HLtoV128,
23373 unop( Iop_ReinterpF64asI64,
23374 triop( Iop_DivF64,
23376 ieee_one,
23377 redp ? mkexpr( frB ) : mkexpr( sqrt ) ) ),
23378 mkU64( 0 ) ) );
23379 break;
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);
23387 assign( frB,
23388 unop( Iop_ReinterpI64asF64,
23389 unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
23391 putVSReg( XT, binop( Iop_64HLtoV128,
23392 unop( Iop_ReinterpF64asI64,
23393 binop( Iop_RoundF64toF32,
23395 mkexpr( frB ) ) ),
23396 mkU64( 0 ) ) );
23397 break;
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];
23408 IRTemp value[4];
23409 IRTemp NaN[4];
23410 IRTemp inf[4];
23411 IRTemp pos[4];
23412 IRTemp DCM[4];
23413 IRTemp zero[4];
23414 IRTemp dnorm[4];
23415 Int i;
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);
23430 assign( value[i],
23431 unop( Iop_64to32,
23432 unop( Iop_V128to64,
23433 binop( Iop_AndV128,
23434 binop( Iop_ShrV128,
23435 mkexpr( vB ),
23436 mkU8( (3-i)*32 ) ),
23437 binop( Iop_64HLtoV128,
23438 mkU64( 0x0 ),
23439 mkU64( 0xFFFFFFFF ) ) ) ) ) );
23441 assign( pos[i], unop( Iop_1Uto32,
23442 binop( Iop_CmpEQ32,
23443 binop( Iop_Shr32,
23444 mkexpr( value[i] ),
23445 mkU8( 31 ) ),
23446 mkU32( 0 ) ) ) );
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,
23453 value[i] ) ) );
23454 assign( DCM[i], create_DCM( Ity_I32, NaN[i], inf[i], zero[i],
23455 dnorm[i], pos[i] ) );
23457 assign( match_value[i],
23458 unop( Iop_1Sto32,
23459 binop( Iop_CmpNE32,
23460 binop( Iop_And32,
23461 mkU32( DCMX_mask ),
23462 mkexpr( DCM[i] ) ),
23463 mkU32( 0 ) ) ) );
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] ) ) ) );
23474 break;
23476 case 0x360: // xviexpsp (VSX Vector Insert Exponent Single-Precision)
23478 Int i;
23479 IRTemp new_XT[5];
23480 IRTemp A_value[4];
23481 IRTemp B_value[4];
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,
23487 mkU64( 0x0 ),
23488 mkU64( 0x0 ) ) );
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],
23495 unop( Iop_64to32,
23496 unop( Iop_V128to64,
23497 binop( Iop_AndV128,
23498 binop( Iop_ShrV128,
23499 mkexpr( vA ),
23500 mkU8( (3-i)*32 ) ),
23501 binop( Iop_64HLtoV128,
23502 mkU64( 0x0 ),
23503 mkU64( 0xFFFFFFFF ) ) ) ) ) );
23504 assign( B_value[i],
23505 unop( Iop_64to32,
23506 unop( Iop_V128to64,
23507 binop( Iop_AndV128,
23508 binop( Iop_ShrV128,
23509 mkexpr( vB ),
23510 mkU8( (3-i)*32 ) ),
23511 binop( Iop_64HLtoV128,
23512 mkU64( 0x0 ),
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] ),
23519 mkU32( 0xFF ) ),
23520 mkU8( 23 ) );
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],
23526 binop( Iop_OrV128,
23527 binop( Iop_ShlV128,
23528 binop( Iop_64HLtoV128,
23529 mkU64( 0 ),
23530 binop( Iop_32HLto64,
23531 mkU32( 0 ),
23532 binop( Iop_Or32,
23533 binop( Iop_Or32,
23534 sign[i],
23535 expr[i] ),
23536 fract[i] ) ) ),
23537 mkU8( (3-i)*32 ) ),
23538 mkexpr( new_XT[i] ) ) );
23540 putVSReg( XT, mkexpr( new_XT[4] ) );
23542 break;
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 ) ),
23559 mkU8( 52 ) );
23560 fract = binop( Iop_And64, mkexpr( rA ), mkU64( 0x000FFFFFFFFFFFFF ) );
23562 putVSReg( XT, binop( Iop_64HLtoV128,
23563 binop( Iop_Or64,
23564 binop( Iop_Or64, sign, expr ),
23565 fract ),
23566 mkU64( 0 ) ) );
23568 break;
23570 case 0x3B6: // xvxexpdp (VSX Vector Extract Exponent Double-Precision)
23571 // xvxsigdp (VSX Vector Extract Significand Double-Precision)
23572 // xxbrh
23573 // xvxexpsp (VSX Vector Extract Exponent Single-Precision)
23574 // xvxsigsp (VSX Vector Extract Significand Single-Precision)
23575 // xxbrw
23576 // xxbrd
23577 // xxbrq
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,
23590 mkexpr( vB ),
23591 binop( Iop_64HLtoV128,
23592 mkU64( 0x7FF0000000000000 ),
23593 mkU64( 0x7FF0000000000000 ) ) ),
23594 mkU8( 52 ) ) );
23596 } else if (inst_select == 1) {
23597 Int i;
23598 IRExpr *normal[2];
23599 IRTemp value[2];
23600 IRTemp new_XT[3];
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,
23605 mkU64( 0x0 ),
23606 mkU64( 0x0 ) ) );
23608 for (i = 0; i < 2; i++) {
23609 value[i] = newTemp(Ity_I64);
23610 assign( value[i],
23611 unop( Iop_V128to64,
23612 binop( Iop_AndV128,
23613 binop( Iop_ShrV128,
23614 mkexpr( vB ),
23615 mkU8( (1-i)*64 ) ),
23616 binop( Iop_64HLtoV128,
23617 mkU64( 0x0 ),
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,
23626 value[i] ) ) ) );
23627 new_XT[i+1] = newTemp(Ity_V128);
23629 assign( new_XT[i+1],
23630 binop( Iop_OrV128,
23631 binop( Iop_ShlV128,
23632 binop( Iop_64HLtoV128,
23633 mkU64( 0x0 ),
23634 binop( Iop_Or64,
23635 binop( Iop_And64,
23636 mkexpr( value[i] ),
23637 mkU64( 0xFFFFFFFFFFFFF ) ),
23638 binop( Iop_Shl64,
23639 unop( Iop_1Uto64,
23640 normal[i]),
23641 mkU8( 52 ) ) ) ),
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 ) ),
23659 mkexpr( vB ) ),
23660 mkU8( 8 ) ) );
23661 assign( sub_element1,
23662 binop( Iop_ShlV128,
23663 binop( Iop_AndV128,
23664 binop(Iop_64HLtoV128,
23665 mkU64( 0x00FF00FF00FF00FF ),
23666 mkU64( 0x00FF00FF00FF00FF ) ),
23667 mkexpr( vB ) ),
23668 mkU8( 8 ) ) );
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,
23679 mkexpr( vB ),
23680 binop( Iop_64HLtoV128,
23681 mkU64( 0x7F8000007F800000 ),
23682 mkU64( 0x7F8000007F800000 ) ) ),
23683 mkU8( 23 ) ) );
23684 } else if (inst_select == 9) {
23685 Int i;
23686 IRExpr *normal[4];
23687 IRTemp value[4];
23688 IRTemp new_value[4];
23689 IRTemp new_XT[5];
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,
23694 mkU64( 0x0 ),
23695 mkU64( 0x0 ) ) );
23697 for (i = 0; i < 4; i++) {
23698 value[i] = newTemp(Ity_I32);
23699 assign( value[i],
23700 unop( Iop_64to32,
23701 unop( Iop_V128to64,
23702 binop( Iop_AndV128,
23703 binop( Iop_ShrV128,
23704 mkexpr( vB ),
23705 mkU8( (3-i)*32 ) ),
23706 binop( Iop_64HLtoV128,
23707 mkU64( 0x0 ),
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,
23718 value[i] ) ) ) );
23719 new_value[i] = newTemp(Ity_I32);
23720 assign( new_value[i],
23721 binop( Iop_Or32,
23722 binop( Iop_And32,
23723 mkexpr( value[i] ),
23724 mkU32( 0x7FFFFF ) ),
23725 binop( Iop_Shl32,
23726 unop( Iop_1Uto32,
23727 normal[i]),
23728 mkU8( 23 ) ) ) );
23730 assign( new_XT[i+1],
23731 binop( Iop_OrV128,
23732 binop( Iop_ShlV128,
23733 binop( Iop_64HLtoV128,
23734 mkU64( 0x0 ),
23735 binop( Iop_32HLto64,
23736 mkU32( 0x0 ),
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 ) ),
23757 mkexpr( vB ) ),
23758 mkU8( 24 ) ) );
23759 assign( sub_element1,
23760 binop( Iop_ShrV128,
23761 binop( Iop_AndV128,
23762 binop(Iop_64HLtoV128,
23763 mkU64( 0x00FF000000FF0000 ),
23764 mkU64( 0x00FF000000FF0000 ) ),
23765 mkexpr( vB ) ),
23766 mkU8( 8 ) ) );
23767 assign( sub_element2,
23768 binop( Iop_ShlV128,
23769 binop( Iop_AndV128,
23770 binop(Iop_64HLtoV128,
23771 mkU64( 0x0000FF000000FF00 ),
23772 mkU64( 0x0000FF000000FF00 ) ),
23773 mkexpr( vB ) ),
23774 mkU8( 8 ) ) );
23775 assign( sub_element3,
23776 binop( Iop_ShlV128,
23777 binop( Iop_AndV128,
23778 binop(Iop_64HLtoV128,
23779 mkU64( 0x00000000FF000000FF ),
23780 mkU64( 0x00000000FF000000FF ) ),
23781 mkexpr( vB ) ),
23782 mkU8( 24 ) ) );
23784 putVSReg( XT,
23785 binop( Iop_OrV128,
23786 binop( Iop_OrV128,
23787 mkexpr( sub_element3 ),
23788 mkexpr( sub_element2 ) ),
23789 binop( Iop_OrV128,
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);
23814 int i;
23815 int shift = 56;
23816 IRTemp sub_element[16];
23817 IRTemp new_xT[17];
23819 new_xT[0] = newTemp( Ity_V128 );
23820 assign( new_xT[0], binop( Iop_64HLtoV128,
23821 mkU64( 0 ),
23822 mkU64( 0 ) ) );
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) ) ),
23835 mkexpr( vB ) ),
23836 mkU8( shift ) ) );
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) ) ),
23844 mkexpr( vB ) ),
23845 mkU8( shift ) ) );
23846 shift = shift - 16;
23848 assign( new_xT[i+1],
23849 binop( Iop_OrV128,
23850 mkexpr( new_xT[i] ),
23851 binop( Iop_OrV128,
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.
23879 assign( src,
23880 unop( Iop_V128to64,
23881 binop( Iop_Perm8x16,
23882 mkexpr( vB ),
23883 binop ( Iop_64HLtoV128,
23884 mkU64( 0 ),
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
23907 * of V128 result.
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
23912 * desired bytes.
23914 assign( result,
23915 binop( Iop_Perm8x16,
23916 binop( Iop_64HLtoV128,
23917 mkexpr( tmp64 ),
23918 mkU64( 0 ) ),
23919 binop ( Iop_64HLtoV128,
23920 mkU64( 0x0F0F00010F0F0203 ),
23921 mkU64( 0x0F0F04050F0F0607 ) ) ) );
23922 else
23923 assign( result,
23924 binop( Iop_Perm8x16,
23925 binop( Iop_64HLtoV128,
23926 mkexpr( tmp64 ),
23927 mkU64( 0 ) ),
23928 binop ( Iop_64HLtoV128,
23929 mkU64( 0x0F0F06070F0F0405 ),
23930 mkU64( 0x0F0F02030F0F0001 ) ) ) );
23931 putVSReg( XT, mkexpr( result ) );
23933 } else if ( inst_select == 31 ) {
23934 int i;
23935 int shift_left = 8;
23936 int shift_right = 120;
23937 IRTemp sub_element[16];
23938 IRTemp new_xT[9];
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,
23944 mkU64( 0 ),
23945 mkU64( 0 ) ) );
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 ) ),
23957 mkU64( 0x0ULL ) ),
23958 mkexpr( vB ) ),
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,
23966 mkU64( 0x0ULL ),
23967 mkU64( ( 0xFFULL << (7 - i) * 8 ) ) ),
23968 mkexpr( vB ) ),
23969 mkU8( shift_left ) ) );
23970 shift_left = shift_left + 16;
23972 assign( new_xT[i+1],
23973 binop( Iop_OrV128,
23974 mkexpr( new_xT[i] ),
23975 binop( Iop_OrV128,
23976 mkexpr ( sub_element[i] ),
23977 mkexpr ( sub_element[i+8] ) ) ) );
23980 putVSReg( XT, mkexpr( new_xT[8] ) );
23982 } else {
23983 vex_printf("dis_vxs_misc(ppc) Invalid instruction selection\n");
23984 return False;
23986 break;
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];
23998 IRTemp value[2];
23999 Int i;
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);
24014 assign( value[i],
24015 unop( Iop_V128to64,
24016 binop( Iop_AndV128,
24017 binop( Iop_ShrV128,
24018 mkexpr( vB ),
24019 mkU8( (1-i)*64 ) ),
24020 binop( Iop_64HLtoV128,
24021 mkU64( 0x0 ),
24022 mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ) );
24024 assign( pos[i], unop( Iop_1Uto64,
24025 binop( Iop_CmpEQ64,
24026 binop( Iop_Shr64,
24027 mkexpr( value[i] ),
24028 mkU8( 63 ) ),
24029 mkU64( 0 ) ) ) );
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,
24035 value[i] ) ) );
24037 assign( DCM[i], create_DCM( Ity_I64, NaN[i], inf[i], zero[i],
24038 dnorm[i], pos[i] ) );
24040 assign( match_value[i],
24041 unop( Iop_1Sto64,
24042 binop( Iop_CmpNE64,
24043 binop( Iop_And64,
24044 mkU64( DCMX_mask ),
24045 mkexpr( DCM[i] ) ),
24046 mkU64( 0 ) ) ) );
24048 putVSReg( XT, binop( Iop_64HLtoV128,
24049 mkexpr( match_value[0] ),
24050 mkexpr( match_value[1] ) ) );
24052 break;
24054 case 0x3E0: // xviexpdp (VSX Vector Insert Exponent Double-Precision)
24056 Int i;
24057 IRTemp new_XT[3];
24058 IRTemp A_value[2];
24059 IRTemp B_value[2];
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,
24065 mkU64( 0x0 ),
24066 mkU64( 0x0 ) ) );
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,
24076 mkexpr( vA ),
24077 mkU8( (1-i)*64 ) ),
24078 binop( Iop_64HLtoV128,
24079 mkU64( 0x0 ),
24080 mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ) );
24081 assign( B_value[i],
24082 unop( Iop_V128to64,
24083 binop( Iop_AndV128,
24084 binop( Iop_ShrV128,
24085 mkexpr( vB ),
24086 mkU8( (1-i)*64 ) ),
24087 binop( Iop_64HLtoV128,
24088 mkU64( 0x0 ),
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] ),
24095 mkU64( 0x7FF ) ),
24096 mkU8( 52 ) );
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],
24102 binop( Iop_OrV128,
24103 binop( Iop_ShlV128,
24104 binop( Iop_64HLtoV128,
24105 mkU64( 0 ),
24106 binop( Iop_Or64,
24107 binop( Iop_Or64,
24108 sign[i],
24109 expr[i] ),
24110 fract[i] ) ),
24111 mkU8( (1-i)*64 ) ),
24112 mkexpr( new_XT[i] ) ) );
24114 putVSReg( XT, mkexpr( new_XT[2] ) );
24116 break;
24118 default:
24119 vex_printf( "dis_vxs_misc(ppc)(opc2)\n" );
24120 return False;
24122 return True;
24126 * VSX vector miscellaneous instructions
24129 static Bool
24130 dis_vx_misc ( UInt prefix, UInt theInstr, UInt opc2 )
24132 /* XX3-Form */
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. */
24151 PREFIX_CHECK
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 ) ) );
24160 assign( nan_mask,
24161 binop( Iop_Or64,
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 ) );
24171 else
24172 assign( snan_mask,
24173 binop( Iop_Or64,
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 ) ) );
24181 switch (opc2) {
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
24186 double word 0 */
24188 /* result of Iop_CmpF64 is 0x40 if operands are equal,
24189 mask is all 1's if equal. */
24191 assign( cmp_mask,
24192 unop( Iop_1Sto64,
24193 unop(Iop_32to1,
24194 binop(Iop_Shr32,
24195 binop( Iop_CmpF64,
24196 unop( Iop_ReinterpI64asF64,
24197 mkexpr( src1 ) ),
24198 unop( Iop_ReinterpI64asF64,
24199 mkexpr( src2 ) ) ),
24200 mkU8( 6 ) ) ) ) );
24202 assign( word_result,
24203 binop( Iop_Or64,
24204 binop( Iop_And64, mkexpr( cmp_mask ),
24205 mkU64( 0xFFFFFFFFFFFFFFFF ) ),
24206 binop( Iop_And64,
24207 unop( Iop_Not64, mkexpr( cmp_mask ) ),
24208 mkU64( 0x0 ) ) ) );
24209 assign( nan_cmp_value, mkU64( 0 ) );
24210 break;
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. */
24219 assign( cmp_mask,
24220 unop( Iop_1Sto64,
24221 unop(Iop_32to1,
24222 binop(Iop_CmpF64,
24223 unop( Iop_ReinterpI64asF64,
24224 mkexpr( src2 ) ),
24225 unop( Iop_ReinterpI64asF64,
24226 mkexpr( src1 ) ) ) ) ) );
24227 assign( word_result,
24228 binop( Iop_Or64,
24229 binop( Iop_And64, mkexpr( cmp_mask ),
24230 mkU64( 0xFFFFFFFFFFFFFFFF ) ),
24231 binop( Iop_And64,
24232 unop( Iop_Not64, mkexpr( cmp_mask ) ),
24233 mkU64( 0x0 ) ) ) );
24234 assign( nan_cmp_value, mkU64( 0 ) );
24235 break;
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. */
24244 assign( cmp_mask,
24245 unop( Iop_1Sto64,
24246 unop(Iop_32to1,
24247 binop( Iop_Or32,
24248 binop( Iop_Shr32,
24249 binop(Iop_CmpF64, /* EQ test */
24250 unop( Iop_ReinterpI64asF64,
24251 mkexpr( src1 ) ),
24252 unop( Iop_ReinterpI64asF64,
24253 mkexpr( src2 ) ) ),
24254 mkU8( 6 ) ),
24255 binop(Iop_CmpF64, /* src2 < src 1 test */
24256 unop( Iop_ReinterpI64asF64,
24257 mkexpr( src2 ) ),
24258 unop( Iop_ReinterpI64asF64,
24259 mkexpr( src1 ) ) ) ) ) ) );
24260 assign( word_result,
24261 binop( Iop_Or64,
24262 binop( Iop_And64, mkexpr( cmp_mask ),
24263 mkU64( 0xFFFFFFFFFFFFFFFF ) ),
24264 binop( Iop_And64,
24265 unop( Iop_Not64, mkexpr( cmp_mask ) ),
24266 mkU64( 0x0 ) ) ) );
24267 assign( nan_cmp_value, mkU64( 0 ) );
24268 break;
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
24275 double word 0 */
24277 /* result of Iop_CmpF64 is 0x1 if arg1 LT then arg2, */
24278 assign( cmp_mask,
24279 unop( Iop_1Sto64,
24280 unop( Iop_32to1,
24281 binop(Iop_CmpF64,
24282 unop( Iop_ReinterpI64asF64,
24283 mkexpr( src2 ) ),
24284 unop( Iop_ReinterpI64asF64,
24285 mkexpr( src1 ) ) ) ) ) );
24286 assign( word_result,
24287 binop( Iop_Or64,
24288 binop( Iop_And64, mkexpr( cmp_mask ), mkexpr( src1 ) ),
24289 binop( Iop_And64,
24290 unop( Iop_Not64, mkexpr( cmp_mask ) ),
24291 mkexpr( src2 ) ) ) );
24292 assign( nan_cmp_value, mkexpr( src2 ) );
24293 break;
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
24300 double word 0 */
24302 /* result of Iop_CmpF64 is 0x1 if arg1 less then arg2, */
24303 assign( cmp_mask,
24304 unop( Iop_1Sto64,
24305 unop( Iop_32to1,
24306 binop(Iop_CmpF64,
24307 unop( Iop_ReinterpI64asF64,
24308 mkexpr( src1 ) ),
24309 unop( Iop_ReinterpI64asF64,
24310 mkexpr( src2 ) ) ) ) ) );
24311 assign( word_result,
24312 binop( Iop_Or64,
24313 binop( Iop_And64, mkexpr( cmp_mask ), mkexpr( src1 ) ),
24314 binop( Iop_And64,
24315 unop( Iop_Not64, mkexpr( cmp_mask ) ),
24316 mkexpr( src2 ) ) ) );
24317 assign( nan_cmp_value, mkexpr( src2 ) );
24318 break;
24321 default:
24322 vex_printf( "dis_vx_misc(ppc)(opc2)\n" );
24323 return False;
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,
24333 binop( Iop_Or64,
24334 binop( Iop_And64, mkexpr( snan_mask ),
24335 unop( Iop_V128HIto64, mkexpr( xT ) ) ),
24336 binop( Iop_And64, unop( Iop_Not64,
24337 mkexpr( snan_mask ) ),
24338 binop( Iop_Or64,
24339 binop( Iop_And64, mkexpr( nan_mask ),
24340 mkexpr( nan_cmp_value ) ),
24341 binop( Iop_And64,
24342 unop( Iop_Not64,
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
24348 case.
24350 putVSReg( XT,
24351 binop( Iop_64HLtoV128,
24352 binop( Iop_Or64,
24353 binop( Iop_And64,
24354 unop( Iop_Not64, mkexpr( result_mask ) ),
24355 mkexpr( word_result ) ),
24356 binop( Iop_And64,
24357 mkexpr( result_mask ),
24358 mkexpr( check_result ) ) ),
24359 mkU64( 0 ) ) );
24360 return True;
24364 * VSX Logical Instructions
24366 static Bool
24367 dis_vx_logic ( UInt prefix, UInt theInstr, UInt opc2 )
24369 /* XX3-Form */
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. */
24378 PREFIX_CHECK
24380 if (opc1 != 0x3C) {
24381 vex_printf( "dis_vx_logic(ppc)(instr)\n" );
24382 return False;
24385 assign( vA, getVSReg( XA ) );
24386 assign( vB, getVSReg( XB ) );
24388 switch (opc2) {
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 ) ) );
24392 break;
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 ) ) );
24396 break;
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 ) ) ) );
24401 break;
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 ) ) );
24405 break;
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 ) ) ) );
24410 break;
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,
24414 mkexpr( vA ),
24415 unop( Iop_NotV128, mkexpr( vB ) ) ) );
24416 break;
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 ) ) ) );
24422 break;
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 ) ) ) );
24428 break;
24429 default:
24430 vex_printf( "dis_vx_logic(ppc)(opc2)\n" );
24431 return False;
24433 return True;
24437 * VSX Load Instructions
24438 * NOTE: VSX supports word-aligned storage access.
24440 static Bool
24441 dis_vx_load ( UInt prefix, UInt theInstr )
24443 /* XX1-Form */
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. */
24454 PREFIX_CHECK
24456 if (opc1 != 0x1F) {
24457 vex_printf( "dis_vx_load(ppc)(instr)\n" );
24458 return False;
24461 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
24463 switch (opc2) {
24464 case 0x00C: // lxsiwzx (Load VSX Scalar as Integer Word and Zero Indexed)
24466 IRExpr * exp;
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 ) ) );
24471 else
24472 exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) );
24474 putVSReg( XT, binop( Iop_64HLtoV128,
24475 unop( Iop_32Uto64, exp),
24476 mkU64(0) ) );
24477 break;
24480 case 0x00D: // lxvrbx
24482 IRExpr * exp;
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,
24488 mkU64( 0x0 ),
24489 binop( Iop_And64, mkU64( 0xFF ), exp ) ) );
24490 else
24491 putVSReg( XT,
24492 binop( Iop_ShrV128,
24493 binop( Iop_64HLtoV128,
24494 mkU64( 0x0 ),
24495 binop( Iop_And64, mkU64( 0xFF ), exp ) ),
24496 mkU8( 15*8 ) ) ); // data is left most byte
24497 break;
24500 case 0x02D: // lxvrhx
24502 IRExpr * exp;
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,
24510 mkU64( 0x0 ),
24511 binop( Iop_And64, mkU64( 0xFFFF ), exp ) ) );
24512 else
24513 putVSReg( XT,
24514 binop( Iop_ShrV128,
24515 binop( Iop_64HLtoV128,
24516 mkU64( 0x0 ),
24517 binop( Iop_And64, mkU64( 0xFFFF ), exp ) ),
24518 mkU8( 7*16 ) ) ); // data is left most half-word
24519 break;
24522 case 0x04D: // lxvrwx
24524 IRExpr * exp;
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,
24532 mkU64( 0x0 ),
24533 binop( Iop_And64, mkU64( 0xFFFFFFFF ), exp ) ) );
24534 else
24535 putVSReg( XT,
24536 binop( Iop_ShrV128,
24537 binop( Iop_64HLtoV128,
24538 mkU64( 0x0 ),
24539 binop( Iop_And64,
24540 mkU64( 0xFFFFFFFF ), exp ) ),
24541 mkU8( 3*32 ) ) ); // data is left most word
24542 break;
24545 case 0x06D: // lxvrdx
24547 IRExpr * exp;
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,
24555 mkU64( 0x0 ),
24556 binop( Iop_And64,
24557 mkU64( 0xFFFFFFFFFFFFFFFFULL), exp ) ) );
24558 else
24559 putVSReg( XT,
24560 binop( Iop_ShrV128,
24561 binop( Iop_64HLtoV128,
24562 mkU64( 0x0 ),
24563 binop( Iop_And64,
24564 mkU64( 0xFFFFFFFFFFFFFFFFULL), exp ) ),
24565 mkU8( 1*64 ) ) ); // data is left most double word
24566 break;
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
24581 * store. */
24582 if (host_endness == VexEndnessLE) {
24583 store_exp = binop( Iop_Or64,
24584 binop( Iop_And64,
24585 mkU64( 0x00000000000000FF ),
24586 unop( Iop_V128to64, mkexpr( vS ) ) ),
24587 binop( Iop_And64,
24588 mkU64( 0xFFFFFFFFFFFFFF00 ),
24589 fetched_exp ) );
24590 store( mkexpr( EA ), store_exp );
24591 } else {
24592 store_exp = binop( Iop_Or64,
24593 binop( Iop_And64,
24594 mkU64( 0xFF00000000000000 ),
24595 unop( Iop_V128HIto64, mkexpr( vS ) ) ),
24596 binop( Iop_And64,
24597 mkU64( 0x00FFFFFFFFFFFFFF ),
24598 fetched_exp ) );
24599 store( mkexpr( EA ), store_exp );
24601 break;
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
24616 * store. */
24617 if (host_endness == VexEndnessLE) {
24618 store_exp = binop( Iop_Or64,
24619 binop( Iop_And64,
24620 mkU64( 0x000000000000FFFF ),
24621 unop( Iop_V128to64, mkexpr( vS ) ) ),
24622 binop( Iop_And64,
24623 mkU64( 0xFFFFFFFFFFFF0000 ),
24624 fetched_exp ) );
24625 store( mkexpr( EA ), store_exp );
24626 } else {
24627 store_exp = binop( Iop_Or64,
24628 binop( Iop_And64,
24629 mkU64( 0xFFFF000000000000 ),
24630 unop( Iop_V128HIto64, mkexpr( vS ) ) ),
24631 binop( Iop_And64,
24632 mkU64( 0x0000FFFFFFFFFFFF ),
24633 fetched_exp ) );
24634 store( mkexpr( EA ), store_exp );
24636 break;
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
24651 * store. */
24652 if (host_endness == VexEndnessLE) {
24653 store_exp = binop( Iop_Or64,
24654 binop( Iop_And64,
24655 mkU64( 0x00000000FFFFFFFF ),
24656 unop( Iop_V128to64, mkexpr( vS ) ) ),
24657 binop( Iop_And64,
24658 mkU64( 0xFFFFFFFF00000000 ),
24659 fetched_exp ) );
24660 store( mkexpr( EA ), store_exp );
24661 } else {
24662 store_exp = binop( Iop_Or64,
24663 binop( Iop_And64,
24664 mkU64( 0xFFFFFFFF00000000 ),
24665 unop( Iop_V128HIto64, mkexpr( vS ) ) ),
24666 binop( Iop_And64,
24667 mkU64( 0x00000000FFFFFFFF ),
24668 fetched_exp ) );
24669 store( mkexpr( EA ), store_exp );
24671 break;
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 );
24690 } else {
24691 store_exp = binop( Iop_And64,
24692 mkU64( 0xFFFFFFFFFFFFFFFF ),
24693 unop( Iop_V128HIto64, mkexpr( vS ) ) );
24694 store( mkexpr( EA ), store_exp );
24696 break;
24699 case 0x04C: // lxsiwax (Load VSX Scalar as Integer Word Algebraic Indexed)
24701 IRExpr * exp;
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 ) ) );
24706 else
24707 exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) );
24709 putVSReg( XT, binop( Iop_64HLtoV128,
24710 unop( Iop_32Sto64, exp),
24711 mkU64(0) ) );
24712 break;
24714 case 0x10C: // lxvx
24716 UInt ea_off = 0;
24717 IRExpr* irx_addr;
24718 IRTemp word[4];
24719 int i;
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 );
24727 irx_addr =
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 ) ) );
24733 ea_off += 4;
24736 putVSReg( XT, binop( Iop_64HLtoV128,
24737 binop( Iop_Or64,
24738 mkexpr( word[2] ),
24739 binop( Iop_Shl64,
24740 mkexpr( word[3] ),
24741 mkU8( 32 ) ) ),
24742 binop( Iop_Or64,
24743 mkexpr( word[0] ),
24744 binop( Iop_Shl64,
24745 mkexpr( word[1] ),
24746 mkU8( 32 ) ) ) ) );
24747 } else {
24748 for ( i = 0; i< 4; i++ ) {
24749 word[i] = newTemp( Ity_I64 );
24751 irx_addr =
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 ) ) );
24757 ea_off += 4;
24760 putVSReg( XT, binop( Iop_64HLtoV128,
24761 binop( Iop_Or64,
24762 mkexpr( word[2] ),
24763 binop( Iop_Shl64,
24764 mkexpr( word[3] ),
24765 mkU8( 32 ) ) ),
24766 binop( Iop_Or64,
24767 mkexpr( word[0] ),
24768 binop( Iop_Shl64,
24769 mkexpr( word[1] ),
24770 mkU8( 32 ) ) ) ) );
24772 break;
24775 case 0x10D: // lxvl
24777 DIP("lxvl %u,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
24779 IRTemp byte[16];
24780 UInt i;
24781 UInt ea_off = 0;
24782 IRExpr* irx_addr;
24783 IRTemp tmp_low[9];
24784 IRTemp tmp_hi[9];
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,
24802 mkU64( 0 ),
24803 binop( Iop_Shr64,
24804 getIReg( rB_addr ),
24805 mkU8( 56 ) ) ) ) );
24807 assign( nb_gt16, unop( Iop_1Sto8,
24808 binop( Iop_CmpLT64U,
24809 binop( Iop_Shr64,
24810 getIReg( rB_addr ),
24811 mkU8( 60 ) ),
24812 mkU64( 1 ) ) ) );
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.
24817 assign( shift,
24818 binop( Iop_And8,
24819 unop( Iop_64to8,
24820 binop( Iop_Mul64,
24821 binop( Iop_Sub64,
24822 mkU64 ( 16 ),
24823 binop( Iop_Shr64,
24824 getIReg( rB_addr ),
24825 mkU8( 56 ) ) ),
24826 mkU64( 8 ) ) ),
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 );
24835 irx_addr =
24836 binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
24837 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
24838 ea_off += 1;
24840 assign( byte[i], binop( Iop_Shl64,
24841 unop( Iop_8Uto64,
24842 load( Ity_I8, irx_addr ) ),
24843 mkU8( 8 * ( 7 - i ) ) ) );
24845 assign( tmp_hi[i+1], binop( Iop_Or64,
24846 mkexpr( byte[i] ),
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 );
24854 irx_addr =
24855 binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
24856 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
24857 ea_off += 1;
24859 assign( byte[i+8], binop( Iop_Shl64,
24860 unop( Iop_8Uto64,
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] ) ),
24873 mkexpr( shift ) ),
24874 mkexpr( shift ) ) );
24875 } else {
24876 for ( i = 0; i < 8; i++ ) {
24877 byte[i] = newTemp( Ity_I64 );
24878 tmp_low[i+1] = newTemp( Ity_I64 );
24880 irx_addr =
24881 binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
24882 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
24883 ea_off += 1;
24885 assign( byte[i], binop( Iop_Shl64,
24886 unop( Iop_8Uto64,
24887 load( Ity_I8, irx_addr ) ),
24888 mkU8( 8 * i ) ) );
24890 assign( tmp_low[i+1],
24891 binop( Iop_Or64,
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 );
24899 irx_addr =
24900 binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
24901 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
24902 ea_off += 1;
24904 assign( byte[i+8], binop( Iop_Shl64,
24905 unop( Iop_8Uto64,
24906 load( Ity_I8, irx_addr ) ),
24907 mkU8( 8 * i ) ) );
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] ) ),
24918 mkexpr( shift ) ),
24919 mkexpr( shift ) ) );
24923 /* If nb = 0, mask out the calculated load result so the stored
24924 * value is zero.
24927 putVSReg( XT, binop( Iop_AndV128,
24928 mkexpr( ld_result ),
24929 binop( Iop_64HLtoV128,
24930 mkexpr( nb_not_zero ),
24931 mkexpr( nb_not_zero ) ) ) );
24932 break;
24935 case 0x12D: // lxvll (Load VSX Vector Left-Justified with Length XX1 form)
24937 IRTemp byte[16];
24938 IRTemp tmp_low[9];
24939 IRTemp tmp_hi[9];
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);
24945 Int i;
24946 UInt ea_off = 0;
24947 IRExpr* irx_addr;
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,
24966 mkexpr( nb ),
24967 mkU64( 0 ) ) ) );
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,
24975 mkU64( 16*8 ),
24976 binop( Iop_Mul64,
24977 mkexpr( nb ),
24978 mkU64( 8 ) ) ) );
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 ) );
24987 ea_off += 1;
24989 /* Instruction always loads in Big Endian format */
24990 assign( byte[i], binop( Iop_Shl64,
24991 unop( Iop_8Uto64,
24992 load( Ity_I8, irx_addr ) ),
24993 mkU8( 8 * (7 - i) ) ) );
24994 assign( tmp_hi[i+1],
24995 binop( Iop_Or64,
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 ) );
25005 ea_off += 1;
25007 /* Instruction always loads in Big Endian format */
25008 assign( byte[i+8], binop( Iop_Shl64,
25009 unop( Iop_8Uto64,
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
25018 * if nb= 0.
25020 assign( mask, binop( Iop_AndV128,
25021 binop( Iop_ShlV128,
25022 binop( Iop_ShrV128,
25023 mkV128( 0xFFFF ),
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,
25029 mkexpr( mask ),
25030 binop( Iop_64HLtoV128,
25031 mkexpr( tmp_hi[8] ),
25032 mkexpr( tmp_low[8] ) ) ) );
25033 break;
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 ) {
25045 UInt ea_off = 4;
25046 IRExpr* irx_addr;
25048 irx_addr =
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 ) ) );
25056 } else {
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 */
25063 putVSReg( XT,
25064 binop( Iop_64HLtoV128,
25065 binop( Iop_Or64,
25066 mkexpr( data ),
25067 binop( Iop_Shl64,
25068 mkexpr( data ),
25069 mkU8( 32 ) ) ),
25070 binop( Iop_Or64,
25071 mkexpr( data ),
25072 binop( Iop_Shl64,
25073 mkexpr( data ),
25074 mkU8( 32 ) ) ) ) );
25075 break;
25078 case 0x20C: // lxsspx (Load VSX Scalar Single-Precision Indexed)
25080 IRExpr * exp;
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 ) ) );
25092 break;
25094 case 0x24C: // lxsdx
25096 IRExpr * exp;
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 ) );
25103 break;
25106 case 0x30D: // lxsibzx
25108 IRExpr *byte;
25109 IRExpr* irx_addr;
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 ) );
25116 else
25117 irx_addr = mkexpr( EA );
25118 /* byte load */
25119 byte = load( Ity_I8, irx_addr );
25120 putVSReg( XT, binop( Iop_64HLtoV128,
25121 unop( Iop_8Uto64, byte ),
25122 mkU64( 0 ) ) );
25123 break;
25126 case 0x32D: // lxsihzx
25128 IRExpr *hword;
25129 IRExpr* irx_addr;
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 ) );
25136 else
25137 irx_addr = mkexpr( EA );
25139 hword = load( Ity_I16, irx_addr );
25140 putVSReg( XT, binop( Iop_64HLtoV128,
25141 unop( Iop_16Uto64,
25142 hword ),
25143 mkU64( 0 ) ) );
25144 break;
25146 case 0x34C: // lxvd2x
25148 IRExpr *t128;
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 );
25164 break;
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 ) ) );
25172 break;
25174 case 0x30C:
25176 IRExpr *t0;
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) {
25182 IRExpr *t0_BE;
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) );
25192 } else {
25193 t0 = load( Ity_V128, mkexpr( EA ) );
25196 putVSReg( XT, t0 );
25197 break;
25200 case 0x32C: // lxvh8x
25202 DIP("lxvh8x %u,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
25204 IRTemp h_word[8];
25205 int i;
25206 UInt ea_off = 0;
25207 IRExpr* irx_addr;
25208 IRTemp tmp_low[5];
25209 IRTemp tmp_hi[5];
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 ) );
25222 ea_off += 2;
25224 assign( h_word[i], binop( Iop_Shl64,
25225 unop( Iop_16Uto64,
25226 load( Ity_I16, irx_addr ) ),
25227 mkU8( 16 * ( 3 - i ) ) ) );
25229 assign( tmp_low[i+1],
25230 binop( Iop_Or64,
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 ) );
25240 ea_off += 2;
25242 assign( h_word[i+4], binop( Iop_Shl64,
25243 unop( Iop_16Uto64,
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] ) ) );
25253 break;
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) );
25279 else
25280 t128 = binop( Iop_64HLtoV128, mkexpr (high_rev), mkexpr (low_rev) );
25282 putVSReg( XT, t128 );
25283 break;
25286 default:
25287 vex_printf( "dis_vx_load(ppc)(opc2)\n" );
25288 return False;
25290 return True;
25294 * VSX Move Instructions
25296 static Bool
25297 dis_vx_move ( UInt prefix, UInt theInstr )
25299 /* XX1-Form */
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. */
25309 PREFIX_CHECK
25311 if ( opc1 != 0x1F ) {
25312 vex_printf( "dis_vx_move(ppc)(instr)\n" );
25313 return False;
25316 switch (opc2) {
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) ) );
25323 break;
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,
25334 mkexpr( tmp ),
25335 mkexpr( tmp ) ),
25336 binop( Iop_32HLto64,
25337 mkexpr( tmp ),
25338 mkexpr( tmp ) ) ) );
25339 putVSReg( XS, mkexpr( vS ) );
25341 break;
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 ) );
25352 else
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 ) );
25359 break;
25361 default:
25362 vex_printf( "dis_vx_move(ppc)(opc2)\n" );
25363 return False;
25365 return True;
25369 * VSX Store Instructions
25370 * NOTE: VSX supports word-aligned storage access.
25372 static Bool
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 ) ) );
25389 switch (opc2) {
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 ) ) );
25395 } else {
25396 putVSReg( XTp+1, load( Ity_V128, mkexpr( EA ) ) );
25397 putVSReg( XTp, load( Ity_V128, mkexpr( EA_16 ) ) );
25399 break;
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 ) ) );
25416 } else {
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 ) ) );
25422 break;
25425 default:
25426 vex_printf("dis_vsx_vector_paired_load_store\n");
25427 return False;
25430 return True;
25433 static Bool
25434 dis_vx_store ( UInt prefix, UInt theInstr )
25436 /* XX1-Form */
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. */
25448 PREFIX_CHECK
25450 if (opc1 != 0x1F) {
25451 vex_printf( "dis_vx_store(ppc)(instr)\n" );
25452 return False;
25455 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
25456 assign( vS, getVSReg( XS ) );
25458 switch (opc2) {
25459 case 0x08C:
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 );
25469 break;
25472 case 0x18C: // stxvx Store VSX Vector Indexed
25474 UInt ea_off = 0;
25475 IRExpr* irx_addr;
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 ) ),
25484 mkU8( 32 ) ) );
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 ) ),
25492 mkU8( 32 ) ) );
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 ) ) );
25501 ea_off += 4;
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 ) ) );
25507 ea_off += 4;
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 ) ) );
25512 ea_off += 4;
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 ) ) );
25517 } else {
25518 store( mkexpr( EA ), unop( Iop_64to32, mkexpr( word3 ) ) );
25520 ea_off += 4;
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 ) ) );
25526 ea_off += 4;
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 ) ) );
25531 ea_off += 4;
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 ) ) );
25537 break;
25540 case 0x18D: // stxvl Store VSX Vector Indexed
25542 UInt ea_off = 0;
25543 IRExpr* irx_addr;
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,
25562 getIReg(rB_addr),
25563 mkU8( 56 ) ) );
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,
25570 binop( Iop_Shr64,
25571 mkexpr( nb_field ),
25572 mkU8( 4 ) ),
25573 mkU64( 1 ) ) ) );
25575 /* nb_zero is 0xFF..FF if the nb_field = 0 */
25576 assign( nb_zero, binop( Iop_64HLtoV128,
25577 unop( Iop_1Sto64,
25578 binop( Iop_CmpEQ64,
25579 mkexpr( nb_field ),
25580 mkU64( 0 ) ) ),
25581 unop( Iop_1Sto64,
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,
25589 binop( Iop_Mul64,
25590 binop( Iop_Sub64,
25591 mkU64( 16 ),
25592 unop( Iop_8Uto64,
25593 mkexpr( n_bytes ) ) ),
25594 mkU64( 8 ) ) ) );
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
25599 * addressed by nb.
25601 assign( base_addr, ea_rAor0( rA_addr ) );
25603 assign( current_mem,
25604 binop( Iop_64HLtoV128,
25605 load( Ity_I64,
25606 binop( mkSzOp( ty, Iop_Add8 ),
25607 mkexpr( base_addr ),
25608 ty == Ity_I64 ? mkU64( 8 ) : mkU32( 8 )
25609 ) ),
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.
25619 assign( nb_mask,
25620 binop( Iop_OrV128,
25621 binop( Iop_AndV128,
25622 mkexpr( nb_zero ),
25623 mkV128( 0 ) ),
25624 binop( Iop_AndV128,
25625 binop( Iop_ShrV128,
25626 mkV128( 0xFFFF ),
25627 mkexpr( shift ) ),
25628 unop( Iop_NotV128, mkexpr( nb_zero ) ) ) ) );
25630 assign( store_val,
25631 binop( Iop_OrV128,
25632 binop( Iop_AndV128,
25633 mkexpr( vS ),
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 ) ),
25642 mkU8( 32 ) ) );
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 ) ),
25650 mkU8( 32 ) ) );
25652 assign( word3, binop( Iop_And64,
25653 unop( Iop_V128to64, mkexpr( store_val ) ),
25654 mkU64( 0xFFFFFFFF ) ) );
25656 ea_off = 0;
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 ) ) );
25662 ea_off += 4;
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 ) ) );
25668 ea_off += 4;
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 ) ) );
25674 ea_off += 4;
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 ) ) );
25679 break;
25682 case 0x1AD: // stxvll (Store VSX Vector Left-justified with length XX1-form)
25684 UInt ea_off = 0;
25685 IRExpr* irx_addr;
25686 IRTemp word0[5];
25687 IRTemp word1[5];
25688 IRTemp word2[5];
25689 IRTemp word3[5];
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 );
25701 IRTemp byte[16];
25702 IRTemp tmp_low[9];
25703 IRTemp tmp_hi[9];
25704 IRTemp nb_field_compare_zero = newTemp( Ity_I64 );
25705 Int i;
25707 DIP("stxvll %u,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
25709 assign( nb_field, binop( Iop_Shr64,
25710 getIReg(rB_addr),
25711 mkU8( 56 ) ) );
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,
25718 binop( Iop_Shr64,
25719 mkexpr( nb_field ),
25720 mkU8( 4 ) ),
25721 mkU64( 1 ) ) ) );
25723 assign( nb_field_compare_zero, unop( Iop_1Sto64,
25724 binop( Iop_CmpEQ64,
25725 mkexpr( nb_field ),
25726 mkU64( 0 ) ) ) );
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 ) ) );
25736 assign( shift,
25737 unop( Iop_64to8,
25738 binop( Iop_Mul64,
25739 binop( Iop_Sub64,
25740 mkU64( 16 ),
25741 unop( Iop_8Uto64, mkexpr( n_bytes ) )),
25742 mkU64( 8 ) ) ) );
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
25747 * addressed by nb.
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 ) );
25768 ea_off += 1;
25770 /* Instruction always loads in Big Endian format */
25771 assign( word0[i+1],
25772 binop( Iop_Or64,
25773 binop( Iop_Shl64,
25774 unop( Iop_8Uto64,
25775 load( Ity_I8,
25776 irx_addr ) ),
25777 mkU8( (3-i)*8 ) ),
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 ) );
25786 ea_off += 1;
25788 /* Instruction always loads in Big Endian format */
25789 assign( word1[i+1],
25790 binop( Iop_Or64,
25791 binop( Iop_Shl64,
25792 unop( Iop_8Uto64,
25793 load( Ity_I8,
25794 irx_addr ) ),
25795 mkU8( (3-i)*8 ) ),
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 ) );
25803 ea_off += 1;
25805 /* Instruction always loads in Big Endian format */
25806 assign( word2[i+1],
25807 binop( Iop_Or64,
25808 binop( Iop_Shl64,
25809 unop( Iop_8Uto64,
25810 load( Ity_I8,
25811 irx_addr ) ),
25812 mkU8( (3-i)*8 ) ),
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 ) );
25820 ea_off += 1;
25822 /* Instruction always loads in Big Endian format */
25823 assign( word3[i+1],
25824 binop( Iop_Or64,
25825 binop( Iop_Shl64,
25826 unop( Iop_8Uto64,
25827 load( Ity_I8,
25828 irx_addr ) ),
25829 mkU8( (3-i)*8 ) ),
25830 mkexpr( word3[i] ) ) );
25834 assign( current_mem,
25835 binop( Iop_64HLtoV128,
25836 binop( Iop_Or64,
25837 binop( Iop_Shl64,
25838 mkexpr( word0[4] ),
25839 mkU8( 32 ) ),
25840 mkexpr( word1[4] ) ),
25841 binop( Iop_Or64,
25842 binop( Iop_Shl64,
25843 mkexpr( word2[4] ),
25844 mkU8( 32 ) ),
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 */
25855 assign( nb_mask,
25856 binop( Iop_OrV128,
25857 binop( Iop_AndV128,
25858 binop( Iop_ShlV128,
25859 binop( Iop_ShrV128,
25860 binop( Iop_64HLtoV128,
25861 mkexpr( mask ),
25862 mkexpr( mask ) ),
25863 mkexpr( shift ) ),
25864 mkexpr( shift ) ),
25865 unop( Iop_NotV128, mkexpr( nb_zero ) ) ),
25866 binop( Iop_AndV128,
25867 mkexpr( nb_zero ),
25868 binop( Iop_64HLtoV128,
25869 mkU64( 0x0 ),
25870 mkU64( 0x0 ) ) ) ) );
25872 assign( store_val,
25873 binop( Iop_OrV128,
25874 binop( Iop_AndV128,
25875 mkexpr( vS ),
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,
25894 binop( Iop_Shr64,
25895 unop( Iop_V128HIto64,
25896 mkexpr( store_val ) ),
25897 mkU8( (7-i)*8 ) ),
25898 mkU64( 0xFF ) ) );
25899 assign( byte[i+8], binop( Iop_And64,
25900 binop( Iop_Shr64,
25901 unop( Iop_V128to64,
25902 mkexpr( store_val ) ),
25903 mkU8( (7-i)*8 ) ),
25904 mkU64( 0xFF ) ) );
25906 assign( tmp_low[i+1],
25907 binop( Iop_Or64,
25908 mkexpr( tmp_low[i] ),
25909 binop( Iop_Shl64, mkexpr( byte[i] ), mkU8( i*8 ) ) ) );
25910 assign( tmp_hi[i+1],
25911 binop( Iop_Or64,
25912 mkexpr( tmp_hi[i] ),
25913 binop( Iop_Shl64, mkexpr( byte[i+8] ),
25914 mkU8( i*8 ) ) ) );
25917 /* Store the value in 32-byte chunks */
25918 ea_off = 0;
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] ) ) );
25924 ea_off += 4;
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] ) ) );
25930 ea_off += 4;
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] ) ) );
25936 ea_off += 4;
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] ) ) );
25942 break;
25945 case 0x28C:
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 ) );
25956 break;
25958 case 0x2CC:
25960 IRExpr * high64;
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 );
25964 break;
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 ) );
25978 break;
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 ) );
25992 break;
25995 case 0x3CC:
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 );
26004 break;
26006 case 0x38C:
26008 UInt ea_off = 0;
26009 IRExpr* irx_addr;
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 ) ) );
26020 ea_off += 4;
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 ) ) );
26024 ea_off += 4;
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 ) ) );
26028 ea_off += 4;
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 ) ) );
26033 break;
26035 case 0x3AC: // stxvh8x Store VSX Vector Halfword*8 Indexed
26037 UInt ea_off = 0;
26038 IRExpr* irx_addr;
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 ) ),
26052 mkU8( 48 ) ) );
26054 assign( half_word1, binop( Iop_And64,
26055 binop( Iop_Shr64,
26056 unop( Iop_V128HIto64, mkexpr( vS ) ),
26057 mkU8( 32 ) ),
26058 mkU64( 0xFFFF ) ) );
26060 assign( half_word2, binop( Iop_And64,
26061 binop( Iop_Shr64,
26062 unop( Iop_V128HIto64, mkexpr( vS ) ),
26063 mkU8( 16 ) ),
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 ) ),
26072 mkU8( 48 ) ) );
26074 assign( half_word5, binop( Iop_And64,
26075 binop( Iop_Shr64,
26076 unop( Iop_V128to64, mkexpr( vS ) ),
26077 mkU8( 32 ) ),
26078 mkU64( 0xFFFF ) ) );
26080 assign( half_word6, binop( Iop_And64,
26081 binop( Iop_Shr64,
26082 unop( Iop_V128to64, mkexpr( vS ) ),
26083 mkU8( 16 ) ),
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,
26093 binop( Iop_Or64,
26094 mkexpr( half_word1 ),
26095 binop( Iop_Shl64,
26096 mkexpr( half_word0 ),
26097 mkU8( 16 ) ) ) ) );
26099 ea_off += 4;
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,
26105 binop( Iop_Or64,
26106 mkexpr( half_word3 ),
26107 binop( Iop_Shl64,
26108 mkexpr( half_word2 ),
26109 mkU8( 16 ) ) ) ) );
26111 ea_off += 4;
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,
26116 binop( Iop_Or64,
26117 mkexpr( half_word5 ),
26118 binop( Iop_Shl64,
26119 mkexpr( half_word4 ),
26120 mkU8( 16 ) ) ) ) );
26121 ea_off += 4;
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,
26126 binop( Iop_Or64,
26127 mkexpr( half_word7 ),
26128 binop( Iop_Shl64,
26129 mkexpr( half_word6 ),
26130 mkU8( 16 ) ) ) ) );
26132 } else {
26133 store( mkexpr( EA ), unop( Iop_64to32,
26134 binop( Iop_Or64,
26135 mkexpr( half_word0 ),
26136 binop( Iop_Shl64,
26137 mkexpr( half_word1 ),
26138 mkU8( 16 ) ) ) ) );
26140 ea_off += 4;
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,
26145 binop( Iop_Or64,
26146 mkexpr( half_word2 ),
26147 binop( Iop_Shl64,
26148 mkexpr( half_word3 ),
26149 mkU8( 16 ) ) ) ) );
26150 ea_off += 4;
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,
26155 binop( Iop_Or64,
26156 mkexpr( half_word4 ),
26157 binop( Iop_Shl64,
26158 mkexpr( half_word5 ),
26159 mkU8( 16 ) ) ) ) );
26160 ea_off += 4;
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,
26165 binop( Iop_Or64,
26166 mkexpr( half_word6 ),
26167 binop( Iop_Shl64,
26168 mkexpr( half_word7 ),
26169 mkU8( 16 ) ) ) ) );
26171 break;
26174 case 0x3EC: // stxvb16x Store VSX Vector Byte*16 Indexed
26176 UInt ea_off = 0;
26177 int i;
26178 IRExpr* irx_addr;
26179 IRTemp byte[16];
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,
26188 binop( Iop_Shr64,
26189 unop( Iop_V128HIto64, mkexpr( vS ) ),
26190 mkU8( 56 - i*8 ) ),
26191 mkU64( 0xFF ) ) );
26193 assign( byte[i+8], binop( Iop_And64,
26194 binop( Iop_Shr64,
26195 unop( Iop_V128to64, mkexpr( vS ) ),
26196 mkU8( 56 - i*8) ),
26197 mkU64( 0xFF ) ) );
26200 if ( host_endness == VexEndnessBE ) {
26201 for ( i = 0; i < 16; i = i + 4) {
26202 irx_addr =
26203 binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
26204 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
26206 store( irx_addr,
26207 unop( Iop_64to32,
26208 binop( Iop_Or64,
26209 binop( Iop_Or64,
26210 mkexpr( byte[i+3] ),
26211 binop( Iop_Shl64,
26212 mkexpr( byte[i+2] ),
26213 mkU8( 8 ) ) ),
26214 binop( Iop_Or64,
26215 binop( Iop_Shl64,
26216 mkexpr( byte[i+1] ),
26217 mkU8( 16 ) ),
26218 binop( Iop_Shl64,
26219 mkexpr( byte[i] ),
26220 mkU8( 24 ) ) ) ) ) );
26221 ea_off += 4;
26224 } else {
26225 for ( i = 0; i < 16; i = i + 4) {
26226 irx_addr =
26227 binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
26228 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
26230 store( irx_addr,
26231 unop( Iop_64to32,
26232 binop( Iop_Or64,
26233 binop( Iop_Or64,
26234 mkexpr( byte[i] ),
26235 binop( Iop_Shl64,
26236 mkexpr( byte[i+1] ),
26237 mkU8( 8 ) ) ),
26238 binop( Iop_Or64,
26239 binop( Iop_Shl64,
26240 mkexpr( byte[i+2] ),
26241 mkU8( 16 ) ),
26242 binop( Iop_Shl64,
26243 mkexpr( byte[i+3] ),
26244 mkU8( 24 ) ) ) ) ) );
26246 ea_off += 4;
26249 break;
26252 default:
26253 vex_printf( "dis_vx_store(ppc)(opc2)\n" );
26254 return False;
26256 return True;
26259 static Bool
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
26265 * instruction set.
26267 /* XX1-Form */
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. */
26277 PREFIX_CHECK
26279 assign( vB, getF128Reg( vB_addr ) );
26280 if (opc1 != 0x3F) {
26281 vex_printf( "dis_vx_Scalar_Round_to_quad_integer(ppc)(instr)\n" );
26282 return False;
26284 switch (opc2) {
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 );
26304 } /* case 0x005 */
26305 break;
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 );
26320 } /* case 0x025 */
26321 break;
26322 default:
26323 vex_printf( "dis_vx_Scalar_Round_to_quad_integer(ppc)(opc2)\n" );
26324 return False;
26325 } /* switch opc2 */
26326 putF128Reg( vT_addr, mkexpr( vT ) );
26327 return True;
26330 static Bool
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
26336 * instruction set.
26338 /* XX1-Form */
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. */
26351 PREFIX_CHECK
26353 assign( vB, getF128Reg( vB_addr ) );
26355 if ( opc1 != 0x3F ) {
26356 vex_printf( "Erorr, dis_vx_Floating_Point_Arithmetic_quad_precision(ppc)(instr)\n" );
26357 return False;
26359 switch ( opc2 ) {
26360 case 0x004: // xsaddqp (VSX Scalar Add Quad-Precision[using round to Odd])
26362 assign( vA, getF128Reg( vA_addr ) );
26364 if ( R0 == 0 ) {
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 ) ) );
26369 } else {
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 );
26376 break;
26378 case 0x024: // xsmulqp (VSX Scalar Multiply Quad-Precision[using round to Odd])
26380 assign( vA, getF128Reg( vA_addr ) );
26382 if ( R0 == 0 ) {
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 ) ) );
26387 } else {
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 ),
26391 mkexpr( vB ) ) );
26393 generate_store_FPRF( Ity_F128, vT, vbi );
26394 break;
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 ) );
26404 if ( R0 == 0 ) {
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);
26407 assign( vT,
26408 qop( Iop_MAddF128, rm, mkexpr( vA ),
26409 mkexpr( vC ), mkexpr( vB ) ) );
26411 } else {
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);
26414 assign( vT,
26415 qop( Iop_MAddF128, set_round_to_Oddmode(), mkexpr( vA ),
26416 mkexpr( vC ), mkexpr( vB ) ) );
26418 generate_store_FPRF( Ity_F128, vT, vbi );
26419 break;
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 ) );
26428 if ( R0 == 0 ) {
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);
26431 assign( vT,
26432 qop( Iop_MSubF128, rm, mkexpr( vA ),
26433 mkexpr( vC ), mkexpr( vB ) ) );
26435 } else {
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);
26438 assign( vT,
26439 qop( Iop_MSubF128, set_round_to_Oddmode(),
26440 mkexpr( vA ), mkexpr( vC ), mkexpr( vB ) ) );
26442 generate_store_FPRF( Ity_F128, vT, vbi );
26443 break;
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 ) );
26452 if ( R0 == 0 ) {
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);
26455 assign( vT,
26456 qop( Iop_NegMAddF128, rm, mkexpr( vA ),
26457 mkexpr( vC ), mkexpr( vB ) ) );
26459 } else {
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);
26462 assign( vT,
26463 qop( Iop_NegMAddF128, set_round_to_Oddmode(),
26464 mkexpr( vA ), mkexpr( vC ), mkexpr( vB ) ) );
26466 generate_store_FPRF( Ity_F128, vT, vbi );
26467 break;
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 ) );
26476 if ( R0 == 0 ) {
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);
26479 assign( vT,
26480 qop( Iop_NegMSubF128, rm, mkexpr( vA ),
26481 mkexpr( vC ), mkexpr( vB ) ) );
26483 } else {
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);
26486 assign( vT,
26487 qop( Iop_NegMSubF128, set_round_to_Oddmode(),
26488 mkexpr( vA ), mkexpr( vC ), mkexpr( vB ) ) );
26490 generate_store_FPRF( Ity_F128, vT, vbi );
26491 break;
26493 case 0x204: // xssubqp (VSX Scalar Subtract Quad-Precision[using round to Odd])
26495 assign( vA, getF128Reg( vA_addr ) );
26496 if ( R0 == 0 ) {
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 ) ) );
26501 } else {
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 ),
26505 mkexpr( vB ) ) );
26507 generate_store_FPRF( Ity_F128, vT, vbi );
26508 break;
26510 case 0x224: // xsdivqp (VSX Scalar Divide Quad-Precision[using round to Odd])
26512 assign( vA, getF128Reg( vA_addr ) );
26513 if ( R0 == 0 ) {
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 ) ) );
26518 } else {
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 ),
26522 mkexpr( vB ) ) );
26524 generate_store_FPRF( Ity_F128, vT, vbi );
26525 break;
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) {
26532 case 27:
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(),
26543 mkexpr( vB ) ) );
26545 generate_store_FPRF( Ity_F128, vT, vbi );
26546 break;
26547 } /* end case 27 */
26548 default:
26549 vex_printf("dis_vx_Floating_Point_Arithmetic_quad_precision(0x324 unknown inst_select)\n");
26550 return False;
26551 } /* end switch inst_select */
26552 break;
26553 } /* end case 0x324 */
26555 case 0x344:
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 ) ) );
26565 break;
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 ) ) );
26572 break;
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 );
26584 break;
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);
26590 assign( vT,
26591 binop( Iop_I128UtoF128, rm,
26592 unop ( Iop_ReinterpF128asI128,
26593 getF128Reg( vB_addr ) ) ) );
26594 generate_store_FPRF( Ity_F128, vT, vbi );
26595 break;
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 ) ) );
26602 break;
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 ) ) );
26609 break;
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 );
26622 break;
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);
26628 assign( vT,
26629 binop( Iop_I128StoF128, rm,
26630 unop ( Iop_ReinterpF128asI128,
26631 mkexpr( vB ) ) ) );
26632 generate_store_FPRF( Ity_F128, vT, vbi );
26633 break;
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 ) ) );
26640 break;
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);
26662 assign( ftmp,
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)
26671 assign( vT,
26672 binop( Iop_F64HLtoF128,
26673 mkexpr( ftmp ),
26674 unop( Iop_ReinterpI64asF64, mkU64( 0 ) ) ) );
26675 else
26676 assign( vT,
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 );
26685 break;
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 );
26696 break;
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 ) ) );
26703 break;
26705 default:
26706 vex_printf( "dis_vx_Floating_Point_Arithmetic_quad_precision invalid inst_select (ppc)(opc2)\n" );
26707 return False;
26708 } /* switch inst_select */
26709 } /* end case 0x344 */
26710 break;
26711 default: /* switch opc2 */
26712 vex_printf( "dis_vx_Floating_Point_Arithmetic_quad_precision(ppc)(opc2)\n" );
26713 return False;
26715 putF128Reg( vT_addr, mkexpr( vT ) );
26716 return True;
26720 /* VSX Scalar Quad-Precision instructions */
26721 static Bool
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
26727 * set.
26729 /* XX1-Form */
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. */
26743 PREFIX_CHECK
26745 assign( vB, getVSReg( vB_addr ) );
26747 if (opc1 != 0x3F) {
26748 vex_printf( "dis_vx_scalar_quad_precision(ppc)(instr)\n" );
26749 return False;
26752 switch (opc2) {
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
26764 FX registers. */
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,
26771 unop(Iop_Not64,
26772 unop(Iop_1Sto64,
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 ) ) );
26781 assign( tmp,
26782 binop( Iop_And64,
26783 mkexpr( src_not_NaN ),
26784 binop( Iop_And64,
26785 unop( Iop_1Sto64,
26786 binop( Iop_CmpEQ64,
26787 mkexpr( vA_hi ),
26788 mkexpr( vB_hi ) ) ),
26789 unop( Iop_1Sto64,
26790 binop( Iop_CmpEQ64,
26791 mkexpr( vA_lo ),
26792 mkexpr( vB_lo ) ) ) ) ) );
26793 assign( vT, binop( Iop_64HLtoV128, mkexpr( tmp ), mkexpr( tmp ) ) );
26795 break;
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,
26808 mkexpr( vA ) ),
26809 mkU64( 0x8000000000000000ULL ) ) );
26810 assign( vB_hi, binop( Iop_Or64,
26811 binop( Iop_And64,
26812 unop( Iop_V128HIto64,
26813 mkexpr( vB ) ),
26814 mkU64( 0x7FFFFFFFFFFFFFFFULL ) ),
26815 mkexpr( sign_vA ) ) );
26816 assign( vT, binop( Iop_64HLtoV128,
26817 mkexpr( vB_hi ),
26818 unop( Iop_V128to64, mkexpr( vB ) ) ) );
26819 break;
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
26829 FX registers. */
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,
26836 unop(Iop_Not64,
26837 unop(Iop_1Sto64,
26838 mkOR1( is_NaN( Ity_V128, vA ),
26839 is_NaN( Ity_V128, vB ) ) ) ) );
26841 /* vA >= vB is Not( vB > vA) */
26842 assign( tmp,
26843 binop( Iop_And64,
26844 mkexpr( src_not_NaN ),
26845 unop( Iop_Not64,
26846 unop( Iop_1Sto64,
26847 Quad_precision_gt( vB, vA ) ) ) ) ) ;
26848 assign( vT, binop( Iop_64HLtoV128, mkexpr( tmp ), mkexpr( tmp ) ) );
26850 break;
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
26859 FX registers. */
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,
26866 unop(Iop_Not64,
26867 unop(Iop_1Sto64,
26868 mkOR1( is_NaN( Ity_V128, vA ),
26869 is_NaN( Ity_V128, vB ) ) ) ) );
26871 assign( tmp,
26872 binop( Iop_And64,
26873 mkexpr( src_not_NaN ),
26874 unop( Iop_1Sto64, Quad_precision_gt( vA, vB ) ) ) );
26876 assign( vT, binop( Iop_64HLtoV128, mkexpr( tmp ), mkexpr( tmp ) ) );
26878 break;
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);
26893 } else {
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,
26901 binop( Iop_Shr64,
26902 unop( Iop_V128HIto64,
26903 mkexpr( vA ) ),
26904 mkU8( 63 ) ),
26905 binop( Iop_Shr64,
26906 unop( Iop_V128HIto64,
26907 mkexpr( vB ) ),
26908 mkU8( 63 ) ) );
26910 /* A < B */
26911 bit4 = Quad_precision_gt( vB, vA );
26913 /* A > B */
26914 bit5 = Quad_precision_gt( vA, vB );
26916 /* A equal B */
26917 bit6 = mkAND1( binop( Iop_CmpEQ64,
26918 unop( Iop_V128HIto64,
26919 mkexpr( vA ) ),
26920 unop( Iop_V128HIto64,
26921 mkexpr( vB ) ) ),
26922 binop( Iop_CmpEQ64,
26923 unop( Iop_V128to64,
26924 mkexpr( vA ) ),
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 */
26932 bit_inf = mkAND1(
26933 mkAND1( is_Inf( Ity_V128, vA ), is_Inf( Ity_V128, vB ) ),
26934 binop( Iop_CmpEQ64,
26935 binop( Iop_And64,
26936 unop( Iop_V128to64,
26937 mkexpr( vA ) ),
26938 mkU64( 0x80000000) ),
26939 binop( Iop_And64,
26940 unop( Iop_V128to64,
26941 mkexpr( vB ) ),
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 ) );
26948 assign( eq_lt_gt,
26949 binop( Iop_Or32,
26950 binop( Iop_Or32,
26951 binop( Iop_Shl32,
26952 unop( Iop_1Uto32, bit4 ),
26953 mkU8( 3 ) ),
26954 binop( Iop_Shl32,
26955 unop( Iop_1Uto32, bit5 ),
26956 mkU8( 2 ) ) ),
26957 binop( Iop_Or32,
26958 binop( Iop_Shl32,
26959 unop( Iop_1Uto32, bit6 ),
26960 mkU8( 1 ) ),
26961 binop( Iop_Or32,
26962 binop( Iop_Shl32,
26963 unop( Iop_1Uto32,
26964 bit_zero ),
26965 mkU8( 1 ) ),
26966 binop( Iop_Shl32,
26967 unop( Iop_1Uto32,
26968 mkAND1( bit_inf, same_sign ) ),
26969 mkU8( 1 ) ) ) ) ) );
26971 assign(CC, binop( Iop_Or32,
26972 binop( Iop_And32,
26973 unop( Iop_Not32,
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 ) );
26981 return True;
26983 break;
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,
26999 binop( Iop_And64,
27000 unop( Iop_V128HIto64,
27001 mkexpr( vA ) ),
27002 mkU64( 0x7FFF000000000000 ) ),
27003 binop( Iop_And64,
27004 unop( Iop_V128HIto64,
27005 mkexpr( vB ) ),
27006 mkU64( 0x7FFF000000000000 ) ) );
27007 /* exp > B exp */
27008 bit5 = binop( Iop_CmpLT64U,
27009 binop( Iop_And64,
27010 unop( Iop_V128HIto64,
27011 mkexpr( vB ) ),
27012 mkU64( 0x7FFF000000000000 ) ),
27013 binop( Iop_And64,
27014 unop( Iop_V128HIto64,
27015 mkexpr( vA ) ),
27016 mkU64( 0x7FFF000000000000 ) ) );
27017 /* test equal */
27018 bit6 = binop( Iop_CmpEQ64,
27019 binop( Iop_And64,
27020 unop( Iop_V128HIto64,
27021 mkexpr( vA ) ),
27022 mkU64( 0x7FFF000000000000 ) ),
27023 binop( Iop_And64,
27024 unop( Iop_V128HIto64,
27025 mkexpr( vB ) ),
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,
27034 binop( Iop_Shl32,
27035 unop( Iop_1Uto32, bit4 ),
27036 mkU8( 3) ),
27037 binop( Iop_Or32,
27038 binop( Iop_Shl32,
27039 unop( Iop_1Uto32, bit5 ),
27040 mkU8( 2) ),
27041 binop( Iop_Shl32,
27042 unop( Iop_1Uto32, bit6 ),
27043 mkU8( 1 ) ) ) ) );
27044 assign(CC, binop( Iop_Or32,
27045 binop( Iop_And32,
27046 unop( Iop_Not32,
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 ) );
27054 return True;
27056 break;
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
27068 FX registers. */
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 ) ) );
27075 } else {
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,
27082 unop( Iop_Not64,
27083 unop( Iop_1Sto64,
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 ),
27098 mkexpr( vA ) ),
27099 binop( Iop_AndV128,
27100 unop( Iop_NotV128, mkexpr( cmp_mask ) ),
27101 mkexpr( vB ) ) ) );
27103 assign( vT,
27104 binop( Iop_OrV128,
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 ) ) ) );
27112 break;
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,
27131 binop( Iop_Shr64,
27132 unop( Iop_V128HIto64,
27133 mkexpr( vB ) ),
27134 mkU8( 63 ) ),
27135 mkU64( 0 ) ) ) );
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 */
27144 binop( Iop_Shr64,
27145 unop( Iop_V128HIto64, mkexpr( vB ) ),
27146 mkU8( 60 ) ),
27147 mkU64( 0x8 ) ),
27148 binop( Iop_Shl64,
27149 unop( Iop_1Uto64,
27150 binop( Iop_CmpNE64,
27151 binop( Iop_And64,
27152 mkexpr( DCM ),
27153 mkU64( DCMX_mask ) ),
27154 mkU64( 0 ) ) ),
27155 mkU8( 1 ) ) ) );
27157 putGST_field( PPC_GST_CR, unop(Iop_64to32, mkexpr( CC ) ), BF );
27158 putFPCC( unop(Iop_64to32, mkexpr( CC ) ) );
27159 return True;
27161 break;
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) {
27172 case 0:
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 ) ) ) );
27178 break;
27180 case 2:
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 ) ) ),
27187 mkU8( 48 ) ) );
27188 break;
27190 case 8:
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 ) ) ) );
27196 break;
27198 case 16:
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 ) ) ) );
27204 break;
27206 case 18:
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,
27215 binop( Iop_And64,
27216 unop( Iop_V128HIto64,
27217 mkexpr( vB ) ),
27218 mkU64( 0x7FFF000000000000 ) ),
27219 mkU64( 0x0 ) ) ) );
27221 assign( expInfinity,
27222 unop( Iop_1Uto64,
27223 binop( Iop_CmpNE64,
27224 binop( Iop_And64,
27225 unop( Iop_V128HIto64,
27226 mkexpr( vB ) ),
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.
27233 assign( vT,
27234 binop( Iop_OrV128,
27235 binop( Iop_ShrV128,
27236 binop( Iop_ShlV128,
27237 mkexpr( vB ),
27238 mkU8( 16 ) ),
27239 mkU8( 16 ) ),
27240 binop( Iop_64HLtoV128,
27241 binop( Iop_Shl64,
27242 binop( Iop_And64,
27243 mkexpr( expZero ),
27244 mkexpr( expInfinity ) ),
27245 mkU8( 48 ) ),
27246 mkU64( 0 ) ) ) );
27248 break;
27250 default:
27251 vex_printf( "dis_vx_scalar_quad_precision invalid inst_select (ppc)(opc2)\n" );
27252 return False;
27255 break;
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,
27265 mkexpr( vB ) ),
27266 mkU64( 0x7FFFULL ) ) );
27267 assign( vT, binop( Iop_64HLtoV128,
27268 binop( Iop_Or64,
27269 binop( Iop_And64,
27270 unop( Iop_V128HIto64,
27271 mkexpr( vA ) ),
27272 mkU64( 0x8000FFFFFFFFFFFFULL ) ),
27273 binop( Iop_Shl64,
27274 mkexpr( exp ),
27275 mkU8( 48 ) ) ),
27276 unop( Iop_V128to64,
27277 mkexpr( vA ) ) ) );
27279 break;
27281 default:
27282 vex_printf( "dis_vx_scalar_quad_precision(ppc)(opc2)\n" );
27284 return False;
27287 putVSReg( vT_addr, mkexpr( vT ) );
27288 return True;
27292 * VSX permute and other miscealleous instructions
27294 static Bool
27295 dis_vx_permute_misc( UInt prefix, UInt theInstr, UInt opc2 )
27297 /* XX3-Form */
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. */
27307 PREFIX_CHECK
27309 if (opc1 != 0x3C) {
27310 vex_printf( "dis_vx_permute_misc(ppc)(instr)\n" );
27311 return False;
27314 assign( vA, getVSReg( XA ) );
27315 assign( vB, getVSReg( XB ) );
27317 switch (opc2) {
27318 case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate)
27320 UChar SHW = ifieldSHW ( theInstr );
27321 IRTemp result = newTemp(Ity_V128);
27322 if ( SHW != 0 ) {
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)) );
27328 } else
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) );
27332 break;
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);
27340 if (DM & 0x2)
27341 assign( hi, unop(Iop_V128to64, mkexpr(vA)) );
27342 else
27343 assign( hi, unop(Iop_V128HIto64, mkexpr(vA)) );
27345 if (DM & 0x1)
27346 assign( lo, unop(Iop_V128to64, mkexpr(vB)) );
27347 else
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 ) );
27354 break;
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 ) );
27382 break;
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))) );
27394 break;
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);
27416 } else {
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 ) );
27426 else // xxpermr
27427 assign( vB_adj,
27428 binop( Iop_Sub16x8,
27429 unop( Iop_Dup8x16, mkU8( 0x1F ) ),
27430 mkexpr( vB ) ) );
27432 /* Limit the Perm8x16 steering values to 0 .. 15 as that is what
27433 IR specifies, and also to hide irrelevant bits from
27434 memcheck.
27436 assign( perm_val,
27437 binop( Iop_AndV128, mkexpr( vB_adj ),
27438 unop( Iop_Dup8x16, mkU8( 0xF ) ) ) );
27439 assign( a_perm,
27440 binop( Iop_Perm8x16, mkexpr( vA ), mkexpr( perm_val ) ) );
27441 assign( b_perm,
27442 binop( Iop_Perm8x16, mkexpr( vT ), mkexpr( perm_val ) ) );
27443 assign( mask, binop( Iop_SarN8x16,
27444 binop( Iop_ShlN8x16, mkexpr( vB_adj ),
27445 mkU8( 3 ) ),
27446 mkU8( 7 ) ) );
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 ) ) ) );
27453 break;
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);
27461 putVSReg( XT,
27462 unop( Iop_Dup32x4,
27463 unop( Iop_V128to32,
27464 binop( Iop_ShrV128, mkexpr( vB ), mkU8( sh_uim ) ) ) ) );
27465 break;
27468 default:
27469 vex_printf( "dis_vx_permute_misc(ppc)(opc2)\n" );
27470 return False;
27472 return True;
27476 AltiVec Load Instructions
27478 static Bool dis_av_load ( const VexAbiInfo* vbi, UInt prefix, UInt theInstr )
27480 /* X-Form */
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. */
27493 PREFIX_CHECK
27495 if (opc1 != 0x1F || b0 != 0) {
27496 vex_printf("dis_av_load(ppc)(instr)\n");
27497 return False;
27500 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
27501 assign( EA_align16, addr_align( mkexpr(EA), 16 ) );
27503 switch (opc2) {
27505 case 0x006: { // lvsl (Load Vector for Shift Left, AV p123)
27506 IRDirty* d;
27507 UInt vD_off = vectorGuestRegOffset(vD_addr);
27508 IRExpr** args_be = mkIRExprVec_5(
27509 IRExpr_GSPTR(),
27510 mkU32(vD_off),
27511 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
27512 mkU32(0xF)),
27513 mkU32(0)/*left*/,
27514 mkU32(1)/*Big Endian*/);
27515 IRExpr** args_le = mkIRExprVec_5(
27516 IRExpr_GSPTR(),
27517 mkU32(vD_off),
27518 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
27519 mkU32(0xF)),
27520 mkU32(0)/*left*/,
27521 mkU32(0)/*Little Endian*/);
27522 if (!mode64) {
27523 d = unsafeIRDirty_0_N (
27524 0/*regparms*/,
27525 "ppc32g_dirtyhelper_LVS",
27526 fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
27527 args_be );
27528 } else {
27529 if (host_endness == VexEndnessBE)
27530 d = unsafeIRDirty_0_N (
27531 0/*regparms*/,
27532 "ppc64g_dirtyhelper_LVS",
27533 fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
27534 args_be );
27535 else
27536 d = unsafeIRDirty_0_N (
27537 0/*regparms*/,
27538 "ppc64g_dirtyhelper_LVS",
27539 fnptr_to_fnentry( vbi, &ppc64g_dirtyhelper_LVS ),
27540 args_le );
27542 DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
27543 /* declare guest state effects */
27544 d->nFxState = 1;
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) );
27552 break;
27554 case 0x026: { // lvsr (Load Vector for Shift Right, AV p125)
27555 IRDirty* d;
27556 UInt vD_off = vectorGuestRegOffset(vD_addr);
27557 IRExpr** args_be = mkIRExprVec_5(
27558 IRExpr_GSPTR(),
27559 mkU32(vD_off),
27560 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
27561 mkU32(0xF)),
27562 mkU32(1)/*right*/,
27563 mkU32(1)/*Big Endian*/);
27564 IRExpr** args_le = mkIRExprVec_5(
27565 IRExpr_GSPTR(),
27566 mkU32(vD_off),
27567 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
27568 mkU32(0xF)),
27569 mkU32(1)/*right*/,
27570 mkU32(0)/*Little Endian*/);
27572 if (!mode64) {
27573 d = unsafeIRDirty_0_N (
27574 0/*regparms*/,
27575 "ppc32g_dirtyhelper_LVS",
27576 fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
27577 args_be );
27578 } else {
27579 if (host_endness == VexEndnessBE)
27580 d = unsafeIRDirty_0_N (
27581 0/*regparms*/,
27582 "ppc64g_dirtyhelper_LVS",
27583 fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
27584 args_be );
27585 else
27586 d = unsafeIRDirty_0_N (
27587 0/*regparms*/,
27588 "ppc64g_dirtyhelper_LVS",
27589 fnptr_to_fnentry( vbi, &ppc64g_dirtyhelper_LVS ),
27590 args_le );
27592 DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
27593 /* declare guest state effects */
27594 d->nFxState = 1;
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) );
27602 break;
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)) );
27610 break;
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)) );
27616 break;
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)) );
27622 break;
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)) );
27627 break;
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)) );
27632 break;
27634 default:
27635 vex_printf("dis_av_load(ppc)(opc2)\n");
27636 return False;
27638 return True;
27642 AltiVec Store Instructions
27644 static Bool dis_av_store ( UInt prefix, UInt theInstr )
27646 /* X-Form */
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. */
27662 PREFIX_CHECK
27664 if (opc1 != 0x1F || b0 != 0) {
27665 vex_printf("dis_av_store(ppc)(instr)\n");
27666 return False;
27669 assign( vS, getVReg(vS_addr));
27670 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
27672 switch (opc2) {
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),
27676 unop(Iop_32to8,
27677 mkNarrowTo32(ty, mkexpr(EA)) )) );
27678 if (host_endness == VexEndnessLE) {
27679 assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
27680 } else {
27681 assign( idx, binop(Iop_Shl8,
27682 binop(Iop_Sub8, mkU8(15), mkexpr(eb)),
27683 mkU8(3)) );
27685 store( mkexpr(EA),
27686 unop( Iop_32to8, unop(Iop_V128to32,
27687 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
27688 break;
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)) );
27697 } else {
27698 assign( idx, binop(Iop_Shl8,
27699 binop(Iop_Sub8, mkU8(14), mkexpr(eb)),
27700 mkU8(3)) );
27702 store( mkexpr(addr_aligned),
27703 unop( Iop_32to16, unop(Iop_V128to32,
27704 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
27705 break;
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)) );
27714 } else {
27715 assign( idx, binop(Iop_Shl8,
27716 binop(Iop_Sub8, mkU8(12), mkexpr(eb)),
27717 mkU8(3)) );
27719 store( mkexpr( addr_aligned),
27720 unop( Iop_V128to32,
27721 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) );
27722 break;
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) );
27728 break;
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) );
27733 break;
27735 default:
27736 vex_printf("dis_av_store(ppc)(opc2)\n");
27737 return False;
27739 return True;
27743 AltiVec Arithmetic Instructions
27745 static Bool dis_av_arith ( UInt prefix, UInt theInstr )
27747 /* VX-Form */
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);
27760 IRTemp aEvn, aOdd;
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. */
27766 PREFIX_CHECK
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 ) );
27776 if (opc1 != 0x4) {
27777 vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n");
27778 return False;
27781 switch (opc2) {
27782 /* Add */
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 ) ) ),
27789 mkU8( 31 ) ) );
27790 break;
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)) );
27795 break;
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)) );
27800 break;
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)) );
27805 break;
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)) );
27810 break;
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
27816 break;
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]
27822 break;
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]
27828 break;
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 ) ) ) );
27860 } else {
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
27869 conversion. */
27870 assign( hi, unop( Iop_128HIto64, mkexpr( tmp128 ) ) );
27871 assign( lo, unop( Iop_128to64, mkexpr( tmp128 ) ) );
27873 putVReg( vD_addr,
27874 binop( Iop_64HLtoV128, mkexpr( hi ), mkexpr( lo ) ) );
27876 break;
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]
27882 break;
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]
27888 break;
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]
27894 break;
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
27905 #define MAX_ELE 4
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;
27915 UInt i;
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],
27975 binop( Iop_Shl64,
27976 unop( expand_op,
27977 unop( Iop_64to32,
27978 unop( Iop_V128to64,
27979 binop( Iop_ShrV128,
27980 mkexpr( vA ),
27981 mkU8( i*shift_by ) )))),
27982 mkU8( 32 ) ) );
27983 } else {
27984 assign( srcA_tmp[i],
27985 unop( expand_op,
27986 unop( Iop_64to32,
27987 unop( Iop_V128to64,
27988 binop( Iop_ShrV128,
27989 mkexpr( vA ),
27990 mkU8( i*shift_by ) ) ) ) ) );
27993 assign( srcB_tmp[i],
27994 unop( expand_op,
27995 unop( Iop_64to32,
27996 unop( Iop_V128to64,
27997 binop( Iop_ShrV128,
27998 mkexpr( vB ),
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],
28009 binop( operation,
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],
28017 unop( extract_res,
28018 binop( Iop_And64,
28019 unop( Iop_1Sto64,
28020 binop( Iop_CmpEQ64,
28021 binop( Iop_Shr64, mkexpr( res_tmp3[i] ), mkU8( 31 )),
28022 mkU64( 0x0 ) ) ),
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],
28030 binop( operation,
28031 mkexpr( srcA_tmp[i] ),
28032 mkexpr( srcB_tmp[i] ) ) );
28033 assign( res_tmp[i],
28034 unop( extract_res,
28035 binop( Iop_And64,
28036 unop( Iop_1Sto64,
28037 binop( Iop_CmpEQ64,
28038 binop( Iop_Shr64, mkexpr( res_tmp2[i] ), mkU8( 32 )),
28039 mkU64( 0x0 ) ) ),
28040 mkexpr( res_tmp2[i] ) ) ) );
28041 } else {
28042 assign( res_tmp[i],
28043 unop( extract_res,
28044 binop( operation,
28045 mkexpr( srcA_tmp[i] ),
28046 mkexpr( srcB_tmp[i] ) ) ) );
28050 if (!(( opc2 == 0x68B ) || ( opc2 == 0x78B ))) {
28051 /* Doing a multiply or divide instruction */
28052 putVReg( vD_addr,
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 ] ) ) ) ) );
28061 } else {
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 );
28067 assign( res_Tmp,
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,
28078 mkexpr( vA ),
28079 binop( Iop_Mul32x4,
28080 mkexpr( res_Tmp ),
28081 mkexpr( vB ) ) ) );
28083 #undef MAX_ELE
28085 break;
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
28094 #define MAX_ELE 2
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;
28101 UInt i;
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,
28144 mkexpr( vA ),
28145 mkU8( i*shift_by ) ) ) );
28147 assign( srcB_tmp[i],
28148 unop( Iop_V128to64,
28149 binop( Iop_ShrV128,
28150 mkexpr( vB ),
28151 mkU8( i*shift_by ) ) ) );
28153 if ((opc2 == 0x1C9) || (opc2 == 0x2C9) || (opc2 == 0x3C9)) {
28154 /* multiply result is I128 */
28155 assign( res_tmp[i],
28156 unop( extract_res,
28157 binop( operation,
28158 mkexpr( srcA_tmp[i] ),
28159 mkexpr( srcB_tmp[i] ) ) ) );
28160 } else {
28161 /* divide result is I64 */
28162 assign( res_tmp[i],
28163 binop( operation,
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,
28176 binop( Iop_Mul64,
28177 mkexpr( res_tmp[ 1 ] ),
28178 mkexpr( srcB_tmp[1] ) ),
28179 binop( Iop_Mul64,
28180 mkexpr( res_tmp[0] ),
28181 mkexpr( srcB_tmp[0] ) ) ) );
28183 putVReg( vD_addr, binop( Iop_Sub64x2,
28184 mkexpr( vA ),
28185 mkexpr( res_Tmp ) ) );
28187 } else {
28188 putVReg( vD_addr, binop( Iop_64HLtoV128,
28189 mkexpr( res_tmp[ 1 ] ),
28190 mkexpr( res_tmp[ 0 ] ) ) );
28193 #undef MAX_ELE
28195 break;
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);
28214 assign( result_hi,
28215 binop( Iop_DivU64E, mkexpr( dividend_hi ),
28216 mkexpr( divisor_hi ) ) );
28217 assign( result_lo,
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 ) ) );
28223 } else {
28224 DIP("vdivesd v%d,v%d,v%d", vD_addr, vA_addr, vB_addr);
28225 assign( result_hi,
28226 binop( Iop_DivS64E, mkexpr( dividend_hi ),
28227 mkexpr( divisor_hi ) ) );
28228 assign( result_lo,
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 ) ) );
28234 break;
28237 /* Subtract */
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,
28242 unop(Iop_NotV128,
28243 binop(Iop_CmpGT32Ux4, mkexpr(vB),
28244 mkexpr(vA))),
28245 mkU8(31)) );
28246 break;
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)) );
28251 break;
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)) );
28256 break;
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)) );
28261 break;
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)) );
28266 break;
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]
28272 break;
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]
28278 break;
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]
28284 break;
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]
28290 break;
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]
28296 break;
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]
28302 break;
28305 /* Maximum */
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)) );
28309 break;
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)) );
28314 break;
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)) );
28319 break;
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)) );
28324 break;
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)) );
28329 break;
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)) );
28334 break;
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)) );
28339 break;
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)) );
28344 break;
28346 /* Minimum */
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)) );
28350 break;
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)) );
28355 break;
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)) );
28360 break;
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)) );
28365 break;
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)) );
28370 break;
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)) );
28375 break;
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)) );
28380 break;
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)) );
28385 break;
28388 /* Average */
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)) );
28392 break;
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)) );
28397 break;
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)) );
28402 break;
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)) );
28407 break;
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)) );
28412 break;
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)) );
28417 break;
28420 /* Multiply */
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);
28423 putVReg( vD_addr,
28424 binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)));
28425 break;
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);
28429 putVReg( vD_addr,
28430 binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)));
28431 break;
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) ) );
28436 break;
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) ) );
28441 break;
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);
28445 putVReg( vD_addr,
28446 binop(Iop_MullEven8Sx16, mkexpr(vA), mkexpr(vB)));
28447 break;
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);
28451 putVReg( vD_addr,
28452 binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)));
28453 break;
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) ) );
28458 break;
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) ));
28463 break;
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) ));
28468 break;
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) ) );
28473 break;
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) ));
28478 break;
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) ));
28483 break;
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) ) );
28488 break;
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 );
28508 /* add lanes */
28509 assign( z3, binop(Iop_Add64, mkexpr(b3),
28510 binop(Iop_Add64,
28511 binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
28512 binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
28513 assign( z2, binop(Iop_Add64, mkexpr(b2),
28514 binop(Iop_Add64,
28515 binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
28516 binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
28517 assign( z1, binop(Iop_Add64, mkexpr(b1),
28518 binop(Iop_Add64,
28519 binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
28520 binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
28521 assign( z0, binop(Iop_Add64, mkexpr(b0),
28522 binop(Iop_Add64,
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)) );
28529 break;
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 );
28548 /* add lanes */
28549 assign( z3, binop(Iop_Add64, mkexpr(b3),
28550 binop(Iop_Add64,
28551 binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
28552 binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
28553 assign( z2, binop(Iop_Add64, mkexpr(b2),
28554 binop(Iop_Add64,
28555 binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
28556 binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
28557 assign( z1, binop(Iop_Add64, mkexpr(b1),
28558 binop(Iop_Add64,
28559 binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
28560 binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
28561 assign( z0, binop(Iop_Add64, mkexpr(b0),
28562 binop(Iop_Add64,
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)) );
28569 break;
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 );
28582 /* add lanes */
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)) );
28595 break;
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 );
28604 /* add lanes */
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)) );
28613 break;
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 );
28622 /* add lanes */
28623 assign( z0, binop(Iop_Add64, mkexpr(b0),
28624 binop(Iop_Add64,
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)) );
28631 break;
28633 default:
28634 vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2);
28635 return False;
28637 return True;
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);
28647 UInt opc2;
28648 IRTemp vA = newTemp(Ity_V128);
28649 IRTemp vB = newTemp(Ity_V128);
28651 if (opc1 != 0x4) {
28652 vex_printf("ERROR: dis_vx_quadword_arith(ppc)\n");
28653 return False;
28656 assign( vA, getVReg( vA_addr ) );
28657 assign( vB, getVReg( vB_addr ) );
28659 opc2 = IFIELD(theInstr, 0, 6);
28660 switch (opc2) {
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 ) ) );
28672 return True;
28675 default:
28676 break; /* fall thru to next case statement */
28677 } /* switch (opc2) */
28679 opc2 = ifieldOPClo11( theInstr );
28680 switch (opc2) {
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);
28690 assign( sh,
28691 binop( Iop_And8,
28692 mkU8( 0x7F ),
28693 unop( Iop_16to8,
28694 unop( Iop_32to16,
28695 unop( Iop_64to32,
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 ) ) );
28702 putVReg( vT_addr,
28703 binop( Iop_OrV128, mkexpr( vA_shl ), mkexpr( vA_shr ) ) );
28705 break;
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 ) ) );
28710 break;
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 ) ),
28728 binop( Iop_Or32,
28729 binop( Iop_Shl32,
28730 mkexpr( gt ), mkU8( 2 ) ),
28731 binop( Iop_Shl32,
28732 mkexpr( eq ), mkU8( 1 ) ) ) ) );
28734 putGST_field( PPC_GST_CR, mkexpr( cc ), BF );
28736 break;
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] */
28743 assign( sh,
28744 binop( Iop_And8,
28745 mkU8( 0x7F ),
28746 unop( Iop_16to8,
28747 unop( Iop_32to16,
28748 unop( Iop_64to32,
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);
28754 putVReg( vT_addr,
28755 binop( Iop_ShlV128, mkexpr( vA ), mkexpr( sh ) ) );
28757 } else {
28758 DIP("vsrq v%u,v%u,v%u\n", vT_addr, vA_addr, vB_addr);
28759 putVReg( vT_addr,
28760 binop( Iop_ShrV128, mkexpr( vA ), mkexpr( sh ) ) );
28763 break;
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 ) ) );
28768 break;
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 ) ),
28786 binop( Iop_Or32,
28787 binop( Iop_Shl32,
28788 mkexpr( gt ), mkU8( 2 ) ),
28789 binop( Iop_Shl32,
28790 mkexpr( eq ), mkU8( 1 ) ) ) ) );
28792 putGST_field( PPC_GST_CR, mkexpr( cc ), BF );
28794 break;
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] */
28809 assign( sh,
28810 binop( Iop_And8,
28811 mkU8( 0x7F ),
28812 unop ( Iop_16to8,
28813 unop ( Iop_32to16,
28814 unop ( Iop_64to32,
28815 unop( Iop_V128HIto64,
28816 mkexpr( vB ) ) ) ) ) ) );
28818 /* mask begin in bits vB[41:47] */
28819 assign( mb,
28820 binop( Iop_And8,
28821 mkU8( 0x7F ),
28822 unop ( Iop_16to8,
28823 unop ( Iop_32to16,
28824 binop( Iop_Shr32,
28825 unop ( Iop_64to32,
28826 unop( Iop_V128HIto64,
28827 mkexpr( vB ) ) ),
28828 mkU8 ( 16 ) ) ) ) ) );
28830 /* mask end in bits vB[49:55] */
28831 assign( tmp,
28832 unop ( Iop_16to8,
28833 unop ( Iop_32to16,
28834 binop( Iop_Shr32,
28835 unop ( Iop_64to32,
28836 unop( Iop_V128HIto64,
28837 mkexpr( vB ) ) ),
28838 mkU8 ( 8 ) ) ) ) );
28840 assign( me,
28841 binop( Iop_Sub8,
28842 mkU8( 127 ),
28843 binop( Iop_And8,
28844 mkU8( 0x7F ),
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. */
28851 assign( mask,
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 ) ),
28859 mkexpr( me ) ),
28860 mkexpr( me ) ),
28861 mkexpr( mb ) ),
28862 mkexpr( mb ) ) );
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 */
28876 putVReg( vT_addr,
28877 binop( Iop_OrV128,
28878 binop( Iop_AndV128,
28879 unop( Iop_NotV128, mkexpr( mask ) ),
28880 mkexpr( vT_initial ) ),
28881 binop( Iop_AndV128,
28882 binop( Iop_OrV128,
28883 mkexpr( vA_shl ),
28884 mkexpr( vA_shr ) ),
28885 mkexpr( mask ) ) ) );
28887 } else {
28888 DIP("vrlqnm v%u,v%u\n", vA_addr, vB_addr);
28890 putVReg( vT_addr,
28891 binop( Iop_AndV128,
28892 binop( Iop_OrV128,
28893 mkexpr( vA_shl ),
28894 mkexpr( vA_shr ) ),
28895 mkexpr( mask ) ) );
28898 break;
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 );
28906 UInt cc_field = 6;
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,
28915 binop( Iop_Shl32,
28916 unop( Iop_1Uto32, mkexpr( eq ) ),
28917 mkU8( 3 ) ),
28918 binop( Iop_Shl32,
28919 unop( Iop_1Uto32,
28920 unop( Iop_Not1, mkexpr( eq ) ) ),
28921 mkU8( 1 ) ) ) );
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 ) ) ) );
28929 break;
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 );
28939 UInt cc_field = 6;
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 ) );
28947 } else {
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,
28956 binop( Iop_Shl32,
28957 unop( Iop_1Uto32, mkexpr( gt ) ),
28958 mkU8( 3 ) ),
28959 binop( Iop_Shl32,
28960 unop( Iop_1Uto32,
28961 unop( Iop_Not1, mkexpr( gt ) ) ),
28962 mkU8( 1 ) ) ) );
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 ) ) ) );
28969 break;
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 ) ) );
28974 break;
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);
28985 assign( sh,
28986 binop( Iop_And8,
28987 mkU8( 0x7F ),
28988 unop( Iop_16to8,
28989 unop( Iop_32to16,
28990 unop( Iop_64to32,
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).
28998 assign( tmp,
28999 binop( Iop_And64,
29000 unop( Iop_1Sto64,
29001 binop( Iop_CmpNE8, mkexpr( sh ), mkU8( 0 ) ) ),
29002 unop( Iop_1Sto64,
29003 unop( Iop_64to1,
29004 binop( Iop_Shr64,
29005 unop( Iop_V128HIto64,
29006 mkexpr( vA ) ),
29007 mkU8( 63 ) ) ) ) ) );
29008 assign( vA_sign,
29009 binop( Iop_ShlV128,
29010 binop( Iop_ShrV128,
29011 binop( Iop_64HLtoV128,
29012 mkexpr( tmp ),
29013 mkexpr( tmp ) ),
29014 mkexpr( shr ) ),
29015 mkexpr( shr ) ) );
29017 putVReg( vT_addr,
29018 binop( Iop_OrV128,
29019 binop( Iop_ShrV128, mkexpr( vA ), mkexpr( sh ) ),
29020 mkexpr( vA_sign ) ) );
29022 break;
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 ) ) );
29027 break;
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 ) ) );
29032 break;
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 ) ) );
29037 break;
29039 default:
29040 vex_printf("dis_av_arith(ppc)(opc2 bits[21:31]=0x%x)\n", opc2);
29041 return False;
29042 } /* switch (opc2) */
29044 return True;
29049 AltiVec Logic Instructions
29051 static Bool dis_av_logic ( UInt prefix, UInt theInstr )
29053 /* VX-Form */
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. */
29066 PREFIX_CHECK
29068 if (opc1 != 0x4) {
29069 vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n");
29070 return False;
29073 switch (opc2) {
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)) );
29077 break;
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))) );
29083 break;
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)) );
29088 break;
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)) );
29093 break;
29095 case 0x504: // vnor (Nor, AV p216)
29096 DIP("vnor v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr);
29097 putVReg( vT_addr,
29098 unop(Iop_NotV128, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB))) );
29099 break;
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,
29104 mkexpr( vA ),
29105 unop( Iop_NotV128, mkexpr( vB ) ) ) );
29106 break;
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 ) ) ) );
29113 break;
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 ) ) ) );
29120 break;
29122 default:
29123 vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2);
29124 return False;
29126 return True;
29130 AltiVec Compare Instructions
29132 static Bool dis_av_cmp ( UInt prefix, UInt theInstr )
29134 /* VXR-Form */
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. */
29147 PREFIX_CHECK
29149 assign( vA, getVReg(vA_addr));
29150 assign( vB, getVReg(vB_addr));
29152 if (opc1 != 0x4) {
29153 vex_printf("dis_av_cmp(ppc)(instr)\n");
29154 return False;
29157 switch (opc2) {
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)) );
29162 break;
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 ) ) ) );
29169 break;
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)) );
29175 break;
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 ) ) ) );
29182 break;
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)) );
29188 break;
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 ) ) ) );
29195 break;
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 ) );
29216 break;
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,
29236 binop( Iop_OrV128,
29237 mkexpr( vAeq0 ),
29238 mkexpr( vBeq0 ) ),
29239 mkexpr( vAeqvB ) ) );
29241 break;
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,
29261 binop( Iop_OrV128,
29262 mkexpr( vAeq0 ),
29263 mkexpr( vBeq0 ) ),
29264 mkexpr( vAeqvB ) ) );
29266 break;
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)) );
29272 break;
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)) );
29278 break;
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)) );
29284 break;
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)) );
29290 break;
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)) );
29296 break;
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)) );
29302 break;
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)) );
29308 break;
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)) );
29314 break;
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)) );
29320 break;
29322 default:
29323 vex_printf("dis_av_cmp(ppc)(opc2)\n");
29324 return False;
29327 putVReg( vD_addr, mkexpr(vD) );
29329 if (flag_rC) {
29330 set_AV_CR6( mkexpr(vD), True );
29332 return True;
29336 AltiVec Multiply-Sum Instructions
29338 static Bool dis_av_multarith ( UInt prefix, UInt theInstr )
29340 /* VA-Form */
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. */
29370 PREFIX_CHECK
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)) );
29380 if (opc1 != 0x4) {
29381 vex_printf("dis_av_multarith(ppc)(instr)\n");
29382 return False;
29385 switch (opc2) {
29386 /* Multiply-Add */
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)),
29403 mkU8(15))) );
29405 assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
29406 binop(Iop_SarN32x4,
29407 binop(Iop_MullEven16Sx8,
29408 mkexpr(aHi), mkexpr(bHi)),
29409 mkU8(15))) );
29411 putVReg( vD_addr,
29412 binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
29413 break;
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)),
29430 mkU8(14)) );
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))),
29437 mkU8(15))) );
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))),
29444 mkU8(15))) );
29446 putVReg( vD_addr,
29447 binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
29448 break;
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)),
29461 mkexpr(cLo)) );
29462 assign(zHi, binop(Iop_Add32x4,
29463 binop(Iop_MullEven16Ux8, mkexpr(aHi), mkexpr(bHi)),
29464 mkexpr(cHi)));
29465 putVReg( vD_addr,
29466 binop(Iop_NarrowBin32to16x8, mkexpr(zHi), mkexpr(zLo)) );
29467 break;
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
29484 are zero. */
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 ) )
29509 ) );
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 ) ),
29516 mkU64( 0 ) );
29518 assign ( partial_sum_hi,
29519 binop( Iop_Add64,
29520 binop( Iop_Add64,
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,
29535 mkexpr( vC ) ),
29536 mkU64( 0 ) );
29538 assign ( result_hi,
29539 binop( Iop_Add64,
29540 binop( Iop_Add64,
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 ) ) );
29547 break;
29550 /* Multiply-Sum */
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 );
29565 putVReg( vD_addr,
29566 binop(Iop_Add32x4, mkexpr(vC),
29567 binop(Iop_Add32x4,
29568 binop(Iop_Add32x4, mkexpr(abEE), mkexpr(abEO)),
29569 binop(Iop_Add32x4, mkexpr(abOE), mkexpr(abOO)))) );
29570 break;
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.
29604 putVReg( vD_addr,
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)))) );
29611 assign(prod,
29612 binop(Iop_QAdd32Sx4,
29613 binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)),
29614 binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO))));
29615 assign( sum0,
29616 unop(Iop_64to32,
29617 binop(Iop_Add64,
29618 unop(Iop_32Sto64,
29619 unop(Iop_64HIto32, unop(Iop_V128HIto64, mkexpr(prod)))),
29620 unop(Iop_32Sto64,
29621 unop(Iop_64HIto32, unop(Iop_V128HIto64, mkexpr(vC)))))));
29622 assign( sum1,
29623 unop(Iop_64to32,
29624 binop(Iop_Add64,
29625 unop(Iop_32Sto64,
29626 unop(Iop_64to32, unop(Iop_V128HIto64, mkexpr(prod)))),
29627 unop(Iop_32Sto64,
29628 unop(Iop_64to32, unop(Iop_V128HIto64, mkexpr(vC)))))));
29629 assign( sum2,
29630 unop(Iop_64to32,
29631 binop(Iop_Add64,
29632 unop(Iop_32Sto64,
29633 unop(Iop_64HIto32, unop(Iop_V128to64, mkexpr(prod)))),
29634 unop(Iop_32Sto64,
29635 unop(Iop_64HIto32, unop(Iop_V128to64, mkexpr(vC)))))));
29636 assign( sum3,
29637 unop(Iop_64to32,
29638 binop(Iop_Add64,
29639 unop(Iop_32Sto64,
29640 unop(Iop_64to32, unop(Iop_V128to64, mkexpr(prod)))),
29641 unop(Iop_32Sto64,
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))));
29647 break;
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)) );
29654 putVReg( vD_addr,
29655 binop(Iop_Add32x4, mkexpr(vC),
29656 binop(Iop_Add32x4, mkexpr(abEvn), mkexpr(abOdd))) );
29657 break;
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 );
29671 /* add lanes */
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)) );
29685 break;
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)) );
29692 putVReg( vD_addr,
29693 binop(Iop_Add32x4, mkexpr(vC),
29694 binop(Iop_Add32x4, mkexpr(abOdd), mkexpr(abEvn))) );
29695 break;
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 );
29709 /* add lanes */
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)) );
29722 break;
29724 default:
29725 vex_printf("dis_av_multarith(ppc)(opc2)\n");
29726 return False;
29728 return True;
29732 AltiVec Polynomial Multiply-Sum Instructions
29734 static Bool dis_av_polymultarith ( UInt prefix, UInt theInstr )
29736 /* VA-Form */
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. */
29748 PREFIX_CHECK
29750 assign( vA, getVReg(vA_addr));
29751 assign( vB, getVReg(vB_addr));
29752 assign( vC, getVReg(vC_addr));
29754 if (opc1 != 0x4) {
29755 vex_printf("dis_av_polymultarith(ppc)(instr)\n");
29756 return False;
29759 switch (opc2) {
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)) );
29765 break;
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)) );
29770 break;
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)) );
29775 break;
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)) );
29780 break;
29781 default:
29782 vex_printf("dis_av_polymultarith(ppc)(opc2=0x%x)\n", opc2);
29783 return False;
29785 return True;
29789 AltiVec Shift/Rotate Instructions
29791 static Bool dis_av_shift ( UInt prefix, UInt theInstr )
29793 /* VX-Form */
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. */
29805 PREFIX_CHECK
29807 assign( vA, getVReg(vA_addr));
29808 assign( vB, getVReg(vB_addr));
29810 if (opc1 != 0x4){
29811 vex_printf("dis_av_shift(ppc)(instr)\n");
29812 return False;
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);
29830 assign( tmpHi_64,
29831 unop( Iop_V128HIto64,
29832 binop( Iop_ShlV128,
29833 mkexpr( vA ),
29834 mkU8( SH ) ) ) );
29835 assign( result,
29836 binop( Iop_64HLtoV128,
29837 mkexpr( tmpHi_64 ),
29838 unop( Iop_V128HIto64,
29839 binop( Iop_ShlV128,
29840 mkexpr( Middle_128 ),
29841 mkU8( SH ) ) ) ) );
29842 } else {
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);
29846 assign( tmpLo_64,
29847 unop( Iop_V128to64,
29848 binop( Iop_ShrV128,
29849 mkexpr( vB ),
29850 mkU8( SH ) ) ) );
29851 assign( result,
29852 binop( Iop_64HLtoV128,
29853 unop( Iop_V128to64,
29854 binop( Iop_ShrV128,
29855 mkexpr( Middle_128 ),
29856 mkU8( SH ) ) ),
29857 mkexpr( tmpLo_64 ) ) );
29859 putVReg( vD_addr, mkexpr( result ) );
29860 return True;
29863 switch (opc2_vx_form) {
29864 /* Rotate */
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)) );
29868 break;
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)) );
29873 break;
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)) );
29878 break;
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)) );
29883 break;
29886 /* Shift Left */
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)) );
29890 break;
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)) );
29895 break;
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)) );
29900 break;
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)) );
29905 break;
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),
29911 unop(Iop_32to8,
29912 unop(Iop_V128to32, mkexpr(vB)))) );
29913 putVReg( vD_addr,
29914 binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
29915 break;
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),
29921 unop(Iop_32to8,
29922 unop(Iop_V128to32, mkexpr(vB)))) );
29923 putVReg( vD_addr,
29924 binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
29925 break;
29929 /* Shift Right */
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)) );
29933 break;
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)) );
29938 break;
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)) );
29943 break;
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),
29949 unop(Iop_32to8,
29950 unop(Iop_V128to32, mkexpr(vB)))) );
29951 putVReg( vD_addr,
29952 binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
29953 break;
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)) );
29958 break;
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)) );
29963 break;
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)) );
29968 break;
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)) );
29973 break;
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),
29979 unop(Iop_32to8,
29980 unop(Iop_V128to32, mkexpr(vB)))) );
29981 putVReg( vD_addr,
29982 binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
29983 break;
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)) );
29989 break;
29992 default:
29993 vex_printf("dis_av_shift(ppc)(opc2)\n");
29994 return False;
29996 return True;
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. */
30022 PREFIX_CHECK
30024 assign( vA, getVReg(vA_addr));
30025 assign( vB, getVReg(vB_addr));
30026 assign( vC, getVReg(vC_addr));
30028 if (opc1 != 0x4) {
30029 vex_printf("dis_av_permute(ppc)(instr)\n");
30030 return False;
30033 switch (opc2) {
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))) );
30040 return True;
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
30052 memcheck */
30053 assign( vC_andF,
30054 binop(Iop_AndV128, mkexpr(vC),
30055 unop(Iop_Dup8x16, mkU8(0xF))) );
30056 assign( a_perm,
30057 binop(Iop_Perm8x16, mkexpr(vA), mkexpr(vC_andF)) );
30058 assign( b_perm,
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)),
30063 mkU8(7)) );
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),
30069 mkexpr(mask))) );
30070 return True;
30072 case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241)
30073 if (b10 != 0) {
30074 vex_printf("dis_av_permute(ppc)(vsldoi)\n");
30075 return False;
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) );
30081 else
30082 putVReg( vD_addr,
30083 binop(Iop_OrV128,
30084 binop(Iop_ShlV128, mkexpr(vA), mkU8(SHB_uimm4*8)),
30085 binop(Iop_ShrV128, mkexpr(vB), mkU8((16-SHB_uimm4)*8))) );
30086 return True;
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 ) ) ),
30101 mkU8 ( 4 ) ) );
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) ) );
30106 return True;
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
30121 memcheck.
30124 assign( vC_adj,
30125 binop( Iop_Sub16x8,
30126 unop( Iop_Dup8x16, mkU8( 0x1F ) ),
30127 mkexpr( vC ) ) );
30128 assign( vC_andF,
30129 binop( Iop_AndV128, mkexpr( vC_adj),
30130 unop( Iop_Dup8x16, mkU8( 0xF ) ) ) );
30131 assign( a_perm,
30132 binop( Iop_Perm8x16, mkexpr( vA ), mkexpr( vC_andF ) ) );
30133 assign( b_perm,
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 ) ) ) );
30145 return True;
30148 default:
30149 break; // Fall through...
30152 opc2 = IFIELD( theInstr, 0, 11 );
30153 switch (opc2) {
30155 /* Merge */
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);
30158 putVReg( vD_addr,
30159 binop(Iop_InterleaveHI8x16, mkexpr(vA), mkexpr(vB)) );
30160 break;
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);
30164 putVReg( vD_addr,
30165 binop(Iop_InterleaveHI16x8, mkexpr(vA), mkexpr(vB)) );
30166 break;
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);
30170 putVReg( vD_addr,
30171 binop(Iop_InterleaveHI32x4, mkexpr(vA), mkexpr(vB)) );
30172 break;
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);
30176 putVReg( vD_addr,
30177 binop(Iop_InterleaveLO8x16, mkexpr(vA), mkexpr(vB)) );
30178 break;
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);
30182 putVReg( vD_addr,
30183 binop(Iop_InterleaveLO16x8, mkexpr(vA), mkexpr(vB)) );
30184 break;
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);
30188 putVReg( vD_addr,
30189 binop(Iop_InterleaveLO32x4, mkexpr(vA), mkexpr(vB)) );
30190 break;
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,
30202 mkexpr( vB ),
30203 unop( Iop_32to8,
30204 binop( Iop_Mul32,
30205 mkU32( 8 ),
30206 mkU32( 31 - uim ) ) ) ),
30207 binop( Iop_64HLtoV128,
30208 mkU64( 0x0ULL ),
30209 mkU64( 0xFFULL ) ) ),
30210 mkU8( 64 ) ) );
30212 break;
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,
30223 mkexpr( vB ),
30224 unop( Iop_32to8,
30225 binop( Iop_Mul32,
30226 mkU32( 8 ),
30227 mkU32( 30 - uim ) ) ) ),
30228 binop( Iop_64HLtoV128,
30229 mkU64( 0x0ULL ),
30230 mkU64( 0xFFFFULL ) ) ),
30231 mkU8( 64 ) ) );
30233 break;
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);
30241 putVReg( vD_addr,
30242 binop( Iop_ShlV128,
30243 binop( Iop_AndV128,
30244 binop( Iop_ShrV128,
30245 mkexpr( vB ),
30246 unop( Iop_32to8,
30247 binop( Iop_Mul32,
30248 mkU32( 8 ),
30249 mkU32( 28 - uim ) ) ) ),
30250 binop( Iop_64HLtoV128,
30251 mkU64( 0x0ULL ),
30252 mkU64( 0xFFFFFFFFULL ) ) ),
30253 mkU8( 64 ) ) );
30255 break;
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);
30263 putVReg( vD_addr,
30264 binop( Iop_ShlV128,
30265 binop( Iop_AndV128,
30266 binop( Iop_ShrV128,
30267 mkexpr( vB ),
30268 unop( Iop_32to8,
30269 binop( Iop_Mul32,
30270 mkU32( 8 ),
30271 mkU32( 24 - uim ) ) ) ),
30272 binop( Iop_64HLtoV128,
30273 mkU64( 0x0ULL ),
30274 mkU64( 0xFFFFFFFFFFFFFFFFULL ) ) ),
30275 mkU8( 64 ) ) );
30277 break;
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,
30291 binop( Iop_Mul32,
30292 mkU32( 8 ),
30293 mkU32( 15 - ( uim + 0 ) ) ) ) );
30295 putVReg( vD_addr,
30296 binop( Iop_OrV128,
30297 binop( Iop_ShlV128,
30298 binop( Iop_AndV128,
30299 binop( Iop_ShrV128,
30300 mkexpr( vB ),
30301 mkU8( ( 15 - 7 )*8 ) ),
30302 binop( Iop_64HLtoV128,
30303 mkU64( 0x0ULL ),
30304 mkU64( 0xFFULL ) ) ),
30305 mkexpr( shift ) ),
30306 binop( Iop_AndV128,
30307 unop( Iop_NotV128,
30308 binop( Iop_ShlV128,
30309 binop( Iop_64HLtoV128,
30310 mkU64( 0x0ULL ),
30311 mkU64( 0xFFULL ) ),
30312 mkexpr( shift ) ) ),
30313 mkexpr( vD ) ) ) );
30315 break;
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,
30328 binop( Iop_Mul32,
30329 mkU32( 8 ),
30330 mkU32( 15 - ( uim + 1 ) ) ) ) );
30332 putVReg( vD_addr,
30333 binop( Iop_OrV128,
30334 binop( Iop_ShlV128,
30335 binop( Iop_AndV128,
30336 binop( Iop_ShrV128,
30337 mkexpr( vB ),
30338 mkU8( (7 - 3)*16 ) ),
30339 binop( Iop_64HLtoV128,
30340 mkU64( 0x0ULL ),
30341 mkU64( 0xFFFFULL ) ) ),
30342 mkexpr( shift ) ),
30343 binop( Iop_AndV128,
30344 unop( Iop_NotV128,
30345 binop( Iop_ShlV128,
30346 binop( Iop_64HLtoV128,
30347 mkU64( 0x0ULL ),
30348 mkU64( 0xFFFFULL ) ),
30349 mkexpr( shift ) ) ),
30350 mkexpr( vD ) ) ) );
30352 break;
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,
30365 binop( Iop_Mul32,
30366 mkU32( 8 ),
30367 mkU32( 15 - ( uim + 3 ) ) ) ) );
30369 putVReg( vD_addr,
30370 binop( Iop_OrV128,
30371 binop( Iop_ShlV128,
30372 binop( Iop_AndV128,
30373 binop( Iop_ShrV128,
30374 mkexpr( vB ),
30375 mkU8( (3 - 1) * 32 ) ),
30376 binop( Iop_64HLtoV128,
30377 mkU64( 0x0ULL ),
30378 mkU64( 0xFFFFFFFFULL ) ) ),
30379 mkexpr( shift ) ),
30380 binop( Iop_AndV128,
30381 unop( Iop_NotV128,
30382 binop( Iop_ShlV128,
30383 binop( Iop_64HLtoV128,
30384 mkU64( 0x0ULL ),
30385 mkU64( 0xFFFFFFFFULL ) ),
30386 mkexpr( shift ) ) ),
30387 mkexpr( vD ) ) ) );
30389 break;
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,
30402 binop( Iop_Mul32,
30403 mkU32( 8 ),
30404 mkU32( 15 - ( uim + 7 ) ) ) ) );
30406 putVReg( vD_addr,
30407 binop( Iop_OrV128,
30408 binop( Iop_ShlV128,
30409 binop( Iop_AndV128,
30410 binop( Iop_ShrV128,
30411 mkexpr( vB ),
30412 mkU8( ( 1 - 0 ) * 64 ) ),
30413 binop( Iop_64HLtoV128,
30414 mkU64( 0x0ULL ),
30415 mkU64( 0xFFFFFFFFFFFFFFFFULL ) ) ),
30416 mkexpr( shift ) ),
30417 binop( Iop_AndV128,
30418 unop( Iop_NotV128,
30419 binop( Iop_ShlV128,
30420 binop( Iop_64HLtoV128,
30421 mkU64( 0x0ULL ),
30422 mkU64( 0xFFFFFFFFFFFFFFFFULL ) ),
30423 mkexpr( shift ) ) ),
30424 mkexpr( vD ) ) ) );
30426 break;
30428 /* Splat */
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))))) );
30436 break;
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))))) );
30444 break;
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,
30451 unop(Iop_V128to32,
30452 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm)))) );
30453 break;
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)) );
30458 break;
30460 case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248)
30461 DIP("vspltish v%d,%d\n", vD_addr, (Char)SIMM_8);
30462 putVReg( vD_addr,
30463 unop(Iop_Dup16x8, mkU16(extend_s_8to32(SIMM_8))) );
30464 break;
30466 case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249)
30467 DIP("vspltisw v%d,%d\n", vD_addr, (Char)SIMM_8);
30468 putVReg( vD_addr,
30469 unop(Iop_Dup32x4, mkU32(extend_s_8to32(SIMM_8))) );
30470 break;
30472 case 0x68C: // vmrgow (Merge Odd Word)
30473 DIP("vmrgow v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
30474 /* VD[0] <- VA[1]
30475 VD[1] <- VB[1]
30476 VD[2] <- VA[3]
30477 VD[3] <- VB[3]
30479 putVReg( vD_addr,
30480 binop(Iop_CatOddLanes32x4, mkexpr(vA), mkexpr(vB) ) );
30481 break;
30483 case 0x78C: // vmrgew (Merge Even Word)
30484 DIP("vmrgew v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
30485 /* VD[0] <- VA[0]
30486 VD[1] <- VB[0]
30487 VD[2] <- VA[2]
30488 VD[3] <- VB[2]
30490 putVReg( vD_addr,
30491 binop(Iop_CatEvenLanes32x4, mkexpr(vA), mkexpr(vB) ) );
30492 break;
30494 default:
30495 vex_printf("dis_av_permute(ppc)(opc2)\n");
30496 return False;
30498 return True;
30502 Vector Integer Absolute Difference
30504 static Bool dis_abs_diff ( UInt prefix, UInt theInstr )
30506 /* VX-Form */
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. */
30522 PREFIX_CHECK
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");
30529 return False;
30532 switch ( opc2 ) {
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 ) ) );
30542 assign( vAminusB,
30543 binop( Iop_AndV128,
30544 binop( Iop_Sub8x16, mkexpr( vA ), mkexpr( vB ) ),
30545 mkexpr( vMask ) ) );
30547 assign( vBminusA,
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 ) ) );
30556 break;
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 ) ) );
30567 assign( vAminusB,
30568 binop( Iop_AndV128,
30569 binop( Iop_Sub16x8, mkexpr( vA ), mkexpr( vB ) ),
30570 mkexpr( vMask ) ) );
30572 assign( vBminusA,
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 ) ) );
30581 break;
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 ) ) );
30592 assign( vAminusB,
30593 binop( Iop_AndV128,
30594 binop( Iop_Sub32x4, mkexpr( vA ), mkexpr( vB ) ),
30595 mkexpr( vMask ) ) );
30597 assign( vBminusA,
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 ) ) );
30606 break;
30608 default:
30609 return False;
30612 putVReg( vT_addr, mkexpr( vT ) );
30614 return True;
30618 AltiVec 128 bit integer multiply by 10 Instructions
30620 static Bool dis_av_mult10 ( UInt prefix, UInt theInstr )
30622 /* VX-Form */
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. */
30632 PREFIX_CHECK
30634 assign( vA, getVReg(vA_addr));
30636 if (opc1 != 0x4) {
30637 vex_printf("dis_av_mult10(ppc)(instr)\n");
30638 return False;
30640 switch (opc2) {
30641 case 0x001: { // vmul10cuq (Vector Multiply-by-10 and write carry
30642 DIP("vmul10cuq v%d,v%d\n", vT_addr, vA_addr);
30643 putVReg( vT_addr,
30644 unop( Iop_MulI128by10Carry, mkexpr( vA ) ) );
30645 break;
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);
30652 putVReg( vT_addr,
30653 binop( Iop_MulI128by10ECarry, mkexpr( vA ), mkexpr( vB ) ) );
30654 break;
30656 case 0x201: { // vmul10uq (Vector Multiply-by-10 Unsigned Quadword VX form)
30657 DIP("vmul10uq v%d,v%d\n", vT_addr, vA_addr);
30658 putVReg( vT_addr,
30659 unop( Iop_MulI128by10, mkexpr( vA ) ) );
30660 break;
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);
30667 putVReg( vT_addr,
30668 binop( Iop_MulI128by10E, mkexpr( vA ), mkexpr( vB ) ) );
30669 break;
30671 default:
30672 vex_printf("dis_av_mult10(ppc)(opc2)\n");
30673 return False;
30675 return True;
30679 AltiVec Pack/Unpack Instructions
30681 static Bool dis_av_pack ( UInt prefix, UInt theInstr )
30683 /* VX-Form */
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. */
30696 PREFIX_CHECK
30698 assign( vA, getVReg(vA_addr));
30699 assign( vB, getVReg(vB_addr));
30701 if (opc1 != 0x4) {
30702 vex_printf("dis_av_pack(ppc)(instr)\n");
30703 return False;
30705 switch (opc2) {
30706 /* Packing */
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);
30709 putVReg( vD_addr,
30710 binop(Iop_NarrowBin16to8x16, mkexpr(vA), mkexpr(vB)) );
30711 return True;
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);
30715 putVReg( vD_addr,
30716 binop(Iop_NarrowBin32to16x8, mkexpr(vA), mkexpr(vB)) );
30717 return True;
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);
30721 putVReg( vD_addr,
30722 binop(Iop_QNarrowBin16Uto8Ux16, mkexpr(vA), mkexpr(vB)) );
30723 // TODO: set VSCR[SAT]
30724 return True;
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);
30728 putVReg( vD_addr,
30729 binop(Iop_QNarrowBin32Uto16Ux8, mkexpr(vA), mkexpr(vB)) );
30730 // TODO: set VSCR[SAT]
30731 return True;
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),
30741 unop(Iop_NotV128,
30742 binop(Iop_SarN16x8,
30743 mkexpr(vA), mkU8(15)))) );
30744 assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
30745 unop(Iop_NotV128,
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]
30751 return True;
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),
30761 unop(Iop_NotV128,
30762 binop(Iop_SarN32x4,
30763 mkexpr(vA), mkU8(31)))) );
30764 assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
30765 unop(Iop_NotV128,
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]
30771 return True;
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);
30775 putVReg( vD_addr,
30776 binop(Iop_QNarrowBin16Sto8Sx16, mkexpr(vA), mkexpr(vB)) );
30777 // TODO: set VSCR[SAT]
30778 return True;
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);
30782 putVReg( vD_addr,
30783 binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(vA), mkexpr(vB)) );
30784 // TODO: set VSCR[SAT]
30785 return True;
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)),
30801 mkU8(10)) );
30802 assign( a2, binop(Iop_ShlN16x8,
30803 binop(Iop_ShrN16x8, mkexpr(vA), mkU8(11)),
30804 mkU8(5)) );
30805 assign( a3, binop(Iop_ShrN16x8,
30806 binop(Iop_ShlN16x8, mkexpr(vA), mkU8(8)),
30807 mkU8(11)) );
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)),
30813 mkU8(10)) );
30814 assign( b2, binop(Iop_ShlN16x8,
30815 binop(Iop_ShrN16x8, mkexpr(vB), mkU8(11)),
30816 mkU8(5)) );
30817 assign( b3, binop(Iop_ShrN16x8,
30818 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(8)),
30819 mkU8(11)) );
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)) );
30825 return True;
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);
30830 putVReg( vD_addr,
30831 binop(Iop_NarrowBin64to32x4, mkexpr(vA), mkexpr(vB)) );
30832 return True;
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);
30836 putVReg( vD_addr,
30837 binop(Iop_QNarrowBin64Uto32Ux4, mkexpr(vA), mkexpr(vB)) );
30838 // TODO: set VSCR[SAT]
30839 return True;
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),
30851 unop(Iop_NotV128,
30852 binop(Iop_SarN64x2,
30853 mkexpr(vA), mkU8(63)))) );
30854 assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
30855 unop(Iop_NotV128,
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]
30861 return True;
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);
30866 putVReg( vD_addr,
30867 binop(Iop_QNarrowBin64Sto32Sx4, mkexpr(vA), mkexpr(vB)) );
30868 // TODO: set VSCR[SAT]
30869 return True;
30870 default:
30871 break; // Fall through...
30875 if (vA_addr != 0) {
30876 vex_printf("dis_av_pack(ppc)(vA_addr)\n");
30877 return False;
30880 signs = newTemp(Ity_V128);
30881 zeros = newTemp(Ity_V128);
30882 assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
30884 switch (opc2) {
30885 /* Unpacking */
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)) );
30889 putVReg( vD_addr,
30890 binop(Iop_InterleaveHI8x16, mkexpr(signs), mkexpr(vB)) );
30891 break;
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)) );
30896 putVReg( vD_addr,
30897 binop(Iop_InterleaveHI16x8, mkexpr(signs), mkexpr(vB)) );
30898 break;
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)) );
30903 putVReg( vD_addr,
30904 binop(Iop_InterleaveLO8x16, mkexpr(signs), mkexpr(vB)) );
30905 break;
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)) );
30910 putVReg( vD_addr,
30911 binop(Iop_InterleaveLO16x8, mkexpr(signs), mkexpr(vB)) );
30912 break;
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)),
30926 mkU8(8)) );
30927 assign( z1, binop(Iop_ShrN16x8,
30928 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
30929 mkU8(11)) );
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)),
30935 mkU8(11)),
30936 mkU8(3)) );
30937 assign( z3, binop(Iop_ShrN16x8,
30938 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
30939 mkU8(11)) );
30940 assign( z23, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
30941 binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
30942 putVReg( vD_addr,
30943 binop(Iop_OrV128,
30944 binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
30945 mkexpr(z23)) );
30946 break;
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)),
30959 mkU8(8)) );
30960 assign( z1, binop(Iop_ShrN16x8,
30961 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
30962 mkU8(11)) );
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)),
30968 mkU8(11)),
30969 mkU8(3)) );
30970 assign( z3, binop(Iop_ShrN16x8,
30971 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
30972 mkU8(11)) );
30973 assign( z23, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
30974 binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
30975 putVReg( vD_addr,
30976 binop(Iop_OrV128,
30977 binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
30978 mkexpr(z23)) );
30979 break;
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)) );
30984 putVReg( vD_addr,
30985 binop(Iop_InterleaveHI32x4, mkexpr(signs), mkexpr(vB)) );
30986 break;
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)) );
30991 putVReg( vD_addr,
30992 binop(Iop_InterleaveLO32x4, mkexpr(signs), mkexpr(vB)) );
30993 break;
30995 default:
30996 vex_printf("dis_av_pack(ppc)(opc2)\n");
30997 return False;
30999 return True;
31003 AltiVec Cipher Instructions
31005 static Bool dis_av_cipher ( UInt prefix, UInt theInstr )
31007 /* VX-Form */
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. */
31018 PREFIX_CHECK
31020 assign( vA, getVReg(vA_addr));
31021 assign( vB, getVReg(vB_addr));
31023 if (opc1 != 0x4) {
31024 vex_printf("dis_av_cipher(ppc)(instr)\n");
31025 return False;
31027 switch (opc2) {
31028 case 0x508: // vcipher (Vector Inverser Cipher)
31029 DIP("vcipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
31030 putVReg( vD_addr,
31031 binop(Iop_CipherV128, mkexpr(vA), mkexpr(vB)) );
31032 return True;
31034 case 0x509: // vcipherlast (Vector Inverser Cipher Last)
31035 DIP("vcipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
31036 putVReg( vD_addr,
31037 binop(Iop_CipherLV128, mkexpr(vA), mkexpr(vB)) );
31038 return True;
31040 case 0x548: // vncipher (Vector Inverser Cipher)
31041 DIP("vncipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
31042 putVReg( vD_addr,
31043 binop(Iop_NCipherV128, mkexpr(vA), mkexpr(vB)) );
31044 return True;
31046 case 0x549: // vncipherlast (Vector Inverser Cipher Last)
31047 DIP("vncipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
31048 putVReg( vD_addr,
31049 binop(Iop_NCipherLV128, mkexpr(vA), mkexpr(vB)) );
31050 return True;
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);
31056 putVReg( vD_addr,
31057 unop(Iop_CipherSV128, mkexpr(vA) ) );
31058 return True;
31060 default:
31061 vex_printf("dis_av_cipher(ppc)(opc2)\n");
31062 return False;
31064 return True;
31068 AltiVec Secure Hash Instructions
31070 static Bool dis_av_hash ( UInt prefix, UInt theInstr )
31072 /* VX-Form */
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. */
31085 PREFIX_CHECK
31087 assign( vA, getVReg(vRA_addr));
31089 if (opc1 != 0x4) {
31090 vex_printf("dis_av_hash(ppc)(instr)\n");
31091 return False;
31094 switch (opc2) {
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));
31099 return True;
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) ) );
31104 return True;
31106 default:
31107 vex_printf("dis_av_hash(ppc)(opc2)\n");
31108 return False;
31110 return True;
31114 * This function is used by the Vector add/subtract [extended] modulo/carry
31115 * instructions.
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
31118 * src3.bit[127].
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;
31134 Int i;
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);
31149 switch (i) {
31150 case 0:
31151 assign(_vecA_32, unop( Iop_64to32, _vecA_low64 ) );
31152 assign(_vecB_32, unop( Iop_64to32, _vecB_low64 ) );
31153 break;
31154 case 1:
31155 assign(_vecA_32, unop( Iop_64HIto32, _vecA_low64 ) );
31156 assign(_vecB_32, unop( Iop_64HIto32, _vecB_low64 ) );
31157 break;
31158 case 2:
31159 assign(_vecA_32, unop( Iop_64to32, _vecA_high64 ) );
31160 assign(_vecB_32, unop( Iop_64to32, _vecB_high64 ) );
31161 break;
31162 case 3:
31163 assign(_vecA_32, unop( Iop_64HIto32, _vecA_high64 ) );
31164 assign(_vecB_32, unop( Iop_64HIto32, _vecB_high64 ) );
31165 break;
31168 assign( res_64, binop( Iop_Add64,
31169 binop ( Iop_Add64,
31170 binop( Iop_32HLto64,
31171 mkU32( 0 ),
31172 mkexpr(_vecA_32) ),
31173 binop( Iop_32HLto64,
31174 mkU32( 0 ),
31175 mkexpr(_vecB_32) ) ),
31176 binop( Iop_32HLto64,
31177 mkU32( 0 ),
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 ) ) );
31187 if (modulo) {
31188 result = newTemp(Ity_V128);
31189 assign(result, binop( Iop_OrV128,
31190 (i == 0) ? binop( Iop_64HLtoV128,
31191 mkU64(0),
31192 mkU64(0) ) : mkexpr(tmp_result),
31193 binop( Iop_ShlV128,
31194 binop( Iop_64HLtoV128,
31195 mkU64(0),
31196 binop( Iop_32HLto64,
31197 mkU32(0),
31198 mkexpr(res_32) ) ),
31199 mkU8(i * 32) ) ) );
31200 tmp_result = newTemp(Ity_V128);
31201 assign(tmp_result, mkexpr(result));
31204 if (modulo)
31205 return result;
31206 else
31207 return carry;
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;
31217 UInt num_bits;
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
31223 size. */
31225 switch (size) {
31226 case 8:
31227 extract_mask_hi = 0x8080808080808080ULL;
31228 extract_mask_lo = 0x8080808080808080ULL;
31229 num_bits = 8;
31230 break;
31232 case 16:
31233 extract_mask_hi = 0x8000800080008000ULL;
31234 extract_mask_lo = 0x8000800080008000ULL;
31235 num_bits = 4;
31236 break;
31238 case 32:
31239 extract_mask_hi = 0x8000000080000000ULL;
31240 extract_mask_lo = 0x8000000080000000ULL;
31241 num_bits = 2;
31242 break;
31244 case 64:
31245 extract_mask_hi = 0x8000000000000000ULL;
31246 extract_mask_lo = 0x8000000000000000ULL;
31247 num_bits = 1;
31248 break;
31250 default:
31251 /* unsupported element size */
31252 vassert(0);
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 ),
31260 mkU64( 1 ) ) );
31261 assign( ones_lo, extract_bits_under_mask ( vbi, mkexpr( src_lo ),
31262 mkU64( extract_mask_lo ),
31263 mkU64( 1 ) ) );
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
31267 IBM numbering */
31268 return binop( Iop_Or64,
31269 binop( Iop_Shl64,
31270 mkexpr( ones_hi ),
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 );
31284 UInt size;
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. */
31307 assign( vRT,
31308 binop( Iop_Sar8x16,
31309 binop( Iop_AndV128,
31310 getVReg(B_addr),
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 ) );
31316 return True;
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. */
31327 assign( vRT,
31328 binop( Iop_Sar16x8,
31329 binop( Iop_AndV128,
31330 getVReg(B_addr),
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 ) );
31336 return True;
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. */
31347 assign( vRT,
31348 binop( Iop_Sar32x4,
31349 binop( Iop_AndV128,
31350 getVReg(B_addr),
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 ) );
31356 return True;
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. */
31366 assign( vRT,
31367 binop( Iop_Sar64x2,
31368 binop( Iop_AndV128,
31369 getVReg(B_addr),
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 ) );
31375 return True;
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) ),
31384 mkU8( 63 ) ) );
31385 assign( ones,
31386 unop( Iop_1Sto64,
31387 binop( Iop_CmpEQ64,
31388 mkU64( 1 ),
31389 binop( Iop_And64,
31390 mkU64( 0x1 ),
31391 mkexpr( src ) ) ) ) );
31392 putVReg( RT_addr, binop( Iop_64HLtoV128,
31393 mkexpr( ones ), mkexpr( ones ) ) );
31395 return True;
31397 case 0x8: // vextractbm
31398 DIP("vextractbm v%u,r%u\n", RT_addr, B_addr);
31399 size = 8;
31400 putIReg( RT_addr, copy_MSB_bit_fields( getVReg( B_addr ), size, vbi ) );
31401 return True;
31403 case 0x9: // vextracthm
31404 DIP("vextracthm v%u,r%u\n", RT_addr, B_addr);
31405 size = 16;
31406 putIReg( RT_addr, copy_MSB_bit_fields( getVReg( B_addr ), size, vbi ) );
31407 return True;
31409 case 0xA: // vextractwm
31410 DIP("vextractwm v%u,r%u\n", RT_addr, B_addr );
31411 size = 32;
31412 putIReg( RT_addr, copy_MSB_bit_fields( getVReg( B_addr ), size, vbi ) );
31413 return True;
31415 case 0xB: // vextractdm
31416 DIP("vextractdm v%u,r%u\n", RT_addr, B_addr);
31417 size = 64;
31418 putIReg( RT_addr, copy_MSB_bit_fields( getVReg( B_addr ), size, vbi ) );
31419 return True;
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 ) ),
31425 mkU8 (63) ) );
31426 return True;
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
31442 elements. */
31443 assign( src_upper, binop( Iop_Shr32,
31444 binop( Iop_And32, mkU32( 0xFF00 ),
31445 unop ( Iop_64to32,
31446 getIReg( B_addr ) ) ),
31447 mkU8( 0x8 ) ) );
31448 assign( src_lower, binop( Iop_And32, mkU32( 0xFF ),
31449 unop ( Iop_64to32,
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 ),
31459 mkU8( 16 ) ) ) );
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 ),
31468 mkU8( 16 ) ) ) );
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 ) );
31489 return True;
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
31501 elements */
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 ) );
31534 return True;
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 ),
31546 unop ( Iop_64to32,
31547 getIReg( B_addr ) ) ) );
31549 assign( src2,
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,
31558 mkexpr( src2 ),
31559 mkexpr( src2 ) ),
31560 binop( Iop_32HLto64,
31561 mkexpr( src2 ),
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 ) );
31572 return True;
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 ) ),
31585 mkU8( 28 ) ) );
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,
31592 mkexpr( src32 ),
31593 mkexpr( src32 ) ),
31594 binop( Iop_32HLto64,
31595 mkexpr( src32 ),
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 ) );
31607 return True;
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,
31618 getIReg( B_addr ),
31619 mkU8( 62 ) ) );
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,
31625 mkexpr( src ),
31626 mkexpr( src ) ),
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 ) );
31637 return True;
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 ) );
31646 assign( ones,
31647 unop( Iop_1Sto64,
31648 binop( Iop_CmpEQ64,
31649 mkU64( 1 ),
31650 binop( Iop_And64,
31651 mkU64( 0x1 ),
31652 mkexpr( src ) ) ) ) );
31653 putVReg( RT_addr, binop( Iop_64HLtoV128,
31654 mkexpr( ones ), mkexpr( ones ) ) );
31655 return True;
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);
31667 size = 8;
31668 assign( bit_mask, copy_MSB_bit_fields( getVReg( B_addr ), size,
31669 vbi ) );
31671 if ( MP == 1) {
31672 assign( bit_cnt, binop( Iop_Shl64,
31673 popcnt64( vbi, mkexpr( bit_mask ) ),
31674 mkU8( 56 ) ) );
31676 } else {
31677 /* Need to complement the bit mask then count the ones. */
31678 assign( bit_cnt,
31679 binop( Iop_Shl64,
31680 popcnt64( vbi,
31681 binop( Iop_And64,
31682 mkU64( 0xFFFF ),
31683 unop( Iop_Not64,
31684 mkexpr( bit_mask ) ) ) ),
31685 mkU8( 56 ) ) );
31687 putIReg( RT_addr, mkexpr( bit_cnt ) );
31688 return True;
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);
31700 size = 16;
31701 assign( bit_mask, copy_MSB_bit_fields( getVReg( B_addr ), size,
31702 vbi ) );
31704 /* Result is in IBM bits [0:6] */
31705 if ( MP == 1) {
31706 assign( bit_cnt,
31707 binop( Iop_Shl64,
31708 popcnt64( vbi, mkexpr( bit_mask ) ),
31709 mkU8( 57 ) ) );
31711 } else {
31712 /* Need to complement the bit mask then count the ones. */
31713 assign( bit_cnt,
31714 binop( Iop_Shl64,
31715 popcnt64( vbi,
31716 binop( Iop_And64,
31717 mkU64( 0xFF ),
31718 unop( Iop_Not64,
31719 mkexpr( bit_mask ) ) ) ),
31720 mkU8( 57 ) ) );
31722 putIReg( RT_addr, mkexpr( bit_cnt ) );
31723 return True;
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);
31735 size = 32;
31736 assign( bit_mask, copy_MSB_bit_fields( getVReg( B_addr ), size,
31737 vbi) );
31739 if ( MP == 1) {
31740 assign( bit_cnt,
31741 binop( Iop_Shl64,
31742 popcnt64( vbi, mkexpr( bit_mask ) ),
31743 mkU8( 58 ) ) );
31745 } else {
31746 /* Need to complement the bit mask then count the ones. */
31747 assign( bit_cnt,
31748 binop( Iop_Shl64,
31749 popcnt64( vbi,
31750 binop( Iop_And64,
31751 mkU64( 0xF ),
31752 unop( Iop_Not64,
31753 mkexpr( bit_mask ) ) ) ),
31754 mkU8( 58 ) ) );
31756 putIReg( RT_addr, mkexpr( bit_cnt ) );
31757 return True;
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);
31769 size = 64;
31770 assign( bit_mask, copy_MSB_bit_fields( getVReg( B_addr ), size,
31771 vbi ) );
31773 /* Result is in IBM bits [0:4] */
31774 if ( MP == 1) {
31775 assign( bit_cnt,
31776 binop( Iop_Shl64,
31777 popcnt64( vbi, mkexpr( bit_mask ) ),
31778 mkU8( 59 ) ) );
31780 } else {
31781 /* Need to complement the bit mask then count the ones. */
31782 assign( bit_cnt,
31783 binop( Iop_Shl64,
31784 popcnt64( vbi,
31785 binop( Iop_And64,
31786 mkU64( 0x3 ),
31787 unop( Iop_Not64,
31788 mkexpr( bit_mask ) ) ) ),
31789 mkU8( 59 ) ) );
31791 putIReg( RT_addr, mkexpr( bit_cnt ) );
31792 return True;
31795 default:
31796 /* Unkown opc2 value for the dis_VSR_byte_mask function. */
31797 return False;
31801 static Bool dis_av_quad ( UInt prefix, UInt theInstr, const VexAbiInfo* vbi )
31803 /* VX-Form */
31804 UChar opc1 = ifieldOPC(theInstr);
31805 UChar vRT_addr = ifieldRegDS(theInstr);
31806 UChar vRA_addr = ifieldRegA(theInstr);
31807 UChar vRB_addr = ifieldRegB(theInstr);
31808 UChar vRC_addr;
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. */
31817 PREFIX_CHECK
31819 assign( vA, getVReg(vRA_addr));
31820 assign( vB, getVReg(vRB_addr));
31822 if (opc1 != 0x4) {
31823 vex_printf("dis_av_quad(ppc)(instr)\n");
31824 return False;
31827 switch (opc2) {
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),
31832 mkexpr(vB),
31833 mkU32(0), False) ) ) );
31834 return True;
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) ) );
31839 return True;
31840 case 0x540: // vsubcuq
31841 DIP("vsubcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
31842 putVReg( vRT_addr,
31843 unop( Iop_32UtoV128,
31844 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
31845 unop( Iop_NotV128,
31846 mkexpr(vB) ),
31847 mkU32(1), False) ) ) );
31848 return True;
31849 case 0x500: // vsubuqm
31850 DIP("vsubuqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
31851 putVReg( vRT_addr,
31852 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
31853 unop( Iop_NotV128, mkexpr(vB) ),
31854 mkU32(1), True) ) );
31855 return 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);
31868 assign( res_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,
31874 mkexpr(vA) ),
31875 unop( Iop_V128to64,
31876 mkexpr(vA) ),
31877 unop( Iop_V128HIto64,
31878 mkexpr(vB) ) ) ) );
31879 assign( res_1,
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,
31885 mkexpr(vA) ),
31886 unop( Iop_V128to64,
31887 mkexpr(vA) ),
31888 unop( Iop_V128to64,
31889 mkexpr(vB) ) ) ) );
31890 assign( res_hi, binop( Iop_32HLto64,
31891 mkU32( 0 ),
31892 binop( Iop_Or32,
31893 binop( Iop_Shl32, mkexpr( res_0 ),
31894 mkU8( 8 ) ),
31895 mkexpr( res_1 ) ) ) );
31897 putVReg( vRT_addr, binop( Iop_64HLtoV128, mkexpr( res_hi ), res_low ) );
31898 return True;
31901 default:
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);
31909 switch (opc2) {
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,
31913 vRC_addr);
31914 assign(cin, binop( Iop_And32,
31915 unop( Iop_64to32,
31916 unop( Iop_V128to64, mkexpr(vC) ) ),
31917 mkU32(1) ) );
31918 putVReg( vRT_addr,
31919 unop( Iop_32UtoV128,
31920 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB),
31921 mkexpr(cin),
31922 False) ) ) );
31923 return True;
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,
31927 vRC_addr);
31928 assign(cin, binop( Iop_And32,
31929 unop( Iop_64to32,
31930 unop( Iop_V128to64, mkexpr(vC) ) ),
31931 mkU32(1) ) );
31932 putVReg( vRT_addr,
31933 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB),
31934 mkexpr(cin),
31935 True) ) );
31936 return True;
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,
31940 vRC_addr);
31941 assign(cin, binop( Iop_And32,
31942 unop( Iop_64to32,
31943 unop( Iop_V128to64, mkexpr(vC) ) ),
31944 mkU32(1) ) );
31945 putVReg( vRT_addr,
31946 unop( Iop_32UtoV128,
31947 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
31948 unop( Iop_NotV128,
31949 mkexpr(vB) ),
31950 mkexpr(cin),
31951 False) ) ) );
31952 return True;
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,
31956 vRC_addr);
31957 assign(cin, binop( Iop_And32,
31958 unop( Iop_64to32,
31959 unop( Iop_V128to64, mkexpr(vC) ) ),
31960 mkU32(1) ) );
31961 putVReg( vRT_addr,
31962 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
31963 unop( Iop_NotV128, mkexpr(vB) ),
31964 mkexpr(cin),
31965 True) ) );
31966 return True;
31967 default:
31968 vex_printf("dis_av_quad(ppc)(opc2.2)\n");
31969 return False;
31972 return True;
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
31980 * per the ISA:
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
31990 * in 32-bit mode.
31992 IRTemp mask = newTemp(Ity_I64);
31993 IRExpr *rtn;
31995 if ( ps == 0 ) {
31996 /* sign code is correct, just return it. */
31997 rtn = tmp;
31999 } else {
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 ),
32005 unop( Iop_64to32,
32006 unop( Iop_V128to64, tmp )
32007 ) ) ) ) );
32008 rtn = binop( Iop_64HLtoV128,
32009 unop( Iop_V128HIto64, tmp ),
32010 binop( Iop_Or64,
32011 binop( Iop_And64, mkU64( 0xF ), mkexpr( mask ) ),
32012 unop( Iop_V128to64, tmp ) ) );
32015 return rtn;
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. */
32038 PREFIX_CHECK
32040 assign( vA, getVReg(vRA_addr));
32041 assign( vB, getVReg(vRB_addr));
32043 if (opc1 != 0x4) {
32044 vex_printf("dis_av_bcd_misc(ppc)(instr)\n");
32045 return False;
32048 switch (opc2) {
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);
32054 zero =
32055 BCDstring_zero( binop( Iop_AndV128,
32056 binop( Iop_64HLtoV128,
32057 mkU64( 0xFFFFFFFFFFFFFFFF ),
32058 mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
32059 mkexpr( vA ) ) );
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,
32068 sign,
32069 mkU64 ( 0xB ) ),
32070 binop( Iop_CmpEQ64,
32071 sign,
32072 mkU64 ( 0xD ) ) );
32074 pos = mkNOT1( neg );
32076 /* invalid if vA or vB is not valid */
32077 valid =
32078 unop( Iop_64to32,
32079 binop( Iop_And64,
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,
32087 mkU64( 0 ),
32088 mkU64( 0xF ) ),
32089 mkexpr( vB ) );
32091 value_va = binop( Iop_AndV128,
32092 binop( Iop_64HLtoV128,
32093 mkU64( 0xFFFFFFFFFFFFFFFF ),
32094 mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
32095 mkexpr( vA ) );
32096 putVReg( vRT_addr, binop( Iop_OrV128, sign_vb, value_va ) );
32098 break;
32100 default:
32101 vex_printf("dis_av_bcd_misc(ppc)(opc2)\n");
32102 return False;
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
32111 assign( eq_lt_gt,
32112 binop( Iop_Or32,
32113 binop( Iop_Shl32,
32114 unop( Iop_1Uto32,
32115 mkAND1( neg,
32116 mkNOT1( zero ) ) ),
32117 mkU8( 3 ) ),
32118 binop( Iop_Or32,
32119 binop( Iop_Shl32,
32120 unop( Iop_1Uto32,
32121 mkAND1( pos,
32122 mkNOT1( zero ) ) ),
32123 mkU8( 2 ) ),
32124 binop( Iop_Shl32,
32125 unop( Iop_1Uto32, zero ),
32126 mkU8( 1 ) ) ) ) );
32128 IRTemp valid_mask = newTemp( Ity_I32 );
32130 assign( valid_mask, unop( Iop_1Sto32, unop( Iop_32to1, valid ) ) );
32132 putGST_field( PPC_GST_CR,
32133 binop( Iop_Or32,
32134 binop( Iop_And32,
32135 mkexpr( valid_mask ),
32136 mkexpr( eq_lt_gt ) ),
32137 binop( Iop_And32,
32138 unop( Iop_Not32, mkexpr( valid_mask ) ),
32139 mkU32( 1 ) ) ),
32140 6 );
32141 return True;
32144 static Bool dis_av_bcd ( UInt prefix, UInt theInstr, const VexAbiInfo* vbi )
32146 /* VX-Form */
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. */
32161 PREFIX_CHECK
32163 assign( vA, getVReg(vRA_addr));
32164 assign( vB, getVReg(vRB_addr));
32166 if (opc1 != 0x4) {
32167 vex_printf("dis_av_bcd(ppc)(instr)\n");
32168 return False;
32171 switch (opc2) {
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,
32186 binop( Iop_BCDAdd,
32187 mkexpr( vA ),
32188 mkexpr( vB ) ) ) );
32189 } else {
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,
32192 binop( Iop_BCDSub,
32193 mkexpr( vA ),
32194 mkexpr( vB ) ) ) );
32197 putVReg( vRT_addr, mkexpr( dst ) );
32198 /* set CR field 6 */
32199 /* result */
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 ),
32207 unop( Iop_64to32,
32208 unop( Iop_V128to64, mkexpr( dst ) ) ) );
32210 sign = mkOR1( binop( Iop_CmpEQ32,
32211 sign_digit,
32212 mkU32 ( 0xB ) ),
32213 binop( Iop_CmpEQ32,
32214 sign_digit,
32215 mkU32 ( 0xD ) ) );
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,
32221 binop( Iop_And64,
32222 is_BCDstring128( vbi,
32223 /*Signed*/True, mkexpr( vA ) ),
32224 is_BCDstring128( vbi,
32225 /*Signed*/True, mkexpr( vB ) )
32226 ) );
32228 /* src A */
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 ),
32235 unop( Iop_64to32,
32236 unop( Iop_V128to64, mkexpr( vA ) ) ) );
32238 signA = mkOR1( binop( Iop_CmpEQ32,
32239 sign_digitA,
32240 mkU32 ( 0xB ) ),
32241 binop( Iop_CmpEQ32,
32242 sign_digitA,
32243 mkU32 ( 0xD ) ) );
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 ) );
32248 /* src B */
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 ),
32255 unop( Iop_64to32,
32256 unop( Iop_V128to64, mkexpr( vB ) ) ) );
32258 signB = mkOR1( binop( Iop_CmpEQ32,
32259 sign_digitB,
32260 mkU32 ( 0xB ) ),
32261 binop( Iop_CmpEQ32,
32262 sign_digitB,
32263 mkU32 ( 0xD ) ) );
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 ) );
32271 if (mode64) {
32272 res_smaller = mkAND1( CmpGT128U( mkexpr( vA ), mkexpr( dst ) ),
32273 CmpGT128U( mkexpr( vB ), mkexpr( dst ) ) );
32275 } else {
32276 /* Have to do this with 32-bit compares, expensive */
32277 res_smaller = mkAND1( UNSIGNED_CMP_GT_V128( mkexpr( vA ),
32278 mkexpr( dst ) ),
32279 UNSIGNED_CMP_GT_V128( mkexpr( vB ),
32280 mkexpr( dst ) ) );
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
32289 * occured.
32291 overflow = mkOR1( mkAND1( res_smaller, mkAND1( negA, negB ) ),
32292 mkAND1( res_smaller, mkAND1( posA, posB ) ) );
32293 } else {
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
32299 * occured.
32301 overflow = mkOR1( mkAND1( res_smaller, mkAND1( negA, posB ) ),
32302 mkAND1( res_smaller, mkAND1( posA, negB ) ) );
32305 break;
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
32311 IRExpr *shift_dir;
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 */
32336 } else {
32337 DIP("bcdus. v%d,v%d,v%d,%d\n", vRT_addr, vRA_addr,
32338 vRB_addr, ps);
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 ) ),
32347 mkexpr( vB ) );
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,
32356 mkU64( 0xFF ),
32357 mkU64( 0x0) ),
32358 mkexpr( vA ) ),
32359 mkU8( 64 ) ) ) );
32361 /* if shift_dir = 0 shift left, otherwise shift right */
32362 shift_dir = binop( Iop_CmpEQ64,
32363 binop( Iop_Shr64,
32364 mkexpr( shift_field ),
32365 mkU8( 7 ) ),
32366 mkU64( 1 ) );
32368 assign( shift_dir_mask, unop( Iop_1Sto64, shift_dir ) );
32370 /* Shift field is stored in 2's complement form */
32371 assign(shift_by,
32372 binop( Iop_Mul64,
32373 binop( Iop_Or64,
32374 binop( Iop_And64,
32375 unop( Iop_Not64,
32376 mkexpr( shift_dir_mask ) ),
32377 mkexpr( shift_field ) ),
32378 binop( Iop_And64,
32379 mkexpr( shift_dir_mask ),
32380 binop( Iop_And64,
32381 binop( Iop_Add64,
32382 mkU64( 1 ),
32383 unop( Iop_Not64,
32384 mkexpr( shift_field ) ) ),
32385 mkU64( 0xFF ) ) ) ),
32386 mkU64( 4 ) ) );
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,
32398 not_excess_shift,
32399 not_excess_shift );
32401 assign( value_shl,
32402 binop( Iop_ShlV128, value, unop( Iop_64to8,
32403 mkexpr( shift_by) ) ) );
32404 assign( value_shr,
32405 binop( Iop_AndV128,
32406 binop( Iop_64HLtoV128,
32407 mkU64( 0xFFFFFFFFFFFFFFFF ),
32408 mkU64( value_mask_low) ),
32409 binop( Iop_ShrV128,
32410 value,
32411 unop( Iop_64to8,
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
32416 * shifted out.
32418 assign( shifted_out,
32419 binop( Iop_OrV128,
32420 binop( Iop_ShrV128,
32421 value,
32422 unop( Iop_64to8,
32423 binop( Iop_Sub64,
32424 mkU64( 32*4 ),
32425 mkexpr( shift_by ) ) ) ),
32426 binop( Iop_AndV128,
32427 unop( Iop_NotV128,
32428 not_excess_shift_mask ),
32429 value ) ) );
32431 overflow = mkAND1( mkNOT1( BCDstring_zero( mkexpr( shifted_out ) ) ),
32432 mkAND1( mkNOT1( shift_dir ),
32433 binop( Iop_CmpNE64,
32434 mkexpr( shift_by ),
32435 mkU64( 0 ) ) ) );
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,
32445 sign_digit,
32446 mkU64 ( 0xB ) ),
32447 binop( Iop_CmpEQ64,
32448 sign_digit,
32449 mkU64 ( 0xD ) ) );
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 ) );
32455 valid =
32456 unop( Iop_64to32,
32457 is_BCDstring128( vbi, /* Signed */True, mkexpr( vB ) ) );
32459 } else {
32460 /* string is an unsigned BCD value */
32461 pos = mkU1( 1 );
32462 neg = mkU1( 0 );
32463 sign = mkU1( 0 );
32465 valid =
32466 unop( Iop_64to32,
32467 is_BCDstring128( vbi, /* Unsigned */False,
32468 mkexpr( vB ) ) );
32471 /* if PS = 0
32472 vB positive, sign is C
32473 vB negative, sign is D
32474 if PS = 1
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,
32478 use sign instead.
32480 if (ps == 0) {
32481 new_sign_val = binop( Iop_Or64,
32482 unop( Iop_1Uto64, sign ),
32483 mkU64( 0xC ) );
32485 } else {
32486 new_sign_val = binop( Iop_Xor64,
32487 binop( Iop_Shl64,
32488 unop( Iop_1Uto64, sign ),
32489 mkU8( 1 ) ),
32490 mkU64( 0xF ) );
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,
32506 mkU64( 0 ),
32507 new_sign_val ),
32508 binop( Iop_AndV128,
32509 not_excess_shift_mask,
32510 result ) ) );
32511 } else if (opc2 == 0x1C1) { //bcdsr.
32512 /* If shifting right, need to round up if needed */
32513 assign( round, unop( Iop_1Uto32,
32514 mkAND1( shift_dir,
32515 check_BCD_round( value,
32516 shift_by ) ) ) );
32518 putVReg( vRT_addr,
32519 binop( Iop_OrV128,
32520 binop( Iop_64HLtoV128,
32521 mkU64( 0 ),
32522 new_sign_val ),
32523 binop( Iop_AndV128,
32524 not_excess_shift_mask,
32525 mkexpr( increment_BCDstring( vbi, result,
32526 mkexpr( round)
32527 ) ) ) ) );
32528 } else { // bcdus.
32529 putVReg( vRT_addr, binop( Iop_AndV128,
32530 not_excess_shift_mask,
32531 result ) );
32534 break;
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;
32544 Int max_digits;
32546 if ( opc2 == 0x101) { // bcdtrunc.
32547 value_mask_low = 0xFFFFFFFFFFFFFFF0;
32548 max_digits = 31;
32549 } else {
32550 value_mask_low = 0xFFFFFFFFFFFFFFFF;
32551 max_digits = 32;
32554 assign( length, binop( Iop_And64,
32555 unop( Iop_V128HIto64,
32556 mkexpr( vA ) ),
32557 mkU64( 0xFFFF ) ) );
32558 shift = unop( Iop_64to8,
32559 binop( Iop_Mul64,
32560 binop( Iop_Sub64,
32561 mkU64( max_digits ),
32562 mkexpr( length ) ),
32563 mkU64( 4 ) ) );
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,
32570 mkexpr( length),
32571 mkU64( 0x1F ) ) );
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,
32579 mkexpr( vB ),
32580 unop( Iop_64to8,
32581 binop( Iop_Mul64,
32582 mkU64( 4 ),
32583 binop( Iop_Add64,
32584 mkU64( 1 ),
32585 mkexpr( length ) ) ) ) )
32586 ) );
32588 /* Overflow occurs if any of the left most 31-length digits of vB
32589 * are non-zero.
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 ) ),
32597 mkexpr( vB ) );
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 ) ),
32606 value ) );
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,
32615 sign_digit,
32616 mkU64 ( 0xB ) ),
32617 binop( Iop_CmpEQ64,
32618 sign_digit,
32619 mkU64 ( 0xD ) ) );
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,
32626 use sign instead.
32628 if (ps == 0) {
32629 new_sign_val = binop( Iop_Or64,
32630 unop( Iop_1Uto64, sign ),
32631 mkU64( 0xC ) );
32632 } else {
32633 new_sign_val = binop( Iop_Xor64,
32634 binop( Iop_Shl64,
32635 unop( Iop_1Uto64, sign ),
32636 mkU8 ( 1 ) ),
32637 mkU64( 0xF ) );
32639 valid =
32640 unop( Iop_64to32,
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 */
32648 neg = mkU1( 0 );
32650 /* Pos position AKA gt = 1 if (not eq zero) */
32651 pos = mkNOT1( zero );
32652 valid =
32653 unop( Iop_64to32,
32654 is_BCDstring128( vbi, /* Unsigned */False,
32655 mkexpr( vB ) ) );
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,
32663 mkV128( 0xFFFF ),
32664 binop( Iop_ShrV128,
32665 binop( Iop_ShlV128, value, shift ),
32666 shift ) );
32668 if ( opc2 == 0x101) { // bcdtrunc.
32669 putVReg( vRT_addr, binop( Iop_OrV128,
32670 binop( Iop_64HLtoV128,
32671 mkU64( 0 ),
32672 new_sign_val ),
32673 result ) );
32674 } else {
32675 putVReg( vRT_addr, result );
32678 break;
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)
32688 IRExpr *sign;
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 ) ),
32702 mkU64( 0xF ) );
32703 zero = mkAND1( binop( Iop_CmpEQ64,
32704 unop( Iop_V128HIto64, mkexpr( vB ) ),
32705 mkU64( 0x0 ) ),
32706 binop( Iop_CmpEQ64,
32707 binop( Iop_And64,
32708 unop( Iop_V128to64, mkexpr( vB ) ),
32709 mkU64( 0xFFFFFFF0 ) ),
32710 mkU64( 0x0 ) ) );
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 */
32725 valid =
32726 unop( Iop_64to32,
32727 is_BCDstring128( vbi, /* Signed */True,
32728 mkexpr( vB ) ) );
32729 overflow = mkU1( 0 ); // not used
32731 break;
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
32743 * vector register.
32745 putVReg( vRT_addr,
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 ),
32754 binop( Iop_And64,
32755 unop( Iop_V128HIto64,
32756 mkexpr( vB ) ),
32757 mkU64( 0x8000000000000000UL ) ) ) );
32758 neg = mkAND1( mkNOT1 ( zero ),
32759 binop( Iop_CmpEQ64, mkU64( 0x8000000000000000UL ),
32760 binop( Iop_And64,
32761 unop( Iop_V128HIto64,
32762 mkexpr( vB ) ),
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 ) ) ),
32799 mkAND1( neg,
32800 mkOR1( neg_upper_lt,
32801 mkAND1( neg_upper_eq,
32802 neg_lower_lt )
32803 ) ) );
32804 valid = mkU32( 1 );
32806 break;
32808 case 4: // bcdctz. (Decimal Convert to Zoned VX-form)
32810 IRExpr *ox_flag, *sign, *vrb_nibble30;
32811 int neg_bit_shift;
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);
32817 if (ps == 0) {
32818 upper_byte = 0x30;
32819 sign_byte = 0x30;
32820 neg_bit_shift = 4+2; /* sign byte is in bits [7:4] */
32821 } else {
32822 upper_byte = 0xF0;
32823 sign_byte = 0xC0;
32824 neg_bit_shift = 4+0;
32827 /* Grab vB bits[7:4]. It goes into bits [3:0] of the
32828 * result.
32830 vrb_nibble30 = binop( Iop_Shr64,
32831 binop( Iop_And64,
32832 unop( Iop_V128to64, mkexpr( vB ) ),
32833 mkU64( 0xF0 ) ),
32834 mkU8( 4 ) );
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,
32841 binop( Iop_And64,
32842 unop( Iop_V128to64, mkexpr( vB ) ),
32843 mkU64( 0xFFFFFFFFFFFFFFFF ) ),
32844 mkU64( 0 ) );
32846 /* zero is the same as eq_flag */
32847 zero = mkAND1( binop( Iop_CmpEQ64,
32848 binop( Iop_And64,
32849 unop( Iop_V128HIto64, mkexpr( vB ) ),
32850 mkU64( 0xFFFFFFFFFFFFFFFF ) ),
32851 mkU64( 0 ) ),
32852 binop( Iop_CmpEQ64,
32853 binop( Iop_And64,
32854 unop( Iop_V128to64, mkexpr( vB ) ),
32855 mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
32856 mkU64( 0 ) ) );
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,
32869 sign_digit,
32870 mkU64 ( 0xB ) ),
32871 binop( Iop_CmpEQ64,
32872 sign_digit,
32873 mkU64 ( 0xD ) ) );
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 ) );
32882 assign( tmp,
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.
32889 putVReg( vRT_addr,
32890 binop( Iop_OrV128,
32891 binop( Iop_64HLtoV128,
32892 mkU64( 0 ),
32893 vrb_nibble30 ),
32894 binop( Iop_OrV128,
32895 mkexpr( tmp ),
32896 binop( Iop_64HLtoV128,
32897 mkU64( 0 ),
32898 binop( Iop_Or64,
32899 mkU64( sign_byte ),
32900 binop( Iop_Shl64,
32901 unop( Iop_1Uto64,
32902 sign ),
32903 mkU8( neg_bit_shift)
32904 ) ) ) ) ) );
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,
32911 binop( Iop_And64,
32912 mkU64( 0xFFFFFFFFFFFFFFF0 ),
32913 unop( Iop_V128HIto64, mkexpr( vB ) ) ),
32914 mkU64( 0 ) );
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.
32925 valid =
32926 unop( Iop_64to32,
32927 is_BCDstring128( vbi, /* Signed */True,
32928 mkexpr( vB ) ) );
32930 break;
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 ) ),
32949 mkU64( 0 ) ),
32950 binop( Iop_CmpEQ64,
32951 binop( Iop_Shr64,
32952 unop( Iop_V128to64,
32953 mkexpr( vB ) ),
32954 mkU8( 32 ) ),
32955 mkU64( 0 ) ) );
32957 /* The sign code must be between 0xA and 0xF and all digits are
32958 * between 0x0 and 0x9.
32960 valid =
32961 unop( Iop_64to32,
32962 is_BCDstring128( vbi, /* Signed */True,
32963 mkexpr( vB ) ) );
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.
32970 ox_flag =
32971 mkNOT1( mkAND1( binop( Iop_CmpEQ64,
32972 binop( Iop_And64,
32973 unop( Iop_V128HIto64,
32974 mkexpr( vB ) ),
32975 mkU64( 0xFFFFFFFFFFFFFFFF ) ),
32976 mkU64( 0 ) ),
32977 binop( Iop_CmpEQ64,
32978 binop( Iop_And64,
32979 unop( Iop_V128to64,
32980 mkexpr( vB ) ),
32981 mkU64( 0xFFFFFFFF00000000 ) ),
32982 mkU64( 0 ) ) ) );
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
32986 * (variable pos).
32988 zero = mkAND1( binop( Iop_CmpEQ64,
32989 binop( Iop_And64,
32990 unop( Iop_V128HIto64,
32991 mkexpr( vB ) ),
32992 mkU64( 0xFFFFFFFFFFFFFFFF ) ),
32993 mkU64( 0 ) ),
32994 binop( Iop_CmpEQ64,
32995 binop( Iop_And64,
32996 unop( Iop_V128to64, mkexpr( vB ) ),
32997 mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
32998 mkU64( 0 ) ) );
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,
33010 sign_digit,
33011 mkU64 ( 0xB ) ),
33012 binop( Iop_CmpEQ64,
33013 sign_digit,
33014 mkU64 ( 0xD ) ) );
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 ) );
33023 assign( tmp,
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.
33032 putVReg( vRT_addr,
33033 binop( Iop_OrV128,
33034 mkexpr( tmp ),
33035 binop( Iop_64HLtoV128,
33036 mkU64( 0 ),
33037 binop( Iop_Or64,
33038 mkU64( 0x29 ),
33039 binop( Iop_Or64,
33040 binop( Iop_Shl64,
33041 unop( Iop_1Uto64,
33042 sign ),
33043 mkU8( 2 ) ),
33044 binop( Iop_Shl64,
33045 unop( Iop_1Uto64,
33046 mkNOT1(sign)),
33047 mkU8( 1 ) )
33048 ) ) ) ) );
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.
33054 valid =
33055 unop( Iop_64to32,
33056 is_BCDstring128( vbi, /* Signed */True,
33057 mkexpr( vB ) ) );
33059 overflow = ox_flag;
33061 break;
33063 case 6: // bcdcfz. (Decimal Convert From Zoned VX-form)
33065 IRExpr *sign;
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 ) );
33072 assign( tmp,
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.
33078 zero =
33079 binop( Iop_CmpEQ64,
33080 binop( Iop_Or64,
33081 binop( Iop_And64,
33082 unop( Iop_V128to64, mkexpr( vB ) ),
33083 mkU64( 0x0F0F0F0F0F0F0F0FULL ) ),
33084 binop( Iop_And64,
33085 unop( Iop_V128to64, mkexpr( vB ) ),
33086 mkU64( 0x0F0F0F0F0F0F0F0FULL ) ) ),
33087 mkU64( 0 ) );
33089 /* Sign bit is in bit 6 of vB. */
33090 sign_digit = binop( Iop_And64, mkU64( 0xF0 ),
33091 unop( Iop_V128to64, mkexpr( vB ) ) );
33093 if ( ps == 0 ) {
33094 /* sign will be equal to 0 for positive number */
33095 sign = binop( Iop_CmpEQ64,
33096 binop( Iop_And64,
33097 sign_digit,
33098 mkU64( 0x40 ) ),
33099 mkU64( 0x40 ) );
33100 } else {
33101 sign = mkOR1(
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 */
33119 putVReg( vRT_addr,
33120 binop( Iop_OrV128,
33121 mkexpr( tmp ),
33122 binop( Iop_64HLtoV128,
33123 mkU64( 0 ),
33124 binop( Iop_Or64,
33125 mkU64( 0xC ),
33126 unop( Iop_1Uto64, sign )
33127 ) ) ) );
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 );
33134 break;
33136 case 7: // bcdcfn. (Decimal Convert From National VX-form)
33138 IRTemp hword_7 = newTemp( Ity_I64 );
33139 IRExpr *sign;
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.
33158 zero =
33159 binop( Iop_CmpEQ64,
33160 binop( Iop_Or64,
33161 binop( Iop_And64,
33162 unop( Iop_V128HIto64, mkexpr( vB ) ),
33163 mkU64( 0x000F000F000F000FULL ) ),
33164 binop( Iop_And64,
33165 unop( Iop_V128to64, mkexpr( vB ) ),
33166 mkU64( 0x000F000F000F0000ULL ) ) ),
33167 mkU64( 0 ) );
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
33185 * flag.
33187 overflow = mkU1( 0 );
33189 /* sign of the result is:
33190 ( 0b1100 OR neg) OR (ps OR (ps AND pos) << 1 )
33193 putVReg( vRT_addr,
33194 binop( Iop_64HLtoV128,
33195 mkU64( 0 ),
33196 binop( Iop_Or64,
33197 binop( Iop_Or64,
33198 binop( Iop_Shl64,
33199 binop( Iop_And64,
33200 mkU64( ps ),
33201 unop( Iop_1Uto64,
33202 mkNOT1(sign))),
33203 mkU8( 1 ) ),
33204 mkU64( ps ) ),
33205 binop( Iop_Or64,
33206 binop( Iop_Or64,
33207 mkU64( 0xC ),
33208 unop( Iop_1Uto64, sign ) ),
33209 mkexpr( tmp ) ) ) ) );
33212 break;
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 ) ),
33224 mkexpr( vB ) );
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,
33234 sign_digit,
33235 mkU64 ( 0xB ) ),
33236 binop( Iop_CmpEQ64,
33237 sign_digit,
33238 mkU64 ( 0xD ) ) );
33239 neg = mkAND1( sign, mkNOT1( zero ) );
33241 pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) );
33243 valid =
33244 unop( Iop_64to32,
33245 is_BCDstring128( vbi, /* Signed */True,
33246 mkexpr( vB ) ) );
33248 /* if PS = 0
33249 vB positive, sign is C
33250 vB negative, sign is D
33251 if PS = 1
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.
33257 if (ps == 0) {
33258 new_sign_val = binop( Iop_Or64,
33259 unop( Iop_1Uto64, sign ),
33260 mkU64( 0xC ) );
33262 } else {
33263 new_sign_val = binop( Iop_Xor64,
33264 binop( Iop_Shl64,
33265 unop( Iop_1Uto64, sign ),
33266 mkU8( 1 ) ),
33267 mkU64( 0xF ) );
33270 putVReg( vRT_addr, binop( Iop_OrV128,
33271 binop( Iop_64HLtoV128,
33272 mkU64( 0 ),
33273 new_sign_val ),
33274 value ) );
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 ) );
33281 break;
33283 default:
33284 vex_printf("dis_av_bcd(ppc)(invalid inst_select)\n");
33285 return False;
33288 break;
33290 default:
33291 vex_printf("dis_av_bcd(ppc)(opc2)\n");
33292 return False;
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
33305 assign( eq_lt_gt,
33306 binop( Iop_Or32,
33307 binop( Iop_Shl32,
33308 unop( Iop_1Uto32, neg ),
33309 mkU8( 3 ) ),
33310 binop( Iop_Or32,
33311 binop( Iop_Shl32,
33312 unop( Iop_1Uto32, pos ),
33313 mkU8( 2 ) ),
33314 binop( Iop_Shl32,
33315 unop( Iop_1Uto32, zero ),
33316 mkU8( 1 ) ) ) ) );
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,
33321 binop( Iop_Or32,
33322 binop( Iop_And32,
33323 mkexpr( valid_mask ),
33324 binop( Iop_Or32,
33325 mkexpr( eq_lt_gt ),
33326 unop( Iop_1Uto32, overflow ) ) ),
33327 binop( Iop_And32,
33328 unop( Iop_Not32, mkexpr( valid_mask ) ),
33329 mkU32( 1 ) ) ),
33330 6 );
33331 return True;
33335 AltiVec Floating Point Arithmetic Instructions
33337 static Bool dis_av_fp_arith ( UInt prefix, UInt theInstr )
33339 /* VA-Form */
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);
33345 UInt opc2=0;
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. */
33352 PREFIX_CHECK
33354 assign( vA, getVReg(vA_addr));
33355 assign( vB, getVReg(vB_addr));
33356 assign( vC, getVReg(vC_addr));
33358 if (opc1 != 0x4) {
33359 vex_printf("dis_av_fp_arith(ppc)(instr)\n");
33360 return False;
33363 IRTemp rm = newTemp(Ity_I32);
33364 assign(rm, get_IR_roundingmode());
33366 opc2 = IFIELD( theInstr, 0, 6 );
33367 switch (opc2) {
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);
33371 putVReg( vD_addr,
33372 dnorm_adj_Vector(
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 ) ) )
33380 ) ) ) );
33381 return True;
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);
33386 putVReg( vD_addr,
33387 negate_Vector( Ity_I32,
33388 dnorm_adj_Vector(
33389 triop( Iop_Sub32Fx4,
33390 mkU32( Irrm_NEAREST ),
33391 dnorm_adj_Vector(
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 ) ) ) ) ) );
33397 return True;
33400 default:
33401 break; // Fall through...
33404 opc2 = IFIELD( theInstr, 0, 11 );
33405 switch (opc2) {
33406 case 0x00A: // vaddfp (Add FP, AV p137)
33407 DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
33408 putVReg( vD_addr,
33409 dnorm_adj_Vector( triop( Iop_Add32Fx4, mkU32( Irrm_NEAREST ),
33410 dnorm_adj_Vector( mkexpr( vA ) ),
33411 dnorm_adj_Vector( mkexpr( vB ) ) ) ) );
33412 return True;
33414 case 0x04A: // vsubfp (Subtract FP, AV p261)
33415 DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
33416 putVReg( vD_addr,
33417 dnorm_adj_Vector( triop( Iop_Sub32Fx4, mkU32( Irrm_NEAREST ),
33418 dnorm_adj_Vector( mkexpr( vA ) ),
33419 dnorm_adj_Vector( mkexpr( vB ) ) ) ) );
33420 return True;
33422 case 0x40A: // vmaxfp (Maximum FP, AV p178)
33423 DIP("vmaxfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
33424 putVReg( vD_addr,
33425 dnorm_adj_Vector( binop( Iop_Max32Fx4,
33426 mkexpr( vA ), mkexpr( vB ) ) ) );
33427 return True;
33429 case 0x44A: // vminfp (Minimum FP, AV p187)
33430 DIP("vminfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
33431 putVReg( vD_addr,
33432 dnorm_adj_Vector( binop( Iop_Min32Fx4,
33433 mkexpr( vA ), mkexpr( vB ) ) ) );
33434 return True;
33436 default:
33437 break; // Fall through...
33441 if (vA_addr != 0) {
33442 vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n");
33443 return False;
33446 switch (opc2) {
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 ) ) ) ) );
33451 return True;
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 ) ) ) ) );
33457 return True;
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
33462 implemented. */
33463 putVReg( vD_addr,
33464 dnorm_adj_Vector( unop( Iop_Exp2_32Fx4,
33465 dnorm_adj_Vector( mkexpr( vB ) ) ) ) );
33466 return True;
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
33471 implemented. */
33472 putVReg( vD_addr,
33473 dnorm_adj_Vector( unop( Iop_Log2_32Fx4,
33474 dnorm_adj_Vector( mkexpr( vB ) ) ) ) );
33475 return True;
33477 default:
33478 vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2);
33479 return False;
33481 return True;
33485 AltiVec Floating Point Compare Instructions
33487 static Bool dis_av_fp_cmp ( UInt prefix, UInt theInstr )
33489 /* VXR-Form */
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. */
33504 PREFIX_CHECK
33506 assign( vA, getVReg(vA_addr));
33507 assign( vB, getVReg(vB_addr));
33509 if (opc1 != 0x4) {
33510 vex_printf("dis_av_fp_cmp(ppc)(instr)\n");
33511 return False;
33514 switch (opc2) {
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 ) ) ) );
33521 break;
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 ) ) ) );
33529 break;
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 ) ) ) );
33537 break;
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);
33548 cmp_bounds = True;
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
33553 a nan.
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 ),
33568 mkexpr( zeros ),
33569 mkexpr( srcB ) ) ) ) );
33571 // finally, just shift gt,lt to correct position
33572 assign( vD, binop(Iop_ShlN32x4,
33573 binop(Iop_OrV128,
33574 binop(Iop_AndV128, mkexpr(gt),
33575 unop(Iop_Dup32x4, mkU32(0x2))),
33576 binop(Iop_AndV128, mkexpr(lt),
33577 unop(Iop_Dup32x4, mkU32(0x1)))),
33578 mkU8(30)) );
33579 break;
33582 default:
33583 vex_printf("dis_av_fp_cmp(ppc)(opc2)\n");
33584 return False;
33587 putVReg( vD_addr, mkexpr(vD) );
33589 if (flag_rC) {
33590 set_AV_CR6( mkexpr(vD), !cmp_bounds );
33592 return True;
33596 AltiVec Floating Point Convert/Round Instructions
33598 static Bool dis_av_fp_convert ( UInt prefix, UInt theInstr )
33600 /* VX-Form */
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. */
33614 PREFIX_CHECK
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;
33622 assign( vInvScale,
33623 unop(Iop_Dup32x4, mkU32( float_to_bits(inv_scale) )) );
33625 if (opc1 != 0x4) {
33626 vex_printf("dis_av_fp_convert(ppc)(instr)\n");
33627 return False;
33630 switch (opc2) {
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)) );
33636 return True;
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)) );
33644 return True;
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);
33648 putVReg( vD_addr,
33649 unop(Iop_QF32toI32Ux4_RZ,
33650 triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
33651 mkexpr(vB), mkexpr(vScale))) );
33652 return True;
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);
33656 putVReg( vD_addr,
33657 unop(Iop_QF32toI32Sx4_RZ,
33658 triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
33659 mkexpr(vB), mkexpr(vScale))) );
33660 return True;
33662 default:
33663 break; // Fall through...
33666 if (UIMM_5 != 0) {
33667 vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n");
33668 return False;
33671 switch (opc2) {
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 ) ) ) );
33676 break;
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 ) ) ) );
33682 break;
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 ) ) ) );
33688 break;
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 ) ) ) );
33694 break;
33696 default:
33697 vex_printf("dis_av_fp_convert(ppc)(opc2)\n");
33698 return False;
33700 return True;
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. */
33710 PREFIX_CHECK
33712 switch (opc2) {
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 );
33727 ULong tm_reason;
33728 UInt failure_code = 0; /* Forcing failure, will not be due to tabort
33729 * or treclaim.
33731 UInt persistant = 1; /* set persistant since we are always failing
33732 * the tbegin.
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
33751 * to tbegin.)
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 );
33761 return True;
33763 break;
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);
33771 break;
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);
33779 break;
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);
33787 break;
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);
33797 break;
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);
33807 break;
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);
33817 break;
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);
33827 break;
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);
33835 break;
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);
33843 break;
33846 case 0x3EE: { //trechkpt.
33847 /* The trechkpt. is just a noop. Do nothing */
33848 DIP("trechkpt.\n");
33849 break;
33852 default:
33853 vex_printf("dis_transactional_memory(ppc): unrecognized instruction\n");
33854 return False;
33857 return True;
33861 /* The 0x3C primary opcode (VSX category) uses several different forms of
33862 * extended opcodes:
33863 * o XX2-form:
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])
33869 * o XX-4 form:
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
33877 * format.
33879 * The get_VSX60_opc2() function uses the vsx_insn array below to obtain the
33880 * secondary opcode for such VSX instructions.
33885 struct vsx_insn {
33886 UInt opcode;
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" },
33894 { 0x18, "xxsel" },
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
34072 * are sorted.
34074 static Int findVSXextOpCode_xx2(UInt opcode)
34076 Int low, mid, high;
34077 low = 0;
34078 high = VSX_XX2_LEN - 1;
34079 while (low <= high) {
34080 mid = (low + high)/2;
34081 if (opcode < vsx_xx2[mid].opcode)
34082 high = mid - 1;
34083 else if (opcode > vsx_xx2[mid].opcode)
34084 low = mid + 1;
34085 else
34086 return mid;
34088 return -1;
34091 static Int findVSXextOpCode_xx3(UInt opcode)
34093 Int low, mid, high;
34094 low = 0;
34095 high = VSX_XX3_LEN - 1;
34096 while (low <= high) {
34097 mid = (low + high)/2;
34098 if (opcode < vsx_xx3[mid].opcode)
34099 high = mid - 1;
34100 else if (opcode > vsx_xx3[mid].opcode)
34101 low = mid + 1;
34102 else
34103 return mid;
34105 return -1;
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
34111 * below.
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
34123 Int ret;
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
34129 return 0x396;
34130 else if (( ret = findVSXextOpCode_xx3(opc2_full & XX3_1_MASK)) >= 0)
34131 return vsx_xx3[ret].opcode;
34132 else {
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.
34146 default: break;
34149 vsxExtOpcode = opc2_full & XX3_4_MASK;
34151 switch (vsxExtOpcode) {
34152 case 0x8: return vsxExtOpcode; // xxsldwi
34153 case 0x28: return vsxExtOpcode; // xxpermdi
34154 default: break;
34157 vsxExtOpcode = opc2_full & XX3_5_MASK;
34159 switch (vsxExtOpcode) {
34160 case 0x354: return vsxExtOpcode; // xvtstdcsp
34161 case 0x3D4: return vsxExtOpcode; // xvtstdcdp
34162 default: break;
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" );
34174 return 0;
34177 static Bool dis_vec_extract_insert ( UInt prefix, UInt theInstr )
34179 /* VA-Form */
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,
34205 getIReg(rC_addr),
34206 mkU64( index_mask ) ) );
34207 switch (opc2) {
34209 case 0x18:
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 */
34214 assign( index0,
34215 binop( Iop_Sub64,
34216 mkU64( max_index_in_src ), mkexpr( byte_index ) ) );
34217 assign( res_tmp, extractBytefromV256( vA, vB, index0 ) );
34218 break;
34220 case 0x19:
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 ) );
34225 break;
34227 case 0x1A:
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 */
34236 assign( index0,
34237 binop( Iop_Sub64,
34238 mkU64( max_index_in_src ), mkexpr( byte_index ) ) );
34239 assign( index1, binop( Iop_Sub64, mkexpr( index0 ), mkU64( 1 ) ) );
34240 assign( res_tmp,
34241 binop( Iop_Or64,
34242 extractBytefromV256( vA, vB, index1 ),
34243 binop( Iop_Shl64,
34244 extractBytefromV256( vA, vB, index0 ),
34245 mkU8( 8 ) ) ) );
34247 break;
34249 case 0x1B:
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 ) ) );
34259 assign( res_tmp,
34260 binop( Iop_Or64,
34261 extractBytefromV256( vA, vB, index0 ),
34262 binop( Iop_Shl64,
34263 extractBytefromV256( vA, vB, index1 ),
34264 mkU8( 8 ) ) ) );
34266 break;
34268 case 0x1C:
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 */
34279 assign( index0,
34280 binop( Iop_Sub64,
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 ) ) );
34285 assign( res_tmp,
34286 binop( Iop_Or64,
34287 binop( Iop_Or64,
34288 extractBytefromV256( vA, vB, index3 ),
34289 binop( Iop_Shl64,
34290 extractBytefromV256( vA, vB, index2 ),
34291 mkU8( 8 ) ) ),
34292 binop( Iop_Or64,
34293 binop( Iop_Shl64,
34294 extractBytefromV256( vA, vB, index1 ),
34295 mkU8( 16 ) ),
34296 binop( Iop_Shl64,
34297 extractBytefromV256( vA, vB, index0 ),
34298 mkU8( 24 ) ) ) ) );
34300 break;
34302 case 0x1D:
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 ) ) );
34316 assign( res_tmp,
34317 binop( Iop_Or64,
34318 binop( Iop_Or64,
34319 extractBytefromV256( vA, vB, index0 ),
34320 binop( Iop_Shl64,
34321 extractBytefromV256( vA, vB, index1 ),
34322 mkU8( 8 ) ) ),
34323 binop( Iop_Or64,
34324 binop( Iop_Shl64,
34325 extractBytefromV256( vA, vB, index2 ),
34326 mkU8( 16 ) ),
34327 binop( Iop_Shl64,
34328 extractBytefromV256( vA, vB, index3 ),
34329 mkU8( 24 ) ) ) ) );
34331 break;
34332 case 0x1E:
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 */
34347 assign( index0,
34348 binop( Iop_Sub64,
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 ) ) );
34357 assign( res_tmp,
34358 binop( Iop_Or64,
34359 binop( Iop_Or64,
34360 binop( Iop_Or64,
34361 extractBytefromV256( vA, vB, index7 ),
34362 binop( Iop_Shl64,
34363 extractBytefromV256( vA, vB,
34364 index6 ),
34365 mkU8( 8 ) ) ),
34366 binop( Iop_Or64,
34367 binop( Iop_Shl64,
34368 extractBytefromV256( vA, vB,
34369 index5 ),
34370 mkU8( 16 ) ),
34371 binop( Iop_Shl64,
34372 extractBytefromV256( vA, vB,
34373 index4 ),
34374 mkU8( 24 ) ) ) ),
34375 binop( Iop_Or64,
34376 binop( Iop_Or64,
34377 binop( Iop_Shl64,
34378 extractBytefromV256( vA, vB,
34379 index3 ),
34380 mkU8( 32 ) ),
34381 binop( Iop_Shl64,
34382 extractBytefromV256( vA, vB,
34383 index2 ),
34384 mkU8( 40 ) ) ),
34385 binop( Iop_Or64,
34386 binop( Iop_Shl64,
34387 extractBytefromV256( vA, vB,
34388 index1 ),
34389 mkU8( 48 ) ),
34390 binop( Iop_Shl64,
34391 extractBytefromV256( vA, vB,
34392 index0 ),
34393 mkU8( 56 ) ) ) ) ) );
34395 break;
34397 case 0x1F:
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 ) ) );
34419 assign( res_tmp,
34420 binop( Iop_Or64,
34421 binop( Iop_Or64,
34422 binop( Iop_Or64,
34423 extractBytefromV256( vA, vB, index0 ),
34424 binop( Iop_Shl64,
34425 extractBytefromV256( vA, vB,
34426 index1 ),
34427 mkU8( 8 ) ) ),
34428 binop( Iop_Or64,
34429 binop( Iop_Shl64,
34430 extractBytefromV256( vA, vB,
34431 index2 ),
34432 mkU8( 16 ) ),
34433 binop( Iop_Shl64,
34434 extractBytefromV256( vA, vB,
34435 index3 ),
34436 mkU8( 24 ) ) ) ),
34437 binop( Iop_Or64,
34438 binop( Iop_Or64,
34439 binop( Iop_Shl64,
34440 extractBytefromV256( vA, vB,
34441 index4 ),
34442 mkU8( 32 ) ),
34443 binop( Iop_Shl64,
34444 extractBytefromV256( vA, vB,
34445 index5 ),
34446 mkU8( 40 ) ) ),
34447 binop( Iop_Or64,
34448 binop( Iop_Shl64,
34449 extractBytefromV256( vA, vB,
34450 index6 ),
34451 mkU8( 48 ) ),
34452 binop( Iop_Shl64,
34453 extractBytefromV256( vA, vB,
34454 index7 ),
34455 mkU8( 56 ) ) ) ) ) );
34457 break;
34459 default:
34460 vex_printf("dis_vec_extract_insert\n");
34461 return False;
34464 putVSReg( vT_addr, binop( Iop_64HLtoV128,
34465 mkexpr( res_tmp ),
34466 mkU64( 0 ) ) );
34468 return True;
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);
34482 UInt cc_field = 6;
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 ) ) );
34495 if (opc2 == 0x18D)
34496 inst_sel = opc2;
34498 else if (opc2 == 0x1CD)
34499 inst_sel = opc2;
34501 switch(inst_sel) {
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;
34510 dir = 0;
34512 } else {
34513 DIP("vstribr%s v%u,v%u\n", Rc ? ".":"", vT_addr, vB_addr);
34514 shift_first = Iop_ShrV128;
34515 dir = 1;
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,
34526 Ity_I8 ) ) );
34527 assign( sh_index,
34528 binop( Iop_And32,
34529 unop( Iop_1Sto32,
34530 binop( Iop_CmpLE32U,
34531 mkexpr( index ),
34532 mkU32( 16 ) ) ),
34533 binop( Iop_Sub32,
34534 mkU32( 16 ),
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,
34541 mkexpr( mask ),
34542 unop( Iop_32to8,
34543 binop( Iop_Mul32,
34544 mkU32( 8 ),
34545 mkexpr( sh_index ) ) ) ),
34546 mkexpr( vB ) ) );
34548 if (Rc)
34549 /* The returned index was between 1 and 16 if a null was found. */
34550 assign( cc, binop( Iop_Shl32,
34551 unop( Iop_1Uto32,
34552 binop( Iop_CmpLE32U,
34553 mkexpr( index ), mkU32( 16 ) ) ),
34554 mkU8( 1 ) ) );
34556 break;
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;
34566 dir = 0;
34568 } else {
34569 DIP("vstrihr%s v%u,v%u\n", Rc ? ".":"", vT_addr, vB_addr);
34570 shift_first = Iop_ShrV128;
34571 dir = 1;
34574 assign( vB, getVReg( vB_addr ) );
34575 assign( index, unop( Iop_8Uto32,
34576 locate_vector_ele_eq( vB, mkU64( 0 ), dir,
34577 Ity_I16 ) ) );
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
34582 of the bits.
34584 assign( sh_index,
34585 binop( Iop_And32,
34586 unop( Iop_1Sto32,
34587 binop( Iop_CmpLE32U,
34588 mkexpr( index ),
34589 mkU32( 8 ) ) ),
34590 binop( Iop_Sub32,
34591 mkU32( 8 ),
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,
34598 mkexpr( mask ),
34599 unop( Iop_32to8,
34600 binop( Iop_Mul32,
34601 mkU32( 16 ),
34602 mkexpr( sh_index ) ) ) ),
34603 mkexpr( vB ) ) );
34605 if (Rc)
34606 /* The returned index was between 1 and 16 if a null was found. */
34607 assign( cc, binop( Iop_Shl32,
34608 unop( Iop_1Uto32,
34609 binop( Iop_CmpLE32U,
34610 mkexpr( index ), mkU32( 8 ) ) ),
34611 mkU8( 1 ) ) );
34613 break;
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;
34629 } else {
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. */
34640 assign( shift,
34641 unop( Iop_32to8,
34642 binop( Iop_And32,
34643 binop( Iop_Mul32,
34644 mkU32( 8 ),
34645 binop( Iop_Sub32,
34646 mkU32( 16 ),
34647 unop( Iop_64to32,
34648 mkexpr( rB ) ) ) ),
34649 unop( Iop_Not32,
34650 unop( Iop_1Sto32,
34651 binop( Iop_CmpLT32S,
34652 mkU32( 16 ),
34653 unop( Iop_64to32,
34654 mkexpr( rB ) ) ) ) )
34655 ) ) );
34657 /* Clear all bits if rB > 16 */
34658 assign( clear_result,
34659 binop( Iop_Or64,
34660 unop( Iop_1Sto64,
34661 binop( Iop_CmpLE32S,
34662 unop( Iop_8Uto32, mkexpr( shift ) ),
34663 mkU32( 127 ) ) ),
34664 unop( Iop_1Sto64,
34665 binop( Iop_CmpLT32S,
34666 mkU32( 16 ),
34667 unop( Iop_64to32,
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.
34674 assign( vT,
34675 binop( Iop_AndV128,
34676 binop( Iop_AndV128,
34677 binop( shift_second,
34678 binop( shift_first,
34679 mkexpr( mask ),
34680 mkexpr( shift ) ),
34681 mkexpr( shift ) ),
34682 mkexpr( vA ) ),
34683 binop( Iop_64HLtoV128, mkexpr( clear_result ),
34684 mkexpr( clear_result ) ) ) );
34686 break;
34688 default:
34689 vex_printf("dis_string_isolate(isnt_sel = %d)\n", inst_sel);
34690 return False;
34693 if (Rc)
34694 putGST_field( PPC_GST_CR, mkexpr( cc ), cc_field );
34696 putVReg( vT_addr, mkexpr( vT ) );
34697 return True;
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]
34709 UInt i;
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)))
34716 return False;
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,
34732 mkU64( 0x1 ),
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,
34738 mkU64( 1 ),
34739 mkexpr( tmp128[i] ) ) ) );
34740 assign( all_false[i+1], mkAND1 ( mkexpr( all_false[i] ),
34741 binop( Iop_CmpEQ64,
34742 mkU64( 0 ),
34743 mkexpr( tmp128[i] ) ) ) );
34746 assign( cc, binop( Iop_Or32,
34747 binop( Iop_Shl32,
34748 unop( Iop_1Uto32,
34749 mkexpr( all_true[MAX_FIELDS] ) ),
34750 mkU8( 3 ) ),
34751 binop( Iop_Shl32,
34752 unop( Iop_1Uto32,
34753 mkexpr( all_false[MAX_FIELDS] ) ),
34754 mkU8( 1 ) ) ) );
34756 putGST_field( PPC_GST_CR, mkexpr( cc ), BF );
34757 return True;
34758 #undef MAX_FIELDS
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. */
34781 switch ( XO ) {
34782 case XVI4GER8:
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 );
34788 break;
34789 case XVI4GER8PP:
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 );
34795 break;
34796 case XVI8GER4:
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 );
34802 break;
34803 case XVI8GER4PP:
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 );
34809 break;
34810 case XVI8GER4SPP:
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 );
34816 break;
34817 case XVI16GER2S:
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 );
34823 break;
34824 case XVI16GER2SPP:
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 );
34830 break;
34831 case XVI16GER2:
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 );
34837 break;
34838 case XVI16GER2PP:
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 );
34844 break;
34846 case XVF16GER2:
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 );
34853 break;
34854 case XVF16GER2PP:
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 );
34861 break;
34862 case XVF16GER2PN:
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 );
34869 break;
34870 case XVF16GER2NP:
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 );
34877 break;
34878 case XVF16GER2NN:
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 );
34885 break;
34886 case XVBF16GER2:
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 );
34893 break;
34894 case XVBF16GER2PP:
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 );
34901 break;
34902 case XVBF16GER2PN:
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 );
34909 break;
34910 case XVBF16GER2NP:
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 );
34917 break;
34918 case XVBF16GER2NN:
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 );
34925 break;
34926 case XVF32GER:
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 );
34933 break;
34934 case XVF32GERPP:
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 );
34941 break;
34942 case XVF32GERPN:
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 );
34949 break;
34950 case XVF32GERNP:
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 );
34957 break;
34958 case XVF32GERNN:
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 );
34965 break;
34966 case XVF64GER:
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 );
34973 break;
34974 case XVF64GERPP:
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 );
34981 break;
34982 case XVF64GERPN:
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 );
34989 break;
34990 case XVF64GERNP:
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 );
34997 break;
34998 case XVF64GERNN:
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 );
35005 break;
35006 default:
35007 vex_printf("ERROR, dis_vsx_accumulator_prefix, Unknown X0 = 0x%x value.\n", XO);
35008 return False;
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);
35018 switch ( XO ) {
35019 case XVI4GER8:
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 );
35031 break;
35032 case XVI4GER8PP:
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 );
35043 break;
35044 case XVI8GER4:
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 );
35055 break;
35056 case XVI8GER4PP:
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 );
35067 break;
35068 case XVI8GER4SPP:
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 );
35079 break;
35080 case XVI16GER2:
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 );
35091 break;
35092 case XVI16GER2PP:
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 );
35103 break;
35104 case XVI16GER2S:
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 );
35115 break;
35116 case XVI16GER2SPP:
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 );
35127 break;
35128 case XVBF16GER2:
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 );
35139 break;
35140 case XVBF16GER2PP:
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 );
35151 break;
35152 case XVBF16GER2PN:
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 );
35163 break;
35164 case XVBF16GER2NP:
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 );
35175 break;
35176 case XVBF16GER2NN:
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 );
35187 break;
35188 case XVF16GER2:
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 );
35199 break;
35200 case XVF16GER2PP:
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 );
35211 break;
35212 case XVF16GER2PN:
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 );
35223 break;
35224 case XVF16GER2NP:
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 );
35235 break;
35236 case XVF16GER2NN:
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 );
35247 break;
35248 case XVF32GER:
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 );
35258 break;
35259 case XVF32GERPP:
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 );
35269 break;
35270 case XVF32GERPN:
35271 PMSK = 0;
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 );
35280 break;
35281 case XVF32GERNP:
35282 PMSK = 0;
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 );
35291 break;
35292 case XVF32GERNN:
35293 PMSK = 0;
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 );
35302 break;
35303 case XVF64GER:
35304 PMSK = 0;
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 )
35312 | XO ),
35313 ACC_mapped_on_VSR );
35314 break;
35315 case XVF64GERPP:
35316 PMSK = 0;
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 )
35324 | XO ),
35325 ACC_mapped_on_VSR );
35326 break;
35327 case XVF64GERPN:
35328 PMSK = 0;
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 )
35336 | XO ),
35337 ACC_mapped_on_VSR );
35338 break;
35339 case XVF64GERNP:
35340 PMSK = 0;
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 )
35348 | XO ),
35349 ACC_mapped_on_VSR );
35350 break;
35351 case XVF64GERNN:
35352 PMSK = 0;
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 )
35360 | XO ),
35361 ACC_mapped_on_VSR );
35362 break;
35363 default:
35364 return False;
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 );
35397 } else {
35398 vex_printf("ERROR, dis_vsx_accumulator_prefix, Unknown instruction theInstr = 0x%x\n",
35399 theInstr);
35400 return False;
35403 return True;
35406 static Bool dis_vector_generate_pvc_from_mask ( UInt prefix,
35407 UInt theInstr,
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 ) );
35418 switch( opc2 ) {
35419 case 0x394:
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 );
35424 break;
35426 case 0x395:
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 );
35431 break;
35433 case 0x3B4:
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 );
35438 break;
35440 case 0x3B5:
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 );
35445 break;
35447 default:
35448 return False;
35451 return True;
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);
35466 IRExpr** args;
35467 IRDirty* d;
35468 UInt mFx = Ifx_None;
35469 IRTemp helper_rtn = newTemp(Ity_I32);
35471 /* There is no prefixed version of these instructions. */
35472 PREFIX_CHECK
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");
35478 return False;
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
35485 guest state. */
35487 if (( opc2 == 0x306 ) && ( L == 1 )) { // copy
35488 DIP("copy %u,%u\n", rA_addr, rB_addr);
35489 operation = COPY_INST;
35490 mFx = Ifx_Read;
35492 } else if ( opc2 == 0x346 ) { // cpabort
35493 DIP("cpabort\n");
35494 operation = CPABORT_INST;
35495 /* Abort data transfer if one is in progress. */
35496 /* cpabort does nothing to the guest state, just resets operation
35497 on the host. */
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;
35514 mFx = Ifx_Write;
35516 } else {
35517 /* Unknown instruction, should never get here. */
35518 return False;
35521 /* Call dirty helper to issue the copy, paste or cpabort instruction on the
35522 host. */
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 (
35532 helper_rtn,
35533 0/*regparms*/,
35534 "copy_paste_abort_dirty_helper",
35535 fnptr_to_fnentry( vbi, &copy_paste_abort_dirty_helper ),
35536 args );
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. */
35540 d->mAddr = NULL;
35542 if (mFx != Ifx_None) {
35543 d->mFx = mFx;
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. */
35552 stmt( IRStmt_Exit(
35553 binop(Iop_CmpNE32, binop( Iop_And32, mkexpr(helper_rtn),
35554 mkU32(0xFF00)),
35555 mkU32(0)),
35556 Ijk_SigTRAP,
35557 mode64 ? IRConst_U64(guest_CIA_curr_instr) :
35558 IRConst_U32((UInt) guest_CIA_curr_instr),
35559 OFFB_CIA
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
35584 state. */
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) ) );
35596 return True;
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;
35609 prefix[6:7] = 3;
35610 prefix[8:11] = 0;
35611 prefix[14:31] = 0;
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;
35623 /* valid */
35624 pDIP( is_prefix, "nop\n");
35625 return True;
35627 return False;
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 );
35637 IRDirty* d;
35639 /* L Format or returned value
35640 0 0 || CRN_32bits
35641 1 CRN_64bits (0 to 0xFFFF_FFFF_FFFF_FFFE)
35642 2 RRN_64bits (0 to 0xFFFF_FFFF_FFFF_FFFE)
35643 3 reserved
35645 On error, return 0xFFFFFFFFFFFFFFFF
35646 A CRN value is a conditioned random number that was processed
35647 to to reduce bias.
35649 /* There is no prefixed version of these instructions. */
35650 PREFIX_CHECK
35651 DIP("darn r%u,%u\n", rD_addr, L);
35653 if (L == 3)
35654 /* Hardware reports illegal instruction if L = 3. */
35655 return False;
35657 IRExpr** args = mkIRExprVec_1( mkU32( L ) );
35659 d = unsafeIRDirty_1_N (
35661 0/*regparms*/,
35662 "darn_dirty_helper",
35663 fnptr_to_fnentry( vbi, &darn_dirty_helper ),
35664 args );
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
35670 memory. */
35671 stmt( IRStmt_Dirty(d) );
35672 putIReg( rD_addr, mkexpr( rD ) );
35673 return True;
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]. */
35688 static
35689 DisResult disInstr_PPC_WRK (
35690 Long delta64,
35691 const VexArchInfo* archinfo,
35692 const VexAbiInfo* abiinfo,
35693 Bool sigill_diag
35696 UChar opc1;
35697 UInt opc2;
35698 UInt opc3;
35699 DisResult dres;
35700 UInt theInstr;
35701 UInt prefix;
35702 IRType ty = mode64 ? Ity_I64 : Ity_I32;
35703 UInt hwcaps = archinfo->hwcaps;
35704 UInt inst_size = WORD_INST_SIZE; //Default
35705 Long delta;
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;
35716 Bool is_prefix;
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
35730 file. */
35731 Bool ACC_mapped_on_VSR = True;
35733 /* What insn variants are we supporting today? */
35734 if (mode64) {
35735 allow_F = True;
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;
35745 } else {
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;
35766 dres.len = 0;
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
35772 and have done. */
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:
35784 32-bit mode:
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
35789 64-bit mode:
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;
35811 if (!reported) {
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");
35814 reported = True;
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");
35823 delta += 20;
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;
35829 else
35830 if (getUIntPPCendianly(code+16) == 0x7C421378 /* or 2,2,2 */) {
35831 /* %R3 = guest_NRADDR */
35832 DIP("r3 = guest_NRADDR\n");
35833 delta += 20;
35834 dres.len = 20;
35835 putIReg(3, IRExpr_Get( OFFB_NRADDR, ty ));
35836 goto decode_success;
35838 else
35839 if (getUIntPPCendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) {
35840 delta += 20;
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));
35847 } else {
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;
35858 else
35859 if (getUIntPPCendianly(code+16) == 0x7C842378 /* or 4,4,4 */) {
35860 /* %R3 = guest_NRADDR_GPR2 */
35861 DIP("r3 = guest_NRADDR_GPR2\n");
35862 delta += 20;
35863 dres.len = 20;
35864 putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty ));
35865 goto decode_success;
35867 else
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);
35872 else
35873 vex_inject_ir(irsb, Iend_LE);
35875 delta += 20;
35876 dres.len = 20;
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
35881 // time.
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;
35897 /*NOTREACHED*/
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 )) {
35910 int ret;
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
35917 prefix = theInstr;
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);
35923 if (ret == True)
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
35935 switch (opc1) {
35937 /* Integer Arithmetic Instructions */
35938 case 0x0E: // addi
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
35955 case 0x1A: // xori
35956 if (dis_int_logic( prefix, theInstr )) goto decode_success;
35957 goto decode_failure;
35959 case 0x1B:
35960 if ( !is_prefix ) { // oris
35961 if (dis_int_logic( prefix, theInstr )) goto decode_success;
35963 goto decode_failure;
35965 case 0x19:
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 */
35984 case 0x20: // lwz
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;
35999 } else { // lwz
36000 if (dis_int_load_prefix( prefix, theInstr ))
36001 goto decode_success;
36003 goto decode_failure;
36006 case 0x22: // lbz
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;
36032 } else {
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 */
36040 case 0x24:
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;
36051 case 0x26:
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;
36062 case 0x2C:
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;
36077 case 0x28:
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;
36088 case 0x29:
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 */
36129 case 0x2E:
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;
36138 case 0x2F:
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,
36156 sigill_diag))
36157 goto decode_success;
36158 goto decode_failure;
36160 /* Trap Instructions */
36161 case 0x02: // tdi
36162 if (!mode64) goto decode_failure;
36163 if (dis_trapi( prefix, theInstr, &dres)) goto decode_success;
36164 goto decode_failure;
36166 case 0x03: // twi
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 */
36176 case 0x30:
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;
36186 case 0x31: // lfsu
36187 if (!allow_F) goto decode_noF;
36188 if (dis_fp_load( prefix, theInstr )) goto decode_success;
36189 goto decode_failure;
36191 case 0x32:
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;
36207 case 0x33:
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;
36213 } else { // lfdu
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 */
36220 case 0x34:
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;
36235 case 0x36:
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;
36250 case 0x37:
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 */
36262 case 0x38:
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;
36281 } else {
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;
36294 case 0x3D:
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 )) {
36336 // ld [30:31] = 0
36337 // ldu [30:31] = 1
36338 // lwa [30:31] = 2
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;
36347 case 0x3B:
36348 if (!allow_F) goto decode_noF;
36349 opc2 = ifieldOPClo10(theInstr);
36351 switch (opc2) {
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
36374 if (!allow_VX)
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)
36399 if (!allow_VX)
36400 goto decode_noVX;
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 );
36411 switch (opc2) {
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 );
36427 switch (opc2) {
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;
36447 default:
36448 break; /* fall through to next opc2 check */
36451 opc2 = IFIELD(theInstr, 1, 5);
36452 switch (opc2) {
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;
36462 case 0x18: // fres
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;
36478 default:
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;
36518 } else {
36519 vex_printf("ERROR, dis_vsx_accumulator_prefix, unknown opc2 = 0x%x\n",
36520 opc2);
36521 goto decode_failure;
36524 } else {
36525 // lxacc
36526 if (dis_vsx_accumulator_prefix( prefix, theInstr, abiinfo,
36527 ACC_mapped_on_VSR ) )
36528 goto decode_success;
36529 goto decode_failure;
36531 break;
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);
36553 UInt vsxOpc2;
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,
36573 allow_isa_3_0))
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,
36584 allow_isa_3_0))
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,
36595 abiinfo ))
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);
36608 switch (vsxOpc2) {
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,
36640 allow_isa_3_0 ))
36641 goto decode_success;
36642 goto decode_failure;
36644 case 0x3B6: {
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,
36656 allow_isa_3_0 ))
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;
36764 default:
36765 goto decode_failure;
36767 break;
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)) {
36780 // std [30:31] = 0
36781 // stdu [30:31] = 1
36782 // stq [30:31] = 2
36783 if (dis_int_store_ds_prefix( prefix, theInstr, abiinfo ))
36784 goto decode_success;
36786 } else {
36787 vex_printf("No mapping for instruction, opc1 = 0x3E, theInstr = 0x%x\n",
36788 theInstr);
36791 goto decode_failure;
36793 case 0x3F:
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);
36807 switch (opc2) {
36808 /* Floating Point Arith Instructions */
36809 case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd
36810 case 0x19: // fmul
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;
36828 case 0x18: // fre
36829 if (!allow_GX) goto decode_noGX;
36830 if (dis_fp_arith( prefix, theInstr )) goto decode_success;
36831 goto decode_failure;
36833 default:
36834 break; // Fall through
36837 opc2 = IFIELD(theInstr, 1, 8);
36838 switch (opc2) {
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;
36845 default:
36846 break; // Fall through
36849 opc2 = IFIELD(theInstr, 1, 10);
36850 UInt inst_select = IFIELD( theInstr, 16, 5 );
36852 switch (opc2) {
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
36947 case 0x048: // fmr
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,
36973 theInstr,
36974 abiinfo ) )
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,
37019 theInstr,
37020 abiinfo ) )
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,
37027 xscvsqqp. */
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,
37036 theInstr,
37037 abiinfo ) )
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,
37044 theInstr,
37045 abiinfo ) )
37046 goto decode_success;
37047 goto decode_failure;
37049 default:
37050 break; // Fall through...
37053 opc2 = ifieldOPClo9( theInstr );
37054 switch (opc2) {
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;
37067 default:
37068 break;
37071 opc2 = ifieldOPClo8( theInstr );
37072 switch (opc2) {
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;
37092 default:
37093 goto decode_failure;
37095 break;
37097 case 0x13:
37099 opc2 = ifieldOPClo5(theInstr);
37100 switch (opc2) {
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);
37111 switch (opc2) {
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;
37132 default:
37133 goto decode_failure;
37135 break;
37137 case 0x1F:
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);
37149 switch (opc2) {
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;
37198 default:
37199 break; // Fall through...
37202 /* All remaining opcodes use full 10 bits. */
37204 opc2 = IFIELD(theInstr, 1, 10);
37205 switch (opc2) {
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;
37215 case 0xDB: // brh
37216 case 0x9B: // brw
37217 case 0xBB: // brd
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]),
37277 abiinfo, &dres))
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
37299 case 0x218: // srw
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
37307 case 0x21B: // srd
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;
37356 if (stopHere) {
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,
37405 archinfo ))
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 */
37415 case 0x004: // tw
37416 if (dis_trap( prefix, theInstr, &dres )) goto decode_success;
37417 goto decode_failure;
37419 case 0x044: // td
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;
37468 /* AV Load */
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;
37476 /* AV Store */
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;
37483 /* VSX Load */
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;
37521 /* VSX Store */
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;
37577 default:
37578 /* Deal with some other cases that we would otherwise have
37579 punted on. */
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 );
37588 putIReg(
37590 IRExpr_ITE( binop(Iop_CmpNE32, getCRbit( bi ), mkU32(0)),
37591 rA == 0 ? (mode64 ? mkU64(0) : mkU32(0))
37592 : getIReg(rA),
37593 getIReg(rB))
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);
37602 switch (opc2) {
37603 case 0x1BD:
37604 if (!mode64) goto decode_failure;
37605 if (dis_int_logic( prefix, theInstr )) goto decode_success;
37606 goto decode_failure;
37608 default:
37609 goto decode_failure;
37611 break;
37614 case 0x04:
37615 /* AltiVec instructions */
37617 opc2 = IFIELD(theInstr, 1, 5);
37618 switch (opc2) {
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;
37625 break;
37627 default:
37628 break; // Fall through...
37631 opc2 = IFIELD(theInstr, 0, 6);
37632 switch (opc2) {
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 */
37670 case 0x2A: // vsel
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;
37695 default:
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
37703 * field.
37705 switch (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;
37715 default:
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);
37733 switch (opc2) {
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;
37846 /* AV Logic */
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;
37859 /* AV Rotate */
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
37975 // vnegw, vnegd
37976 // vprtybw, vprtybd, vprtybq
37977 // vctzb, vctzh, vctzw, vctzd
37978 // vextsd2q
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,
37984 allow_isa_3_0 ))
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,
38016 abiinfo ))
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;
38041 default:
38042 break; // Fall through...
38045 opc2 = IFIELD(theInstr, 0, 10);
38046 switch (opc2) {
38048 /* AV Compare */
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;
38073 default:
38074 goto decode_failure;
38076 break;
38078 default:
38079 goto decode_failure;
38081 decode_noF:
38082 vassert(!allow_F);
38083 if (sigill_diag)
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",
38087 theInstr);
38088 goto not_supported;
38089 decode_noV:
38090 vassert(!allow_V);
38091 if (sigill_diag)
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",
38097 theInstr);
38098 goto not_supported;
38099 decode_noVX:
38100 vassert(!allow_VX);
38101 if (sigill_diag)
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",
38105 theInstr);
38106 goto not_supported;
38107 decode_noFX:
38108 vassert(!allow_FX);
38109 if (sigill_diag)
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",
38113 theInstr);
38114 goto not_supported;
38115 decode_noGX:
38116 vassert(!allow_GX);
38117 if (sigill_diag)
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",
38121 theInstr);
38122 goto not_supported;
38123 decode_noDFP:
38124 vassert(!allow_DFP);
38125 if (sigill_diag)
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",
38129 theInstr);
38130 goto not_supported;
38131 decode_noP8:
38132 vassert(!allow_isa_2_07);
38133 if (sigill_diag)
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",
38137 theInstr);
38138 goto not_supported;
38140 decode_noP9:
38141 vassert(!allow_isa_3_0);
38142 if (sigill_diag)
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",
38146 theInstr);
38147 goto not_supported;
38149 decode_noIsa3_1:
38150 vassert(!allow_isa_3_1);
38151 if (sigill_diag)
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;
38157 decode_failure:
38158 /* All decode failures end up here. */
38159 opc1 = ifieldOPC(theInstr);
38160 opc2 = (theInstr) & 0x7FF;
38161 if (sigill_diag) {
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);
38169 } else {
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);
38177 not_supported:
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
38182 now. */
38183 putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) );
38184 dres.len = 0;
38185 dres.whatNext = Dis_StopHere;
38186 dres.jk_StopHere = Ijk_NoDecode;
38187 return dres;
38188 } /* switch (opc) for the main (primary) opcode switch. */
38190 decode_success:
38191 /* All decode successes end up here. */
38192 switch (dres.whatNext) {
38193 case Dis_Continue:
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));
38197 break;
38198 case Dis_StopHere:
38199 break;
38200 default:
38201 vassert(0);
38203 DIP("\n");
38205 if (dres.len == 0) {
38206 dres.len = inst_size; //Tell Valgrind the size of the instruction just excuted
38207 } else {
38208 vassert(dres.len == 20);
38210 return dres;
38213 #undef DIP
38214 #undef DIS
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,
38226 Long delta,
38227 Addr guest_IP,
38228 VexArch guest_arch,
38229 const VexArchInfo* archinfo,
38230 const VexAbiInfo* abiinfo,
38231 VexEndness host_endness_IN,
38232 Bool sigill_diag_IN )
38234 IRType ty;
38235 DisResult dres;
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");
38246 dres.len = 0;
38247 dres.whatNext = Dis_StopHere;
38248 dres.jk_StopHere = Ijk_NoDecode;
38249 dres.hint = Dis_HintNone;
38250 return dres;
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;
38263 if (mode64) {
38264 vassert((hwcaps_guest & mask32) == 0);
38265 } else {
38266 vassert((hwcaps_guest & mask64) == 0);
38269 /* Set globals (see top of this file) */
38270 guest_code = guest_code_IN;
38271 irsb = irsb_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 );
38279 return dres;
38282 /*--------------------------------------------------------------------*/
38283 /*--- end guest_ppc_toIR.c ---*/
38284 /*--------------------------------------------------------------------*/