1
2 /*--------------------------------------------------------------------*/
3 /*--- begin guest_ppc_toIR.c ---*/
4 /*--------------------------------------------------------------------*/
5
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
10 Copyright (C) 2004-2015 OpenWorks LLP
11 info@open-works.net
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 02110-1301, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29
30 Neither the names of the U.S. Department of Energy nor the
31 University of California nor the names of its contributors may be
32 used to endorse or promote products derived from this software
33 without prior written permission.
34 */
35
36 /* TODO 18/Nov/05:
37
38 Spot rld... cases which are simply left/right shifts and emit
39 Shl64/Shr64 accordingly.
40
41 Altivec
42 - datastream insns
43 - lvxl,stvxl: load/store with 'least recently used' hint
44 - vexptefp, vlogefp
45
46 LIMITATIONS:
47
48 Various, including:
49
50 - Some invalid forms of lswi and lswx are accepted when they should
51 not be.
52
53 - Floating Point:
54 - All exceptions disabled in FPSCR
55 - condition codes not set in FPSCR
56
57 - Altivec floating point:
58 - vmaddfp, vnmsubfp
59 Because we're using Java/IEEE mode (FPSCR[NJ]), rather than the
60 system default of Non-Java mode, we get some small errors
61 (lowest bit only).
62 This is because Non-Java mode brutally hacks denormalised results
63 to zero, whereas we keep maximum accuracy. However, using
64 Non-Java mode would give us more inaccuracy, as our intermediate
65 results would then be zeroed, too.
66
67 - AbiHints for the stack red zone are only emitted for
68 unconditional calls and returns (bl, blr). They should also be
69 emitted for conditional calls and returns, but we don't have a
70 way to express that right now. Ah well.
71
72 - Uses of Iop_{Add,Sub,Mul}32Fx4: the backend (host_ppc_isel.c)
73 ignores the rounding mode, and generates code that assumes
74 round-to-nearest. This means V will compute incorrect results
75 for uses of these IROps when the rounding mode (first) arg is
76 not mkU32(Irrm_NEAREST).
77 */
78
79 /* "Special" instructions.
80
81 This instruction decoder can decode four special instructions
82 which mean nothing natively (are no-ops as far as regs/mem are
83 concerned) but have meaning for supporting Valgrind. A special
84 instruction is flagged by a 16-byte preamble:
85
86 32-bit mode: 5400183E 5400683E 5400E83E 5400983E
87 (rlwinm 0,0,3,0,31; rlwinm 0,0,13,0,31;
88 rlwinm 0,0,29,0,31; rlwinm 0,0,19,0,31)
89
90 64-bit mode: 78001800 78006800 7800E802 78009802
91 (rotldi 0,0,3; rotldi 0,0,13;
92 rotldi 0,0,61; rotldi 0,0,51)
93
94 Following that, one of the following 3 are allowed
95 (standard interpretation in parentheses):
96
97 7C210B78 (or 1,1,1) %R3 = client_request ( %R4 )
98 7C421378 (or 2,2,2) %R3 = guest_NRADDR
99 7C631B78 (or 3,3,3) branch-and-link-to-noredir %R11 Big endian
100 7C631B78 (or 3,3,3) branch-and-link-to-noredir %R12 Little endian
101 7C842378 (or 4,4,4) %R3 = guest_NRADDR_GPR2
102 7CA52B78 (or 5,5,5) IR injection
103
104 Any other bytes following the 16-byte preamble are illegal and
105 constitute a failure in instruction decoding. This all assumes
106 that the preamble will never occur except in specific code
107 fragments designed for Valgrind to catch.
108 */
109
110 /* Little Endian notes */
111 /*
112 * Vector operations in little Endian mode behave in non-obvious ways at times.
113 * Below is an attempt at explaining this.
114 *
115 * LE/BE vector example
116 * With a vector of unsigned ints declared as follows:
117 * vector unsigned int vec_inA =
118 { 0x11111111, 0x22222222, 0x33333333, 0x44444444 };
119 * The '0x11111111' word is word zero in both LE and BE format. But the
120 * loaded vector register will have word zero on the far left in BE mode and
121 * on the far right in LE mode. The lvx and stvx instructions work naturally
122 * for whatever endianness is in effect. For example, in LE mode, the stvx
123 * stores word zero (far right word) of the vector at the lowest memory
124 * address of the EA; in BE mode, stvx still stores word zero at the lowest
125 * memory address, but with word zero interpreted as the one at the far left
126 * of the register.
127 *
128 * The lxvd2x and stxvd2x instructions are not so well suited for LE mode.
129 * When the compiler generates an lxvd2x instruction to load the
130 * above-declared vector of unsigned integers, it loads the vector as two
131 * double words, but they are in BE word-wise format. To put the vector in
132 * the right order for LE, the compiler also generates an xxswapd after the
133 * load, which puts it in proper LE format. Similarly, the stxvd2x
134 * instruction has a BE bias, storing the vector in BE word-wise format. But
135 * the compiler also generates an xxswapd prior to the store, thus ensuring
136 * the vector is stored in memory in the correct LE order.
137 *
138 * Vector-flavored Iops, such Iop_V128Hito64, reference the hi and lo parts
139 * of a double words and words within a vector. Because of the reverse order
140 * of numbering for LE as described above, the high part refers to word 1 in
141 * LE format. When input data is saved to a guest state vector register
142 * (e.g., via Iop_64HLtoV128), it is first saved to memory and then the
143 * register is loaded via PPCInstr_AvLdSt, which does an lvx instruction.
144 * The saving of the data to memory must be done in proper LE order. For the
145 * inverse operation of extracting data from a vector register (e.g.,
146 * Iop_V128Hito64), the register is first saved (by PPCInstr_AvLdSt resulting
147 * in stvx), and then integer registers are loaded from the memory location
148 * from where the vector register was saved. Again, this must be done in
149 * proper LE order. So for these various vector Iops, we have LE-specific
150 * code in host_ppc_isel.c
151 *
152 * Another unique behavior of vectors in LE mode is with the vector scalar
153 * (VSX) operations that operate on "double word 0" of the source register,
154 * storing the result in "double word 0" of the output vector register. For
155 * these operations, "double word 0" is interpreted as "high half of the
156 * register" (i.e, the part on the left side).
157 *
158 */
159 /* Translates PPC32/64 code to IR. */
160
161 /* References
162
163 #define PPC32
164 "PowerPC Microprocessor Family:
165 The Programming Environments Manual for 32-Bit Microprocessors"
166 02/21/2000
167 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2
168
169 #define PPC64
170 "PowerPC Microprocessor Family:
171 Programming Environments Manual for 64-Bit Microprocessors"
172 06/10/2003
173 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/F7E732FF811F783187256FDD004D3797
174
175 #define AV
176 "PowerPC Microprocessor Family:
177 AltiVec(TM) Technology Programming Environments Manual"
178 07/10/2003
179 http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/FBFA164F824370F987256D6A006F424D
180 */
181
182 #include "libvex_basictypes.h"
183 #include "libvex_ir.h"
184 #include "libvex.h"
185 #include "libvex_emnote.h"
186 #include "libvex_guest_ppc32.h"
187 #include "libvex_guest_ppc64.h"
188
189 #include "main_util.h"
190 #include "main_globals.h"
191 #include "guest_generic_bb_to_IR.h"
192 #include "guest_ppc_defs.h"
193
194 /*------------------------------------------------------------*/
195 /*--- Globals ---*/
196 /*------------------------------------------------------------*/
197
198 /* These are set at the start of the translation of an insn, right
199 down in disInstr_PPC, so that we don't have to pass them around
200 endlessly. They are all constant during the translation of any
201 given insn. */
202
203 /* We need to know this to do sub-register accesses correctly. */
204 static VexEndness host_endness;
205
206 /* Pointer to the guest code area. */
207 static const UChar* guest_code;
208
209 /* The guest address corresponding to guest_code[0]. */
210 static Addr64 guest_CIA_bbstart;
211
212 /* The guest address for the instruction currently being
213 translated. */
214 static Addr64 guest_CIA_curr_instr;
215
216 /* The IRSB* into which we're generating code. */
217 static IRSB* irsb;
218
219 /* Is our guest binary 32 or 64bit? Set at each call to
220 disInstr_PPC below. */
221 static Bool mode64 = False;
222
223 // Given a pointer to a function as obtained by "& functionname" in C,
224 // produce a pointer to the actual entry point for the function. For
225 // most platforms it's the identity function. Unfortunately, on
226 // ppc64-linux it isn't (sigh)
fnptr_to_fnentry(const VexAbiInfo * vbi,void * f)227 static void* fnptr_to_fnentry( const VexAbiInfo* vbi, void* f )
228 {
229 if (vbi->host_ppc_calls_use_fndescrs) {
230 /* f is a pointer to a 3-word function descriptor, of which the
231 first word is the entry address. */
232 /* note, this is correct even with cross-jitting, since this is
233 purely a host issue, not a guest one. */
234 HWord* fdescr = (HWord*)f;
235 return (void*)(fdescr[0]);
236 } else {
237 /* Simple; "& f" points directly at the code for f. */
238 return f;
239 }
240 }
241
242 #define SIGN_BIT 0x8000000000000000ULL
243 #define SIGN_MASK 0x7fffffffffffffffULL
244 #define SIGN_BIT32 0x80000000
245 #define SIGN_MASK32 0x7fffffff
246
247
248 /*------------------------------------------------------------*/
249 /*--- Debugging output ---*/
250 /*------------------------------------------------------------*/
251
252 #define DIP(format, args...) \
253 if (vex_traceflags & VEX_TRACE_FE) \
254 vex_printf(format, ## args)
255
256 #define DIS(buf, format, args...) \
257 if (vex_traceflags & VEX_TRACE_FE) \
258 vex_sprintf(buf, format, ## args)
259
260
261 /*------------------------------------------------------------*/
262 /*--- Offsets of various parts of the ppc32/64 guest state ---*/
263 /*------------------------------------------------------------*/
264
265 #define offsetofPPCGuestState(_x) \
266 (mode64 ? offsetof(VexGuestPPC64State, _x) : \
267 offsetof(VexGuestPPC32State, _x))
268
269 #define OFFB_CIA offsetofPPCGuestState(guest_CIA)
270 #define OFFB_IP_AT_SYSCALL offsetofPPCGuestState(guest_IP_AT_SYSCALL)
271 #define OFFB_SPRG3_RO offsetofPPCGuestState(guest_SPRG3_RO)
272 #define OFFB_LR offsetofPPCGuestState(guest_LR)
273 #define OFFB_CTR offsetofPPCGuestState(guest_CTR)
274 #define OFFB_XER_SO offsetofPPCGuestState(guest_XER_SO)
275 #define OFFB_XER_OV offsetofPPCGuestState(guest_XER_OV)
276 #define OFFB_XER_CA offsetofPPCGuestState(guest_XER_CA)
277 #define OFFB_XER_BC offsetofPPCGuestState(guest_XER_BC)
278 #define OFFB_FPROUND offsetofPPCGuestState(guest_FPROUND)
279 #define OFFB_DFPROUND offsetofPPCGuestState(guest_DFPROUND)
280 #define OFFB_VRSAVE offsetofPPCGuestState(guest_VRSAVE)
281 #define OFFB_VSCR offsetofPPCGuestState(guest_VSCR)
282 #define OFFB_EMNOTE offsetofPPCGuestState(guest_EMNOTE)
283 #define OFFB_CMSTART offsetofPPCGuestState(guest_CMSTART)
284 #define OFFB_CMLEN offsetofPPCGuestState(guest_CMLEN)
285 #define OFFB_NRADDR offsetofPPCGuestState(guest_NRADDR)
286 #define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2)
287 #define OFFB_TFHAR offsetofPPCGuestState(guest_TFHAR)
288 #define OFFB_TEXASR offsetofPPCGuestState(guest_TEXASR)
289 #define OFFB_TEXASRU offsetofPPCGuestState(guest_TEXASRU)
290 #define OFFB_TFIAR offsetofPPCGuestState(guest_TFIAR)
291 #define OFFB_PPR offsetofPPCGuestState(guest_PPR)
292 #define OFFB_PSPB offsetofPPCGuestState(guest_PSPB)
293
294
295 /*------------------------------------------------------------*/
296 /*--- Extract instruction fields --- */
297 /*------------------------------------------------------------*/
298
299 /* Extract field from insn, given idx (zero = lsb) and field length */
300 #define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1))
301
302 /* Extract primary opcode, instr[31:26] */
ifieldOPC(UInt instr)303 static UChar ifieldOPC( UInt instr ) {
304 return toUChar( IFIELD( instr, 26, 6 ) );
305 }
306
307 /* Extract 10-bit secondary opcode, instr[10:1] */
ifieldOPClo10(UInt instr)308 static UInt ifieldOPClo10 ( UInt instr) {
309 return IFIELD( instr, 1, 10 );
310 }
311
312 /* Extract 9-bit secondary opcode, instr[9:1] */
ifieldOPClo9(UInt instr)313 static UInt ifieldOPClo9 ( UInt instr) {
314 return IFIELD( instr, 1, 9 );
315 }
316
317 /* Extract 8-bit secondary opcode, instr[8:1] */
ifieldOPClo8(UInt instr)318 static UInt ifieldOPClo8 ( UInt instr) {
319 return IFIELD( instr, 1, 8 );
320 }
321
322 /* Extract 5-bit secondary opcode, instr[5:1] */
ifieldOPClo5(UInt instr)323 static UInt ifieldOPClo5 ( UInt instr) {
324 return IFIELD( instr, 1, 5 );
325 }
326
327 /* Extract RD (destination register) field, instr[25:21] */
ifieldRegDS(UInt instr)328 static UChar ifieldRegDS( UInt instr ) {
329 return toUChar( IFIELD( instr, 21, 5 ) );
330 }
331
332 /* Extract XT (destination register) field, instr[0,25:21] */
ifieldRegXT(UInt instr)333 static UChar ifieldRegXT ( UInt instr )
334 {
335 UChar upper_bit = toUChar (IFIELD (instr, 0, 1));
336 UChar lower_bits = toUChar (IFIELD (instr, 21, 5));
337 return (upper_bit << 5) | lower_bits;
338 }
339
340 /* Extract XS (store source register) field, instr[0,25:21] */
ifieldRegXS(UInt instr)341 static inline UChar ifieldRegXS ( UInt instr )
342 {
343 return ifieldRegXT ( instr );
344 }
345
346 /* Extract RA (1st source register) field, instr[20:16] */
ifieldRegA(UInt instr)347 static UChar ifieldRegA ( UInt instr ) {
348 return toUChar( IFIELD( instr, 16, 5 ) );
349 }
350
351 /* Extract XA (1st source register) field, instr[2,20:16] */
ifieldRegXA(UInt instr)352 static UChar ifieldRegXA ( UInt instr )
353 {
354 UChar upper_bit = toUChar (IFIELD (instr, 2, 1));
355 UChar lower_bits = toUChar (IFIELD (instr, 16, 5));
356 return (upper_bit << 5) | lower_bits;
357 }
358
359 /* Extract RB (2nd source register) field, instr[15:11] */
ifieldRegB(UInt instr)360 static UChar ifieldRegB ( UInt instr ) {
361 return toUChar( IFIELD( instr, 11, 5 ) );
362 }
363
364 /* Extract XB (2nd source register) field, instr[1,15:11] */
ifieldRegXB(UInt instr)365 static UChar ifieldRegXB ( UInt instr )
366 {
367 UChar upper_bit = toUChar (IFIELD (instr, 1, 1));
368 UChar lower_bits = toUChar (IFIELD (instr, 11, 5));
369 return (upper_bit << 5) | lower_bits;
370 }
371
372 /* Extract RC (3rd source register) field, instr[10:6] */
ifieldRegC(UInt instr)373 static UChar ifieldRegC ( UInt instr ) {
374 return toUChar( IFIELD( instr, 6, 5 ) );
375 }
376
377 /* Extract XC (3rd source register) field, instr[3,10:6] */
ifieldRegXC(UInt instr)378 static UChar ifieldRegXC ( UInt instr )
379 {
380 UChar upper_bit = toUChar (IFIELD (instr, 3, 1));
381 UChar lower_bits = toUChar (IFIELD (instr, 6, 5));
382 return (upper_bit << 5) | lower_bits;
383 }
384
385 /* Extract bit 10, instr[10] */
ifieldBIT10(UInt instr)386 static UChar ifieldBIT10 ( UInt instr ) {
387 return toUChar( IFIELD( instr, 10, 1 ) );
388 }
389
390 /* Extract 2nd lowest bit, instr[1] */
ifieldBIT1(UInt instr)391 static UChar ifieldBIT1 ( UInt instr ) {
392 return toUChar( IFIELD( instr, 1, 1 ) );
393 }
394
395 /* Extract lowest bit, instr[0] */
ifieldBIT0(UInt instr)396 static UChar ifieldBIT0 ( UInt instr ) {
397 return toUChar( instr & 0x1 );
398 }
399
400 /* Extract unsigned bottom half, instr[15:0] */
ifieldUIMM16(UInt instr)401 static UInt ifieldUIMM16 ( UInt instr ) {
402 return instr & 0xFFFF;
403 }
404
405 /* Extract unsigned bottom 26 bits, instr[25:0] */
ifieldUIMM26(UInt instr)406 static UInt ifieldUIMM26 ( UInt instr ) {
407 return instr & 0x3FFFFFF;
408 }
409
410 /* Extract DM field, instr[9:8] */
ifieldDM(UInt instr)411 static UChar ifieldDM ( UInt instr ) {
412 return toUChar( IFIELD( instr, 8, 2 ) );
413 }
414
415 /* Extract SHW field, instr[9:8] */
ifieldSHW(UInt instr)416 static inline UChar ifieldSHW ( UInt instr )
417 {
418 return ifieldDM ( instr );
419 }
420
421 /*------------------------------------------------------------*/
422 /*--- Guest-state identifiers ---*/
423 /*------------------------------------------------------------*/
424
425 typedef enum {
426 PPC_GST_CIA, // Current Instruction Address
427 PPC_GST_LR, // Link Register
428 PPC_GST_CTR, // Count Register
429 PPC_GST_XER, // Overflow, carry flags, byte count
430 PPC_GST_CR, // Condition Register
431 PPC_GST_FPSCR, // Floating Point Status/Control Register
432 PPC_GST_VRSAVE, // Vector Save/Restore Register
433 PPC_GST_VSCR, // Vector Status and Control Register
434 PPC_GST_EMWARN, // Emulation warnings
435 PPC_GST_CMSTART,// For icbi: start of area to invalidate
436 PPC_GST_CMLEN, // For icbi: length of area to invalidate
437 PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn
438 PPC_GST_SPRG3_RO, // SPRG3
439 PPC_GST_TFHAR, // Transactional Failure Handler Address Register
440 PPC_GST_TFIAR, // Transactional Failure Instruction Address Register
441 PPC_GST_TEXASR, // Transactional EXception And Summary Register
442 PPC_GST_TEXASRU, // Transactional EXception And Summary Register Upper
443 PPC_GST_PPR, // Program Priority register
444 PPC_GST_PPR32, // Upper 32-bits of Program Priority register
445 PPC_GST_PSPB, /* Problem State Priority Boost register, Note, the
446 * register is initialized to a non-zero value. Currently
447 * Valgrind is not supporting the register value to
448 * automatically decrement. Could be added later if
449 * needed.
450 */
451 PPC_GST_MAX
452 } PPC_GST;
453
454 #define MASK_FPSCR_RN 0x3ULL // Binary floating point rounding mode
455 #define MASK_FPSCR_DRN 0x700000000ULL // Decimal floating point rounding mode
456 #define MASK_VSCR_VALID 0x00010001
457
458
459 /*------------------------------------------------------------*/
460 /*--- FP Helpers ---*/
461 /*------------------------------------------------------------*/
462
463 /* Produce the 32-bit pattern corresponding to the supplied
464 float. */
float_to_bits(Float f)465 static UInt float_to_bits ( Float f )
466 {
467 union { UInt i; Float f; } u;
468 vassert(4 == sizeof(UInt));
469 vassert(4 == sizeof(Float));
470 vassert(4 == sizeof(u));
471 u.f = f;
472 return u.i;
473 }
474
475
476 /*------------------------------------------------------------*/
477 /*--- Misc Helpers ---*/
478 /*------------------------------------------------------------*/
479
480 /* Generate mask with 1's from 'begin' through 'end',
481 wrapping if begin > end.
482 begin->end works from right to left, 0=lsb
483 */
MASK32(UInt begin,UInt end)484 static UInt MASK32( UInt begin, UInt end )
485 {
486 UInt m1, m2, mask;
487 vassert(begin < 32);
488 vassert(end < 32);
489 m1 = ((UInt)(-1)) << begin;
490 m2 = ((UInt)(-1)) << end << 1;
491 mask = m1 ^ m2;
492 if (begin > end) mask = ~mask; // wrap mask
493 return mask;
494 }
495
MASK64(UInt begin,UInt end)496 static ULong MASK64( UInt begin, UInt end )
497 {
498 ULong m1, m2, mask;
499 vassert(begin < 64);
500 vassert(end < 64);
501 m1 = ((ULong)(-1)) << begin;
502 m2 = ((ULong)(-1)) << end << 1;
503 mask = m1 ^ m2;
504 if (begin > end) mask = ~mask; // wrap mask
505 return mask;
506 }
507
nextInsnAddr(void)508 static Addr64 nextInsnAddr( void )
509 {
510 return guest_CIA_curr_instr + 4;
511 }
512
513
514 /*------------------------------------------------------------*/
515 /*--- Helper bits and pieces for deconstructing the ---*/
516 /*--- ppc32/64 insn stream. ---*/
517 /*------------------------------------------------------------*/
518
519 /* Add a statement to the list held by "irsb". */
stmt(IRStmt * st)520 static void stmt ( IRStmt* st )
521 {
522 addStmtToIRSB( irsb, st );
523 }
524
525 /* Generate a new temporary of the given type. */
newTemp(IRType ty)526 static IRTemp newTemp ( IRType ty )
527 {
528 vassert(isPlausibleIRType(ty));
529 return newIRTemp( irsb->tyenv, ty );
530 }
531
532 /* Various simple conversions */
533
extend_s_5to8(UChar x)534 static UChar extend_s_5to8 ( UChar x )
535 {
536 return toUChar((((Int)x) << 27) >> 27);
537 }
538
extend_s_8to32(UChar x)539 static UInt extend_s_8to32( UChar x )
540 {
541 return (UInt)((((Int)x) << 24) >> 24);
542 }
543
extend_s_16to32(UInt x)544 static UInt extend_s_16to32 ( UInt x )
545 {
546 return (UInt)((((Int)x) << 16) >> 16);
547 }
548
extend_s_16to64(UInt x)549 static ULong extend_s_16to64 ( UInt x )
550 {
551 return (ULong)((((Long)x) << 48) >> 48);
552 }
553
extend_s_26to64(UInt x)554 static ULong extend_s_26to64 ( UInt x )
555 {
556 return (ULong)((((Long)x) << 38) >> 38);
557 }
558
extend_s_32to64(UInt x)559 static ULong extend_s_32to64 ( UInt x )
560 {
561 return (ULong)((((Long)x) << 32) >> 32);
562 }
563
564 /* Do a proper-endian load of a 32-bit word, regardless of the endianness
565 of the underlying host. */
getUIntPPCendianly(const UChar * p)566 static UInt getUIntPPCendianly ( const UChar* p )
567 {
568 UInt w = 0;
569 if (host_endness == VexEndnessBE) {
570 w = (w << 8) | p[0];
571 w = (w << 8) | p[1];
572 w = (w << 8) | p[2];
573 w = (w << 8) | p[3];
574 } else {
575 w = (w << 8) | p[3];
576 w = (w << 8) | p[2];
577 w = (w << 8) | p[1];
578 w = (w << 8) | p[0];
579 }
580 return w;
581 }
582
583
584 /*------------------------------------------------------------*/
585 /*--- Helpers for constructing IR. ---*/
586 /*------------------------------------------------------------*/
587
assign(IRTemp dst,IRExpr * e)588 static void assign ( IRTemp dst, IRExpr* e )
589 {
590 stmt( IRStmt_WrTmp(dst, e) );
591 }
592
593 /* This generates a normal (non store-conditional) store. */
store(IRExpr * addr,IRExpr * data)594 static void store ( IRExpr* addr, IRExpr* data )
595 {
596 IRType tyA = typeOfIRExpr(irsb->tyenv, addr);
597 vassert(tyA == Ity_I32 || tyA == Ity_I64);
598
599 if (host_endness == VexEndnessBE)
600 stmt( IRStmt_Store(Iend_BE, addr, data) );
601 else
602 stmt( IRStmt_Store(Iend_LE, addr, data) );
603 }
604
unop(IROp op,IRExpr * a)605 static IRExpr* unop ( IROp op, IRExpr* a )
606 {
607 return IRExpr_Unop(op, a);
608 }
609
binop(IROp op,IRExpr * a1,IRExpr * a2)610 static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
611 {
612 return IRExpr_Binop(op, a1, a2);
613 }
614
triop(IROp op,IRExpr * a1,IRExpr * a2,IRExpr * a3)615 static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 )
616 {
617 return IRExpr_Triop(op, a1, a2, a3);
618 }
619
qop(IROp op,IRExpr * a1,IRExpr * a2,IRExpr * a3,IRExpr * a4)620 static IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2,
621 IRExpr* a3, IRExpr* a4 )
622 {
623 return IRExpr_Qop(op, a1, a2, a3, a4);
624 }
625
mkexpr(IRTemp tmp)626 static IRExpr* mkexpr ( IRTemp tmp )
627 {
628 return IRExpr_RdTmp(tmp);
629 }
630
mkU8(UChar i)631 static IRExpr* mkU8 ( UChar i )
632 {
633 return IRExpr_Const(IRConst_U8(i));
634 }
635
mkU16(UInt i)636 static IRExpr* mkU16 ( UInt i )
637 {
638 return IRExpr_Const(IRConst_U16(i));
639 }
640
mkU32(UInt i)641 static IRExpr* mkU32 ( UInt i )
642 {
643 return IRExpr_Const(IRConst_U32(i));
644 }
645
mkU64(ULong i)646 static IRExpr* mkU64 ( ULong i )
647 {
648 return IRExpr_Const(IRConst_U64(i));
649 }
650
mkV128(UShort i)651 static IRExpr* mkV128 ( UShort i )
652 {
653 vassert(i == 0 || i == 0xffff);
654 return IRExpr_Const(IRConst_V128(i));
655 }
656
657 /* This generates a normal (non load-linked) load. */
load(IRType ty,IRExpr * addr)658 static IRExpr* load ( IRType ty, IRExpr* addr )
659 {
660 if (host_endness == VexEndnessBE)
661 return IRExpr_Load(Iend_BE, ty, addr);
662 else
663 return IRExpr_Load(Iend_LE, ty, addr);
664 }
665
stmt_load(IRTemp result,IRExpr * addr,IRExpr * storedata)666 static IRStmt* stmt_load ( IRTemp result,
667 IRExpr* addr, IRExpr* storedata )
668 {
669 if (host_endness == VexEndnessBE)
670 return IRStmt_LLSC(Iend_BE, result, addr, storedata);
671 else
672 return IRStmt_LLSC(Iend_LE, result, addr, storedata);
673 }
674
mkOR1(IRExpr * arg1,IRExpr * arg2)675 static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 )
676 {
677 vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
678 vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
679 return unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1),
680 unop(Iop_1Uto32, arg2)));
681 }
682
mkAND1(IRExpr * arg1,IRExpr * arg2)683 static IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 )
684 {
685 vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
686 vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
687 return unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1),
688 unop(Iop_1Uto32, arg2)));
689 }
690
691 /* expand V128_8Ux16 to 2x V128_16Ux8's */
expand8Ux16(IRExpr * vIn,IRTemp * vEvn,IRTemp * vOdd)692 static void expand8Ux16( IRExpr* vIn,
693 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
694 {
695 IRTemp ones8x16 = newTemp(Ity_V128);
696
697 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
698 vassert(vEvn && *vEvn == IRTemp_INVALID);
699 vassert(vOdd && *vOdd == IRTemp_INVALID);
700 *vEvn = newTemp(Ity_V128);
701 *vOdd = newTemp(Ity_V128);
702
703 assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
704 assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) );
705 assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16),
706 binop(Iop_ShrV128, vIn, mkU8(8))) );
707 }
708
709 /* expand V128_8Sx16 to 2x V128_16Sx8's */
expand8Sx16(IRExpr * vIn,IRTemp * vEvn,IRTemp * vOdd)710 static void expand8Sx16( IRExpr* vIn,
711 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
712 {
713 IRTemp ones8x16 = newTemp(Ity_V128);
714
715 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
716 vassert(vEvn && *vEvn == IRTemp_INVALID);
717 vassert(vOdd && *vOdd == IRTemp_INVALID);
718 *vEvn = newTemp(Ity_V128);
719 *vOdd = newTemp(Ity_V128);
720
721 assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
722 assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) );
723 assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16),
724 binop(Iop_ShrV128, vIn, mkU8(8))) );
725 }
726
727 /* expand V128_16Uto8 to 2x V128_32Ux4's */
expand16Ux8(IRExpr * vIn,IRTemp * vEvn,IRTemp * vOdd)728 static void expand16Ux8( IRExpr* vIn,
729 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
730 {
731 IRTemp ones16x8 = newTemp(Ity_V128);
732
733 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
734 vassert(vEvn && *vEvn == IRTemp_INVALID);
735 vassert(vOdd && *vOdd == IRTemp_INVALID);
736 *vEvn = newTemp(Ity_V128);
737 *vOdd = newTemp(Ity_V128);
738
739 assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
740 assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) );
741 assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8),
742 binop(Iop_ShrV128, vIn, mkU8(16))) );
743 }
744
745 /* expand V128_16Sto8 to 2x V128_32Sx4's */
expand16Sx8(IRExpr * vIn,IRTemp * vEvn,IRTemp * vOdd)746 static void expand16Sx8( IRExpr* vIn,
747 /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
748 {
749 IRTemp ones16x8 = newTemp(Ity_V128);
750
751 vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
752 vassert(vEvn && *vEvn == IRTemp_INVALID);
753 vassert(vOdd && *vOdd == IRTemp_INVALID);
754 *vEvn = newTemp(Ity_V128);
755 *vOdd = newTemp(Ity_V128);
756
757 assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
758 assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) );
759 assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8),
760 binop(Iop_ShrV128, vIn, mkU8(16))) );
761 }
762
763 /* break V128 to 4xF64's*/
breakV128to4xF64(IRExpr * t128,IRTemp * t3,IRTemp * t2,IRTemp * t1,IRTemp * t0)764 static void breakV128to4xF64( IRExpr* t128,
765 /*OUTs*/
766 IRTemp* t3, IRTemp* t2,
767 IRTemp* t1, IRTemp* t0 )
768 {
769 IRTemp hi64 = newTemp(Ity_I64);
770 IRTemp lo64 = newTemp(Ity_I64);
771
772 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
773 vassert(t0 && *t0 == IRTemp_INVALID);
774 vassert(t1 && *t1 == IRTemp_INVALID);
775 vassert(t2 && *t2 == IRTemp_INVALID);
776 vassert(t3 && *t3 == IRTemp_INVALID);
777 *t0 = newTemp(Ity_F64);
778 *t1 = newTemp(Ity_F64);
779 *t2 = newTemp(Ity_F64);
780 *t3 = newTemp(Ity_F64);
781
782 assign( hi64, unop(Iop_V128HIto64, t128) );
783 assign( lo64, unop(Iop_V128to64, t128) );
784 assign( *t3,
785 unop( Iop_F32toF64,
786 unop( Iop_ReinterpI32asF32,
787 unop( Iop_64HIto32, mkexpr( hi64 ) ) ) ) );
788 assign( *t2,
789 unop( Iop_F32toF64,
790 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( hi64 ) ) ) ) );
791 assign( *t1,
792 unop( Iop_F32toF64,
793 unop( Iop_ReinterpI32asF32,
794 unop( Iop_64HIto32, mkexpr( lo64 ) ) ) ) );
795 assign( *t0,
796 unop( Iop_F32toF64,
797 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( lo64 ) ) ) ) );
798 }
799
800
801 /* break V128 to 4xI32's, then sign-extend to I64's */
breakV128to4x64S(IRExpr * t128,IRTemp * t3,IRTemp * t2,IRTemp * t1,IRTemp * t0)802 static void breakV128to4x64S( IRExpr* t128,
803 /*OUTs*/
804 IRTemp* t3, IRTemp* t2,
805 IRTemp* t1, IRTemp* t0 )
806 {
807 IRTemp hi64 = newTemp(Ity_I64);
808 IRTemp lo64 = newTemp(Ity_I64);
809
810 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
811 vassert(t0 && *t0 == IRTemp_INVALID);
812 vassert(t1 && *t1 == IRTemp_INVALID);
813 vassert(t2 && *t2 == IRTemp_INVALID);
814 vassert(t3 && *t3 == IRTemp_INVALID);
815 *t0 = newTemp(Ity_I64);
816 *t1 = newTemp(Ity_I64);
817 *t2 = newTemp(Ity_I64);
818 *t3 = newTemp(Ity_I64);
819
820 assign( hi64, unop(Iop_V128HIto64, t128) );
821 assign( lo64, unop(Iop_V128to64, t128) );
822 assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) );
823 assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(hi64))) );
824 assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) );
825 assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(lo64))) );
826 }
827
828 /* break V128 to 4xI32's, then zero-extend to I64's */
breakV128to4x64U(IRExpr * t128,IRTemp * t3,IRTemp * t2,IRTemp * t1,IRTemp * t0)829 static void breakV128to4x64U ( IRExpr* t128,
830 /*OUTs*/
831 IRTemp* t3, IRTemp* t2,
832 IRTemp* t1, IRTemp* t0 )
833 {
834 IRTemp hi64 = newTemp(Ity_I64);
835 IRTemp lo64 = newTemp(Ity_I64);
836
837 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
838 vassert(t0 && *t0 == IRTemp_INVALID);
839 vassert(t1 && *t1 == IRTemp_INVALID);
840 vassert(t2 && *t2 == IRTemp_INVALID);
841 vassert(t3 && *t3 == IRTemp_INVALID);
842 *t0 = newTemp(Ity_I64);
843 *t1 = newTemp(Ity_I64);
844 *t2 = newTemp(Ity_I64);
845 *t3 = newTemp(Ity_I64);
846
847 assign( hi64, unop(Iop_V128HIto64, t128) );
848 assign( lo64, unop(Iop_V128to64, t128) );
849 assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) );
850 assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32, mkexpr(hi64))) );
851 assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) );
852 assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32, mkexpr(lo64))) );
853 }
854
breakV128to4x32(IRExpr * t128,IRTemp * t3,IRTemp * t2,IRTemp * t1,IRTemp * t0)855 static void breakV128to4x32( IRExpr* t128,
856 /*OUTs*/
857 IRTemp* t3, IRTemp* t2,
858 IRTemp* t1, IRTemp* t0 )
859 {
860 IRTemp hi64 = newTemp(Ity_I64);
861 IRTemp lo64 = newTemp(Ity_I64);
862
863 vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
864 vassert(t0 && *t0 == IRTemp_INVALID);
865 vassert(t1 && *t1 == IRTemp_INVALID);
866 vassert(t2 && *t2 == IRTemp_INVALID);
867 vassert(t3 && *t3 == IRTemp_INVALID);
868 *t0 = newTemp(Ity_I32);
869 *t1 = newTemp(Ity_I32);
870 *t2 = newTemp(Ity_I32);
871 *t3 = newTemp(Ity_I32);
872
873 assign( hi64, unop(Iop_V128HIto64, t128) );
874 assign( lo64, unop(Iop_V128to64, t128) );
875 assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) );
876 assign( *t2, unop(Iop_64to32, mkexpr(hi64)) );
877 assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) );
878 assign( *t0, unop(Iop_64to32, mkexpr(lo64)) );
879 }
880
mkV128from32(IRTemp t3,IRTemp t2,IRTemp t1,IRTemp t0)881 static IRExpr* mkV128from32( IRTemp t3, IRTemp t2,
882 IRTemp t1, IRTemp t0 )
883 {
884 return
885 binop( Iop_64HLtoV128,
886 binop(Iop_32HLto64, mkexpr(t3), mkexpr(t2)),
887 binop(Iop_32HLto64, mkexpr(t1), mkexpr(t0))
888 );
889 }
890
891
892 /* Signed saturating narrow 64S to 32 */
mkQNarrow64Sto32(IRExpr * t64)893 static IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 )
894 {
895 IRTemp hi32 = newTemp(Ity_I32);
896 IRTemp lo32 = newTemp(Ity_I32);
897
898 vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
899
900 assign( hi32, unop(Iop_64HIto32, t64));
901 assign( lo32, unop(Iop_64to32, t64));
902
903 return IRExpr_ITE(
904 /* if (hi32 == (lo32 >>s 31)) */
905 binop(Iop_CmpEQ32, mkexpr(hi32),
906 binop( Iop_Sar32, mkexpr(lo32), mkU8(31))),
907 /* then: within signed-32 range: lo half good enough */
908 mkexpr(lo32),
909 /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */
910 binop(Iop_Add32, mkU32(0x7FFFFFFF),
911 binop(Iop_Shr32, mkexpr(hi32), mkU8(31))));
912 }
913
914 /* Unsigned saturating narrow 64S to 32 */
mkQNarrow64Uto32(IRExpr * t64)915 static IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 )
916 {
917 IRTemp hi32 = newTemp(Ity_I32);
918 IRTemp lo32 = newTemp(Ity_I32);
919
920 vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
921
922 assign( hi32, unop(Iop_64HIto32, t64));
923 assign( lo32, unop(Iop_64to32, t64));
924
925 return IRExpr_ITE(
926 /* if (top 32 bits of t64 are 0) */
927 binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0)),
928 /* then: within unsigned-32 range: lo half good enough */
929 mkexpr(lo32),
930 /* else: positive saturate -> 0xFFFFFFFF */
931 mkU32(0xFFFFFFFF));
932 }
933
934 /* Signed saturate narrow 64->32, combining to V128 */
mkV128from4x64S(IRExpr * t3,IRExpr * t2,IRExpr * t1,IRExpr * t0)935 static IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2,
936 IRExpr* t1, IRExpr* t0 )
937 {
938 vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
939 vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
940 vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
941 vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
942 return binop(Iop_64HLtoV128,
943 binop(Iop_32HLto64,
944 mkQNarrow64Sto32( t3 ),
945 mkQNarrow64Sto32( t2 )),
946 binop(Iop_32HLto64,
947 mkQNarrow64Sto32( t1 ),
948 mkQNarrow64Sto32( t0 )));
949 }
950
951 /* Unsigned saturate narrow 64->32, combining to V128 */
mkV128from4x64U(IRExpr * t3,IRExpr * t2,IRExpr * t1,IRExpr * t0)952 static IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2,
953 IRExpr* t1, IRExpr* t0 )
954 {
955 vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
956 vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
957 vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
958 vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
959 return binop(Iop_64HLtoV128,
960 binop(Iop_32HLto64,
961 mkQNarrow64Uto32( t3 ),
962 mkQNarrow64Uto32( t2 )),
963 binop(Iop_32HLto64,
964 mkQNarrow64Uto32( t1 ),
965 mkQNarrow64Uto32( t0 )));
966 }
967
968 /* Simulate irops Iop_MullOdd*, since we don't have them */
969 #define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \
970 binop(Iop_MullEven8Ux16, \
971 binop(Iop_ShrV128, expr_vA, mkU8(8)), \
972 binop(Iop_ShrV128, expr_vB, mkU8(8)))
973
974 #define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \
975 binop(Iop_MullEven8Sx16, \
976 binop(Iop_ShrV128, expr_vA, mkU8(8)), \
977 binop(Iop_ShrV128, expr_vB, mkU8(8)))
978
979 #define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \
980 binop(Iop_MullEven16Ux8, \
981 binop(Iop_ShrV128, expr_vA, mkU8(16)), \
982 binop(Iop_ShrV128, expr_vB, mkU8(16)))
983
984 #define MK_Iop_MullOdd32Ux4( expr_vA, expr_vB ) \
985 binop(Iop_MullEven32Ux4, \
986 binop(Iop_ShrV128, expr_vA, mkU8(32)), \
987 binop(Iop_ShrV128, expr_vB, mkU8(32)))
988
989 #define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \
990 binop(Iop_MullEven16Sx8, \
991 binop(Iop_ShrV128, expr_vA, mkU8(16)), \
992 binop(Iop_ShrV128, expr_vB, mkU8(16)))
993
994 #define MK_Iop_MullOdd32Sx4( expr_vA, expr_vB ) \
995 binop(Iop_MullEven32Sx4, \
996 binop(Iop_ShrV128, expr_vA, mkU8(32)), \
997 binop(Iop_ShrV128, expr_vB, mkU8(32)))
998
999
mk64lo32Sto64(IRExpr * src)1000 static IRExpr* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr* src )
1001 {
1002 vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
1003 return unop(Iop_32Sto64, unop(Iop_64to32, src));
1004 }
1005
mk64lo32Uto64(IRExpr * src)1006 static IRExpr* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr* src )
1007 {
1008 vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
1009 return unop(Iop_32Uto64, unop(Iop_64to32, src));
1010 }
1011
mkSzOp(IRType ty,IROp op8)1012 static IROp mkSzOp ( IRType ty, IROp op8 )
1013 {
1014 Int adj;
1015 vassert(ty == Ity_I8 || ty == Ity_I16 ||
1016 ty == Ity_I32 || ty == Ity_I64);
1017 vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 || op8 == Iop_Mul8 ||
1018 op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8 ||
1019 op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8 ||
1020 op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 ||
1021 op8 == Iop_Not8 );
1022 adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3));
1023 return adj + op8;
1024 }
1025
1026 /* Make sure we get valid 32 and 64bit addresses */
mkSzAddr(IRType ty,Addr64 addr)1027 static Addr64 mkSzAddr ( IRType ty, Addr64 addr )
1028 {
1029 vassert(ty == Ity_I32 || ty == Ity_I64);
1030 return ( ty == Ity_I64 ?
1031 (Addr64)addr :
1032 (Addr64)extend_s_32to64( toUInt(addr) ) );
1033 }
1034
1035 /* sz, ULong -> IRExpr */
mkSzImm(IRType ty,ULong imm64)1036 static IRExpr* mkSzImm ( IRType ty, ULong imm64 )
1037 {
1038 vassert(ty == Ity_I32 || ty == Ity_I64);
1039 return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64);
1040 }
1041
1042 /* sz, ULong -> IRConst */
mkSzConst(IRType ty,ULong imm64)1043 static IRConst* mkSzConst ( IRType ty, ULong imm64 )
1044 {
1045 vassert(ty == Ity_I32 || ty == Ity_I64);
1046 return ( ty == Ity_I64 ?
1047 IRConst_U64(imm64) :
1048 IRConst_U32((UInt)imm64) );
1049 }
1050
1051 /* Sign extend imm16 -> IRExpr* */
mkSzExtendS16(IRType ty,UInt imm16)1052 static IRExpr* mkSzExtendS16 ( IRType ty, UInt imm16 )
1053 {
1054 vassert(ty == Ity_I32 || ty == Ity_I64);
1055 return ( ty == Ity_I64 ?
1056 mkU64(extend_s_16to64(imm16)) :
1057 mkU32(extend_s_16to32(imm16)) );
1058 }
1059
1060 /* Sign extend imm32 -> IRExpr* */
mkSzExtendS32(IRType ty,UInt imm32)1061 static IRExpr* mkSzExtendS32 ( IRType ty, UInt imm32 )
1062 {
1063 vassert(ty == Ity_I32 || ty == Ity_I64);
1064 return ( ty == Ity_I64 ?
1065 mkU64(extend_s_32to64(imm32)) :
1066 mkU32(imm32) );
1067 }
1068
1069 /* IR narrows I32/I64 -> I8/I16/I32 */
mkNarrowTo8(IRType ty,IRExpr * src)1070 static IRExpr* mkNarrowTo8 ( IRType ty, IRExpr* src )
1071 {
1072 vassert(ty == Ity_I32 || ty == Ity_I64);
1073 return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src);
1074 }
1075
mkNarrowTo16(IRType ty,IRExpr * src)1076 static IRExpr* mkNarrowTo16 ( IRType ty, IRExpr* src )
1077 {
1078 vassert(ty == Ity_I32 || ty == Ity_I64);
1079 return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src);
1080 }
1081
mkNarrowTo32(IRType ty,IRExpr * src)1082 static IRExpr* mkNarrowTo32 ( IRType ty, IRExpr* src )
1083 {
1084 vassert(ty == Ity_I32 || ty == Ity_I64);
1085 return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
1086 }
1087
1088 /* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */
mkWidenFrom8(IRType ty,IRExpr * src,Bool sined)1089 static IRExpr* mkWidenFrom8 ( IRType ty, IRExpr* src, Bool sined )
1090 {
1091 IROp op;
1092 vassert(ty == Ity_I32 || ty == Ity_I64);
1093 if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64;
1094 else op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64;
1095 return unop(op, src);
1096 }
1097
mkWidenFrom16(IRType ty,IRExpr * src,Bool sined)1098 static IRExpr* mkWidenFrom16 ( IRType ty, IRExpr* src, Bool sined )
1099 {
1100 IROp op;
1101 vassert(ty == Ity_I32 || ty == Ity_I64);
1102 if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64;
1103 else op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64;
1104 return unop(op, src);
1105 }
1106
mkWidenFrom32(IRType ty,IRExpr * src,Bool sined)1107 static IRExpr* mkWidenFrom32 ( IRType ty, IRExpr* src, Bool sined )
1108 {
1109 vassert(ty == Ity_I32 || ty == Ity_I64);
1110 if (ty == Ity_I32)
1111 return src;
1112 return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
1113 }
1114
1115
integerGuestRegOffset(UInt archreg)1116 static Int integerGuestRegOffset ( UInt archreg )
1117 {
1118 vassert(archreg < 32);
1119
1120 // jrs: probably not necessary; only matters if we reference sub-parts
1121 // of the ppc registers, but that isn't the case
1122 // later: this might affect Altivec though?
1123
1124 switch (archreg) {
1125 case 0: return offsetofPPCGuestState(guest_GPR0);
1126 case 1: return offsetofPPCGuestState(guest_GPR1);
1127 case 2: return offsetofPPCGuestState(guest_GPR2);
1128 case 3: return offsetofPPCGuestState(guest_GPR3);
1129 case 4: return offsetofPPCGuestState(guest_GPR4);
1130 case 5: return offsetofPPCGuestState(guest_GPR5);
1131 case 6: return offsetofPPCGuestState(guest_GPR6);
1132 case 7: return offsetofPPCGuestState(guest_GPR7);
1133 case 8: return offsetofPPCGuestState(guest_GPR8);
1134 case 9: return offsetofPPCGuestState(guest_GPR9);
1135 case 10: return offsetofPPCGuestState(guest_GPR10);
1136 case 11: return offsetofPPCGuestState(guest_GPR11);
1137 case 12: return offsetofPPCGuestState(guest_GPR12);
1138 case 13: return offsetofPPCGuestState(guest_GPR13);
1139 case 14: return offsetofPPCGuestState(guest_GPR14);
1140 case 15: return offsetofPPCGuestState(guest_GPR15);
1141 case 16: return offsetofPPCGuestState(guest_GPR16);
1142 case 17: return offsetofPPCGuestState(guest_GPR17);
1143 case 18: return offsetofPPCGuestState(guest_GPR18);
1144 case 19: return offsetofPPCGuestState(guest_GPR19);
1145 case 20: return offsetofPPCGuestState(guest_GPR20);
1146 case 21: return offsetofPPCGuestState(guest_GPR21);
1147 case 22: return offsetofPPCGuestState(guest_GPR22);
1148 case 23: return offsetofPPCGuestState(guest_GPR23);
1149 case 24: return offsetofPPCGuestState(guest_GPR24);
1150 case 25: return offsetofPPCGuestState(guest_GPR25);
1151 case 26: return offsetofPPCGuestState(guest_GPR26);
1152 case 27: return offsetofPPCGuestState(guest_GPR27);
1153 case 28: return offsetofPPCGuestState(guest_GPR28);
1154 case 29: return offsetofPPCGuestState(guest_GPR29);
1155 case 30: return offsetofPPCGuestState(guest_GPR30);
1156 case 31: return offsetofPPCGuestState(guest_GPR31);
1157 default: break;
1158 }
1159 vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/
1160 }
1161
getIReg(UInt archreg)1162 static IRExpr* getIReg ( UInt archreg )
1163 {
1164 IRType ty = mode64 ? Ity_I64 : Ity_I32;
1165 vassert(archreg < 32);
1166 return IRExpr_Get( integerGuestRegOffset(archreg), ty );
1167 }
1168
1169 /* Ditto, but write to a reg instead. */
putIReg(UInt archreg,IRExpr * e)1170 static void putIReg ( UInt archreg, IRExpr* e )
1171 {
1172 IRType ty = mode64 ? Ity_I64 : Ity_I32;
1173 vassert(archreg < 32);
1174 vassert(typeOfIRExpr(irsb->tyenv, e) == ty );
1175 stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) );
1176 }
1177
1178
1179 /* Floating point egisters are mapped to VSX registers[0..31]. */
floatGuestRegOffset(UInt archreg)1180 static Int floatGuestRegOffset ( UInt archreg )
1181 {
1182 vassert(archreg < 32);
1183
1184 if (host_endness == VexEndnessLE) {
1185 switch (archreg) {
1186 case 0: return offsetofPPCGuestState(guest_VSR0) + 8;
1187 case 1: return offsetofPPCGuestState(guest_VSR1) + 8;
1188 case 2: return offsetofPPCGuestState(guest_VSR2) + 8;
1189 case 3: return offsetofPPCGuestState(guest_VSR3) + 8;
1190 case 4: return offsetofPPCGuestState(guest_VSR4) + 8;
1191 case 5: return offsetofPPCGuestState(guest_VSR5) + 8;
1192 case 6: return offsetofPPCGuestState(guest_VSR6) + 8;
1193 case 7: return offsetofPPCGuestState(guest_VSR7) + 8;
1194 case 8: return offsetofPPCGuestState(guest_VSR8) + 8;
1195 case 9: return offsetofPPCGuestState(guest_VSR9) + 8;
1196 case 10: return offsetofPPCGuestState(guest_VSR10) + 8;
1197 case 11: return offsetofPPCGuestState(guest_VSR11) + 8;
1198 case 12: return offsetofPPCGuestState(guest_VSR12) + 8;
1199 case 13: return offsetofPPCGuestState(guest_VSR13) + 8;
1200 case 14: return offsetofPPCGuestState(guest_VSR14) + 8;
1201 case 15: return offsetofPPCGuestState(guest_VSR15) + 8;
1202 case 16: return offsetofPPCGuestState(guest_VSR16) + 8;
1203 case 17: return offsetofPPCGuestState(guest_VSR17) + 8;
1204 case 18: return offsetofPPCGuestState(guest_VSR18) + 8;
1205 case 19: return offsetofPPCGuestState(guest_VSR19) + 8;
1206 case 20: return offsetofPPCGuestState(guest_VSR20) + 8;
1207 case 21: return offsetofPPCGuestState(guest_VSR21) + 8;
1208 case 22: return offsetofPPCGuestState(guest_VSR22) + 8;
1209 case 23: return offsetofPPCGuestState(guest_VSR23) + 8;
1210 case 24: return offsetofPPCGuestState(guest_VSR24) + 8;
1211 case 25: return offsetofPPCGuestState(guest_VSR25) + 8;
1212 case 26: return offsetofPPCGuestState(guest_VSR26) + 8;
1213 case 27: return offsetofPPCGuestState(guest_VSR27) + 8;
1214 case 28: return offsetofPPCGuestState(guest_VSR28) + 8;
1215 case 29: return offsetofPPCGuestState(guest_VSR29) + 8;
1216 case 30: return offsetofPPCGuestState(guest_VSR30) + 8;
1217 case 31: return offsetofPPCGuestState(guest_VSR31) + 8;
1218 default: break;
1219 }
1220 } else {
1221 switch (archreg) {
1222 case 0: return offsetofPPCGuestState(guest_VSR0);
1223 case 1: return offsetofPPCGuestState(guest_VSR1);
1224 case 2: return offsetofPPCGuestState(guest_VSR2);
1225 case 3: return offsetofPPCGuestState(guest_VSR3);
1226 case 4: return offsetofPPCGuestState(guest_VSR4);
1227 case 5: return offsetofPPCGuestState(guest_VSR5);
1228 case 6: return offsetofPPCGuestState(guest_VSR6);
1229 case 7: return offsetofPPCGuestState(guest_VSR7);
1230 case 8: return offsetofPPCGuestState(guest_VSR8);
1231 case 9: return offsetofPPCGuestState(guest_VSR9);
1232 case 10: return offsetofPPCGuestState(guest_VSR10);
1233 case 11: return offsetofPPCGuestState(guest_VSR11);
1234 case 12: return offsetofPPCGuestState(guest_VSR12);
1235 case 13: return offsetofPPCGuestState(guest_VSR13);
1236 case 14: return offsetofPPCGuestState(guest_VSR14);
1237 case 15: return offsetofPPCGuestState(guest_VSR15);
1238 case 16: return offsetofPPCGuestState(guest_VSR16);
1239 case 17: return offsetofPPCGuestState(guest_VSR17);
1240 case 18: return offsetofPPCGuestState(guest_VSR18);
1241 case 19: return offsetofPPCGuestState(guest_VSR19);
1242 case 20: return offsetofPPCGuestState(guest_VSR20);
1243 case 21: return offsetofPPCGuestState(guest_VSR21);
1244 case 22: return offsetofPPCGuestState(guest_VSR22);
1245 case 23: return offsetofPPCGuestState(guest_VSR23);
1246 case 24: return offsetofPPCGuestState(guest_VSR24);
1247 case 25: return offsetofPPCGuestState(guest_VSR25);
1248 case 26: return offsetofPPCGuestState(guest_VSR26);
1249 case 27: return offsetofPPCGuestState(guest_VSR27);
1250 case 28: return offsetofPPCGuestState(guest_VSR28);
1251 case 29: return offsetofPPCGuestState(guest_VSR29);
1252 case 30: return offsetofPPCGuestState(guest_VSR30);
1253 case 31: return offsetofPPCGuestState(guest_VSR31);
1254 default: break;
1255 }
1256 }
1257 vpanic("floatGuestRegOffset(ppc)"); /*notreached*/
1258 }
1259
getFReg(UInt archreg)1260 static IRExpr* getFReg ( UInt archreg )
1261 {
1262 vassert(archreg < 32);
1263 return IRExpr_Get( floatGuestRegOffset(archreg), Ity_F64 );
1264 }
1265
1266 /* Ditto, but write to a reg instead. */
putFReg(UInt archreg,IRExpr * e)1267 static void putFReg ( UInt archreg, IRExpr* e )
1268 {
1269 vassert(archreg < 32);
1270 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
1271 stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) );
1272 }
1273
1274 /* get Decimal float value. Note, they share floating point register file. */
getDReg(UInt archreg)1275 static IRExpr* getDReg(UInt archreg) {
1276 IRExpr *e;
1277 vassert( archreg < 32 );
1278 e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D64 );
1279 return e;
1280 }
getDReg32(UInt archreg)1281 static IRExpr* getDReg32(UInt archreg) {
1282 IRExpr *e;
1283 vassert( archreg < 32 );
1284 e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D32 );
1285 return e;
1286 }
1287
1288 /* Read a floating point register pair and combine their contents into a
1289 128-bit value */
getDReg_pair(UInt archreg)1290 static IRExpr *getDReg_pair(UInt archreg) {
1291 IRExpr *high = getDReg( archreg );
1292 IRExpr *low = getDReg( archreg + 1 );
1293
1294 return binop( Iop_D64HLtoD128, high, low );
1295 }
1296
1297 /* Ditto, but write to a reg instead. */
putDReg32(UInt archreg,IRExpr * e)1298 static void putDReg32(UInt archreg, IRExpr* e) {
1299 vassert( archreg < 32 );
1300 vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D32 );
1301 stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) );
1302 }
1303
putDReg(UInt archreg,IRExpr * e)1304 static void putDReg(UInt archreg, IRExpr* e) {
1305 vassert( archreg < 32 );
1306 vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D64 );
1307 stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) );
1308 }
1309
1310 /* Write a 128-bit floating point value into a register pair. */
putDReg_pair(UInt archreg,IRExpr * e)1311 static void putDReg_pair(UInt archreg, IRExpr *e) {
1312 IRTemp low = newTemp( Ity_D64 );
1313 IRTemp high = newTemp( Ity_D64 );
1314
1315 vassert( archreg < 32 );
1316 vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D128 );
1317
1318 assign( low, unop( Iop_D128LOtoD64, e ) );
1319 assign( high, unop( Iop_D128HItoD64, e ) );
1320
1321 stmt( IRStmt_Put( floatGuestRegOffset( archreg ), mkexpr( high ) ) );
1322 stmt( IRStmt_Put( floatGuestRegOffset( archreg + 1 ), mkexpr( low ) ) );
1323 }
1324
vsxGuestRegOffset(UInt archreg)1325 static Int vsxGuestRegOffset ( UInt archreg )
1326 {
1327 vassert(archreg < 64);
1328 switch (archreg) {
1329 case 0: return offsetofPPCGuestState(guest_VSR0);
1330 case 1: return offsetofPPCGuestState(guest_VSR1);
1331 case 2: return offsetofPPCGuestState(guest_VSR2);
1332 case 3: return offsetofPPCGuestState(guest_VSR3);
1333 case 4: return offsetofPPCGuestState(guest_VSR4);
1334 case 5: return offsetofPPCGuestState(guest_VSR5);
1335 case 6: return offsetofPPCGuestState(guest_VSR6);
1336 case 7: return offsetofPPCGuestState(guest_VSR7);
1337 case 8: return offsetofPPCGuestState(guest_VSR8);
1338 case 9: return offsetofPPCGuestState(guest_VSR9);
1339 case 10: return offsetofPPCGuestState(guest_VSR10);
1340 case 11: return offsetofPPCGuestState(guest_VSR11);
1341 case 12: return offsetofPPCGuestState(guest_VSR12);
1342 case 13: return offsetofPPCGuestState(guest_VSR13);
1343 case 14: return offsetofPPCGuestState(guest_VSR14);
1344 case 15: return offsetofPPCGuestState(guest_VSR15);
1345 case 16: return offsetofPPCGuestState(guest_VSR16);
1346 case 17: return offsetofPPCGuestState(guest_VSR17);
1347 case 18: return offsetofPPCGuestState(guest_VSR18);
1348 case 19: return offsetofPPCGuestState(guest_VSR19);
1349 case 20: return offsetofPPCGuestState(guest_VSR20);
1350 case 21: return offsetofPPCGuestState(guest_VSR21);
1351 case 22: return offsetofPPCGuestState(guest_VSR22);
1352 case 23: return offsetofPPCGuestState(guest_VSR23);
1353 case 24: return offsetofPPCGuestState(guest_VSR24);
1354 case 25: return offsetofPPCGuestState(guest_VSR25);
1355 case 26: return offsetofPPCGuestState(guest_VSR26);
1356 case 27: return offsetofPPCGuestState(guest_VSR27);
1357 case 28: return offsetofPPCGuestState(guest_VSR28);
1358 case 29: return offsetofPPCGuestState(guest_VSR29);
1359 case 30: return offsetofPPCGuestState(guest_VSR30);
1360 case 31: return offsetofPPCGuestState(guest_VSR31);
1361 case 32: return offsetofPPCGuestState(guest_VSR32);
1362 case 33: return offsetofPPCGuestState(guest_VSR33);
1363 case 34: return offsetofPPCGuestState(guest_VSR34);
1364 case 35: return offsetofPPCGuestState(guest_VSR35);
1365 case 36: return offsetofPPCGuestState(guest_VSR36);
1366 case 37: return offsetofPPCGuestState(guest_VSR37);
1367 case 38: return offsetofPPCGuestState(guest_VSR38);
1368 case 39: return offsetofPPCGuestState(guest_VSR39);
1369 case 40: return offsetofPPCGuestState(guest_VSR40);
1370 case 41: return offsetofPPCGuestState(guest_VSR41);
1371 case 42: return offsetofPPCGuestState(guest_VSR42);
1372 case 43: return offsetofPPCGuestState(guest_VSR43);
1373 case 44: return offsetofPPCGuestState(guest_VSR44);
1374 case 45: return offsetofPPCGuestState(guest_VSR45);
1375 case 46: return offsetofPPCGuestState(guest_VSR46);
1376 case 47: return offsetofPPCGuestState(guest_VSR47);
1377 case 48: return offsetofPPCGuestState(guest_VSR48);
1378 case 49: return offsetofPPCGuestState(guest_VSR49);
1379 case 50: return offsetofPPCGuestState(guest_VSR50);
1380 case 51: return offsetofPPCGuestState(guest_VSR51);
1381 case 52: return offsetofPPCGuestState(guest_VSR52);
1382 case 53: return offsetofPPCGuestState(guest_VSR53);
1383 case 54: return offsetofPPCGuestState(guest_VSR54);
1384 case 55: return offsetofPPCGuestState(guest_VSR55);
1385 case 56: return offsetofPPCGuestState(guest_VSR56);
1386 case 57: return offsetofPPCGuestState(guest_VSR57);
1387 case 58: return offsetofPPCGuestState(guest_VSR58);
1388 case 59: return offsetofPPCGuestState(guest_VSR59);
1389 case 60: return offsetofPPCGuestState(guest_VSR60);
1390 case 61: return offsetofPPCGuestState(guest_VSR61);
1391 case 62: return offsetofPPCGuestState(guest_VSR62);
1392 case 63: return offsetofPPCGuestState(guest_VSR63);
1393 default: break;
1394 }
1395 vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/
1396 }
1397
1398 /* Vector registers are mapped to VSX registers[32..63]. */
vectorGuestRegOffset(UInt archreg)1399 static Int vectorGuestRegOffset ( UInt archreg )
1400 {
1401 vassert(archreg < 32);
1402
1403 switch (archreg) {
1404 case 0: return offsetofPPCGuestState(guest_VSR32);
1405 case 1: return offsetofPPCGuestState(guest_VSR33);
1406 case 2: return offsetofPPCGuestState(guest_VSR34);
1407 case 3: return offsetofPPCGuestState(guest_VSR35);
1408 case 4: return offsetofPPCGuestState(guest_VSR36);
1409 case 5: return offsetofPPCGuestState(guest_VSR37);
1410 case 6: return offsetofPPCGuestState(guest_VSR38);
1411 case 7: return offsetofPPCGuestState(guest_VSR39);
1412 case 8: return offsetofPPCGuestState(guest_VSR40);
1413 case 9: return offsetofPPCGuestState(guest_VSR41);
1414 case 10: return offsetofPPCGuestState(guest_VSR42);
1415 case 11: return offsetofPPCGuestState(guest_VSR43);
1416 case 12: return offsetofPPCGuestState(guest_VSR44);
1417 case 13: return offsetofPPCGuestState(guest_VSR45);
1418 case 14: return offsetofPPCGuestState(guest_VSR46);
1419 case 15: return offsetofPPCGuestState(guest_VSR47);
1420 case 16: return offsetofPPCGuestState(guest_VSR48);
1421 case 17: return offsetofPPCGuestState(guest_VSR49);
1422 case 18: return offsetofPPCGuestState(guest_VSR50);
1423 case 19: return offsetofPPCGuestState(guest_VSR51);
1424 case 20: return offsetofPPCGuestState(guest_VSR52);
1425 case 21: return offsetofPPCGuestState(guest_VSR53);
1426 case 22: return offsetofPPCGuestState(guest_VSR54);
1427 case 23: return offsetofPPCGuestState(guest_VSR55);
1428 case 24: return offsetofPPCGuestState(guest_VSR56);
1429 case 25: return offsetofPPCGuestState(guest_VSR57);
1430 case 26: return offsetofPPCGuestState(guest_VSR58);
1431 case 27: return offsetofPPCGuestState(guest_VSR59);
1432 case 28: return offsetofPPCGuestState(guest_VSR60);
1433 case 29: return offsetofPPCGuestState(guest_VSR61);
1434 case 30: return offsetofPPCGuestState(guest_VSR62);
1435 case 31: return offsetofPPCGuestState(guest_VSR63);
1436 default: break;
1437 }
1438 vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/
1439 }
1440
getVReg(UInt archreg)1441 static IRExpr* getVReg ( UInt archreg )
1442 {
1443 vassert(archreg < 32);
1444 return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 );
1445 }
1446
1447 /* Ditto, but write to a reg instead. */
putVReg(UInt archreg,IRExpr * e)1448 static void putVReg ( UInt archreg, IRExpr* e )
1449 {
1450 vassert(archreg < 32);
1451 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
1452 stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) );
1453 }
1454
1455 /* Get contents of VSX guest register */
getVSReg(UInt archreg)1456 static IRExpr* getVSReg ( UInt archreg )
1457 {
1458 vassert(archreg < 64);
1459 return IRExpr_Get( vsxGuestRegOffset(archreg), Ity_V128 );
1460 }
1461
1462 /* Ditto, but write to a VSX reg instead. */
putVSReg(UInt archreg,IRExpr * e)1463 static void putVSReg ( UInt archreg, IRExpr* e )
1464 {
1465 vassert(archreg < 64);
1466 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
1467 stmt( IRStmt_Put(vsxGuestRegOffset(archreg), e) );
1468 }
1469
1470
guestCR321offset(UInt cr)1471 static Int guestCR321offset ( UInt cr )
1472 {
1473 switch (cr) {
1474 case 0: return offsetofPPCGuestState(guest_CR0_321 );
1475 case 1: return offsetofPPCGuestState(guest_CR1_321 );
1476 case 2: return offsetofPPCGuestState(guest_CR2_321 );
1477 case 3: return offsetofPPCGuestState(guest_CR3_321 );
1478 case 4: return offsetofPPCGuestState(guest_CR4_321 );
1479 case 5: return offsetofPPCGuestState(guest_CR5_321 );
1480 case 6: return offsetofPPCGuestState(guest_CR6_321 );
1481 case 7: return offsetofPPCGuestState(guest_CR7_321 );
1482 default: vpanic("guestCR321offset(ppc)");
1483 }
1484 }
1485
guestCR0offset(UInt cr)1486 static Int guestCR0offset ( UInt cr )
1487 {
1488 switch (cr) {
1489 case 0: return offsetofPPCGuestState(guest_CR0_0 );
1490 case 1: return offsetofPPCGuestState(guest_CR1_0 );
1491 case 2: return offsetofPPCGuestState(guest_CR2_0 );
1492 case 3: return offsetofPPCGuestState(guest_CR3_0 );
1493 case 4: return offsetofPPCGuestState(guest_CR4_0 );
1494 case 5: return offsetofPPCGuestState(guest_CR5_0 );
1495 case 6: return offsetofPPCGuestState(guest_CR6_0 );
1496 case 7: return offsetofPPCGuestState(guest_CR7_0 );
1497 default: vpanic("guestCR3offset(ppc)");
1498 }
1499 }
1500
1501 typedef enum {
1502 _placeholder0,
1503 _placeholder1,
1504 _placeholder2,
1505 BYTE,
1506 HWORD,
1507 WORD,
1508 DWORD
1509 } _popcount_data_type;
1510
1511 /* Generate an IR sequence to do a popcount operation on the supplied
1512 IRTemp, and return a new IRTemp holding the result. 'ty' may be
1513 Ity_I32 or Ity_I64 only. */
gen_POPCOUNT(IRType ty,IRTemp src,_popcount_data_type data_type)1514 static IRTemp gen_POPCOUNT ( IRType ty, IRTemp src, _popcount_data_type data_type )
1515 {
1516 /* Do count across 2^data_type bits,
1517 byte: data_type = 3
1518 half word: data_type = 4
1519 word: data_type = 5
1520 double word: data_type = 6 (not supported for 32-bit type)
1521 */
1522 Int shift[6];
1523 _popcount_data_type idx, i;
1524 IRTemp mask[6];
1525 IRTemp old = IRTemp_INVALID;
1526 IRTemp nyu = IRTemp_INVALID;
1527
1528 vassert(ty == Ity_I64 || ty == Ity_I32);
1529
1530 if (ty == Ity_I32) {
1531
1532 for (idx = 0; idx < WORD; idx++) {
1533 mask[idx] = newTemp(ty);
1534 shift[idx] = 1 << idx;
1535 }
1536 assign(mask[0], mkU32(0x55555555));
1537 assign(mask[1], mkU32(0x33333333));
1538 assign(mask[2], mkU32(0x0F0F0F0F));
1539 assign(mask[3], mkU32(0x00FF00FF));
1540 assign(mask[4], mkU32(0x0000FFFF));
1541 old = src;
1542 for (i = 0; i < data_type; i++) {
1543 nyu = newTemp(ty);
1544 assign(nyu,
1545 binop(Iop_Add32,
1546 binop(Iop_And32,
1547 mkexpr(old),
1548 mkexpr(mask[i])),
1549 binop(Iop_And32,
1550 binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
1551 mkexpr(mask[i]))));
1552 old = nyu;
1553 }
1554 return nyu;
1555 }
1556
1557 // else, ty == Ity_I64
1558 vassert(mode64);
1559
1560 for (i = 0; i < DWORD; i++) {
1561 mask[i] = newTemp( Ity_I64 );
1562 shift[i] = 1 << i;
1563 }
1564 assign( mask[0], mkU64( 0x5555555555555555ULL ) );
1565 assign( mask[1], mkU64( 0x3333333333333333ULL ) );
1566 assign( mask[2], mkU64( 0x0F0F0F0F0F0F0F0FULL ) );
1567 assign( mask[3], mkU64( 0x00FF00FF00FF00FFULL ) );
1568 assign( mask[4], mkU64( 0x0000FFFF0000FFFFULL ) );
1569 assign( mask[5], mkU64( 0x00000000FFFFFFFFULL ) );
1570 old = src;
1571 for (i = 0; i < data_type; i++) {
1572 nyu = newTemp( Ity_I64 );
1573 assign( nyu,
1574 binop( Iop_Add64,
1575 binop( Iop_And64, mkexpr( old ), mkexpr( mask[i] ) ),
1576 binop( Iop_And64,
1577 binop( Iop_Shr64, mkexpr( old ), mkU8( shift[i] ) ),
1578 mkexpr( mask[i] ) ) ) );
1579 old = nyu;
1580 }
1581 return nyu;
1582 }
1583
1584 /* Special purpose population count function for
1585 * vpopcntd in 32-bit mode.
1586 */
gen_vpopcntd_mode32(IRTemp src1,IRTemp src2)1587 static IRTemp gen_vpopcntd_mode32 ( IRTemp src1, IRTemp src2 )
1588 {
1589 Int i, shift[6];
1590 IRTemp mask[6];
1591 IRTemp old = IRTemp_INVALID;
1592 IRTemp nyu1 = IRTemp_INVALID;
1593 IRTemp nyu2 = IRTemp_INVALID;
1594 IRTemp retval = newTemp(Ity_I64);
1595
1596 vassert(!mode64);
1597
1598 for (i = 0; i < WORD; i++) {
1599 mask[i] = newTemp(Ity_I32);
1600 shift[i] = 1 << i;
1601 }
1602 assign(mask[0], mkU32(0x55555555));
1603 assign(mask[1], mkU32(0x33333333));
1604 assign(mask[2], mkU32(0x0F0F0F0F));
1605 assign(mask[3], mkU32(0x00FF00FF));
1606 assign(mask[4], mkU32(0x0000FFFF));
1607 old = src1;
1608 for (i = 0; i < WORD; i++) {
1609 nyu1 = newTemp(Ity_I32);
1610 assign(nyu1,
1611 binop(Iop_Add32,
1612 binop(Iop_And32,
1613 mkexpr(old),
1614 mkexpr(mask[i])),
1615 binop(Iop_And32,
1616 binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
1617 mkexpr(mask[i]))));
1618 old = nyu1;
1619 }
1620
1621 old = src2;
1622 for (i = 0; i < WORD; i++) {
1623 nyu2 = newTemp(Ity_I32);
1624 assign(nyu2,
1625 binop(Iop_Add32,
1626 binop(Iop_And32,
1627 mkexpr(old),
1628 mkexpr(mask[i])),
1629 binop(Iop_And32,
1630 binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
1631 mkexpr(mask[i]))));
1632 old = nyu2;
1633 }
1634 assign(retval, unop(Iop_32Uto64, binop(Iop_Add32, mkexpr(nyu1), mkexpr(nyu2))));
1635 return retval;
1636 }
1637
1638
1639 // ROTL(src32/64, rot_amt5/6)
ROTL(IRExpr * src,IRExpr * rot_amt)1640 static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src,
1641 IRExpr* rot_amt )
1642 {
1643 IRExpr *mask, *rot;
1644 vassert(typeOfIRExpr(irsb->tyenv,rot_amt) == Ity_I8);
1645
1646 if (typeOfIRExpr(irsb->tyenv,src) == Ity_I64) {
1647 // rot = (src << rot_amt) | (src >> (64-rot_amt))
1648 mask = binop(Iop_And8, rot_amt, mkU8(63));
1649 rot = binop(Iop_Or64,
1650 binop(Iop_Shl64, src, mask),
1651 binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask)));
1652 } else {
1653 // rot = (src << rot_amt) | (src >> (32-rot_amt))
1654 mask = binop(Iop_And8, rot_amt, mkU8(31));
1655 rot = binop(Iop_Or32,
1656 binop(Iop_Shl32, src, mask),
1657 binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask)));
1658 }
1659 /* Note: the ITE not merely an optimisation; it's needed
1660 because otherwise the Shr is a shift by the word size when
1661 mask denotes zero. For rotates by immediates, a lot of
1662 this junk gets folded out. */
1663 return IRExpr_ITE( binop(Iop_CmpNE8, mask, mkU8(0)),
1664 /* non-zero rotate */ rot,
1665 /* zero rotate */ src);
1666 }
1667
1668 /* Standard effective address calc: (rA + rB) */
ea_rA_idxd(UInt rA,UInt rB)1669 static IRExpr* ea_rA_idxd ( UInt rA, UInt rB )
1670 {
1671 IRType ty = mode64 ? Ity_I64 : Ity_I32;
1672 vassert(rA < 32);
1673 vassert(rB < 32);
1674 return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), getIReg(rB));
1675 }
1676
1677 /* Standard effective address calc: (rA + simm) */
ea_rA_simm(UInt rA,UInt simm16)1678 static IRExpr* ea_rA_simm ( UInt rA, UInt simm16 )
1679 {
1680 IRType ty = mode64 ? Ity_I64 : Ity_I32;
1681 vassert(rA < 32);
1682 return binop(mkSzOp(ty, Iop_Add8), getIReg(rA),
1683 mkSzExtendS16(ty, simm16));
1684 }
1685
1686 /* Standard effective address calc: (rA|0) */
ea_rAor0(UInt rA)1687 static IRExpr* ea_rAor0 ( UInt rA )
1688 {
1689 IRType ty = mode64 ? Ity_I64 : Ity_I32;
1690 vassert(rA < 32);
1691 if (rA == 0) {
1692 return mkSzImm(ty, 0);
1693 } else {
1694 return getIReg(rA);
1695 }
1696 }
1697
1698 /* Standard effective address calc: (rA|0) + rB */
ea_rAor0_idxd(UInt rA,UInt rB)1699 static IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB )
1700 {
1701 vassert(rA < 32);
1702 vassert(rB < 32);
1703 return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB );
1704 }
1705
1706 /* Standard effective address calc: (rA|0) + simm16 */
ea_rAor0_simm(UInt rA,UInt simm16)1707 static IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 )
1708 {
1709 IRType ty = mode64 ? Ity_I64 : Ity_I32;
1710 vassert(rA < 32);
1711 if (rA == 0) {
1712 return mkSzExtendS16(ty, simm16);
1713 } else {
1714 return ea_rA_simm( rA, simm16 );
1715 }
1716 }
1717
1718
1719 /* Align effective address */
addr_align(IRExpr * addr,UChar align)1720 static IRExpr* addr_align( IRExpr* addr, UChar align )
1721 {
1722 IRType ty = mode64 ? Ity_I64 : Ity_I32;
1723 ULong mask;
1724 switch (align) {
1725 case 1: return addr; // byte aligned
1726 case 2: mask = ~0ULL << 1; break; // half-word aligned
1727 case 4: mask = ~0ULL << 2; break; // word aligned
1728 case 16: mask = ~0ULL << 4; break; // quad-word aligned
1729 default:
1730 vex_printf("addr_align: align = %u\n", align);
1731 vpanic("addr_align(ppc)");
1732 }
1733
1734 vassert(typeOfIRExpr(irsb->tyenv,addr) == ty);
1735 return binop( mkSzOp(ty, Iop_And8), addr, mkSzImm(ty, mask) );
1736 }
1737
1738
1739 /* Exit the trace if ADDR (intended to be a guest memory address) is
1740 not ALIGN-aligned, generating a request for a SIGBUS followed by a
1741 restart of the current insn. */
gen_SIGBUS_if_misaligned(IRTemp addr,UChar align)1742 static void gen_SIGBUS_if_misaligned ( IRTemp addr, UChar align )
1743 {
1744 vassert(align == 2 || align == 4 || align == 8 || align == 16);
1745 if (mode64) {
1746 vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64);
1747 stmt(
1748 IRStmt_Exit(
1749 binop(Iop_CmpNE64,
1750 binop(Iop_And64, mkexpr(addr), mkU64(align-1)),
1751 mkU64(0)),
1752 Ijk_SigBUS,
1753 IRConst_U64( guest_CIA_curr_instr ), OFFB_CIA
1754 )
1755 );
1756 } else {
1757 vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32);
1758 stmt(
1759 IRStmt_Exit(
1760 binop(Iop_CmpNE32,
1761 binop(Iop_And32, mkexpr(addr), mkU32(align-1)),
1762 mkU32(0)),
1763 Ijk_SigBUS,
1764 IRConst_U32( guest_CIA_curr_instr ), OFFB_CIA
1765 )
1766 );
1767 }
1768 }
1769
1770
1771 /* Generate AbiHints which mark points at which the ELF or PowerOpen
1772 ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some
1773 N) becomes undefined. That is at function calls and returns. ELF
1774 ppc32 doesn't have this "feature" (how fortunate for it). nia is
1775 the address of the next instruction to be executed.
1776 */
make_redzone_AbiHint(const VexAbiInfo * vbi,IRTemp nia,const HChar * who)1777 static void make_redzone_AbiHint ( const VexAbiInfo* vbi,
1778 IRTemp nia, const HChar* who )
1779 {
1780 Int szB = vbi->guest_stack_redzone_size;
1781 if (0) vex_printf("AbiHint: %s\n", who);
1782 vassert(szB >= 0);
1783 if (szB > 0) {
1784 if (mode64) {
1785 vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64);
1786 stmt( IRStmt_AbiHint(
1787 binop(Iop_Sub64, getIReg(1), mkU64(szB)),
1788 szB,
1789 mkexpr(nia)
1790 ));
1791 } else {
1792 vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32);
1793 stmt( IRStmt_AbiHint(
1794 binop(Iop_Sub32, getIReg(1), mkU32(szB)),
1795 szB,
1796 mkexpr(nia)
1797 ));
1798 }
1799 }
1800 }
1801
1802
1803 /*------------------------------------------------------------*/
1804 /*--- Helpers for condition codes. ---*/
1805 /*------------------------------------------------------------*/
1806
1807 /* Condition register layout.
1808
1809 In the hardware, CR is laid out like this. The leftmost end is the
1810 most significant bit in the register; however the IBM documentation
1811 numbers the bits backwards for some reason.
1812
1813 CR0 CR1 .......... CR6 CR7
1814 0 .. 3 ....................... 28 .. 31 (IBM bit numbering)
1815 31 28 3 0 (normal bit numbering)
1816
1817 Each CR field is 4 bits: [<,>,==,SO]
1818
1819 Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc.
1820
1821 Indexing from BI to guest state:
1822
1823 let n = BI / 4
1824 off = BI % 4
1825 this references CR n:
1826
1827 off==0 -> guest_CRn_321 >> 3
1828 off==1 -> guest_CRn_321 >> 2
1829 off==2 -> guest_CRn_321 >> 1
1830 off==3 -> guest_CRn_SO
1831
1832 Bear in mind the only significant bit in guest_CRn_SO is bit 0
1833 (normal notation) and in guest_CRn_321 the significant bits are
1834 3, 2 and 1 (normal notation).
1835 */
1836
putCR321(UInt cr,IRExpr * e)1837 static void putCR321 ( UInt cr, IRExpr* e )
1838 {
1839 vassert(cr < 8);
1840 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1841 stmt( IRStmt_Put(guestCR321offset(cr), e) );
1842 }
1843
putCR0(UInt cr,IRExpr * e)1844 static void putCR0 ( UInt cr, IRExpr* e )
1845 {
1846 vassert(cr < 8);
1847 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1848 stmt( IRStmt_Put(guestCR0offset(cr), e) );
1849 }
1850
getCR0(UInt cr)1851 static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr )
1852 {
1853 vassert(cr < 8);
1854 return IRExpr_Get(guestCR0offset(cr), Ity_I8);
1855 }
1856
getCR321(UInt cr)1857 static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr )
1858 {
1859 vassert(cr < 8);
1860 return IRExpr_Get(guestCR321offset(cr), Ity_I8);
1861 }
1862
1863 /* Fetch the specified CR bit (as per IBM/hardware notation) and
1864 return it at the bottom of an I32; the top 31 bits are guaranteed
1865 to be zero. */
getCRbit(UInt bi)1866 static IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi )
1867 {
1868 UInt n = bi / 4;
1869 UInt off = bi % 4;
1870 vassert(bi < 32);
1871 if (off == 3) {
1872 /* Fetch the SO bit for this CR field */
1873 /* Note: And32 is redundant paranoia iff guest state only has 0
1874 or 1 in that slot. */
1875 return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
1876 } else {
1877 /* Fetch the <, > or == bit for this CR field */
1878 return binop( Iop_And32,
1879 binop( Iop_Shr32,
1880 unop(Iop_8Uto32, getCR321(n)),
1881 mkU8(toUChar(3-off)) ),
1882 mkU32(1) );
1883 }
1884 }
1885
1886 /* Dually, write the least significant bit of BIT to the specified CR
1887 bit. Indexing as per getCRbit. */
putCRbit(UInt bi,IRExpr * bit)1888 static void putCRbit ( UInt bi, IRExpr* bit )
1889 {
1890 UInt n, off;
1891 IRExpr* safe;
1892 vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32);
1893 safe = binop(Iop_And32, bit, mkU32(1));
1894 n = bi / 4;
1895 off = bi % 4;
1896 vassert(bi < 32);
1897 if (off == 3) {
1898 /* This is the SO bit for this CR field */
1899 putCR0(n, unop(Iop_32to8, safe));
1900 } else {
1901 off = 3 - off;
1902 vassert(off == 1 || off == 2 || off == 3);
1903 putCR321(
1904 n,
1905 unop( Iop_32to8,
1906 binop( Iop_Or32,
1907 /* old value with field masked out */
1908 binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)),
1909 mkU32(~(1 << off))),
1910 /* new value in the right place */
1911 binop(Iop_Shl32, safe, mkU8(toUChar(off)))
1912 )
1913 )
1914 );
1915 }
1916 }
1917
1918 /* Fetch the specified CR bit (as per IBM/hardware notation) and
1919 return it somewhere in an I32; it does not matter where, but
1920 whichever bit it is, all other bits are guaranteed to be zero. In
1921 other words, the I32-typed expression will be zero if the bit is
1922 zero and nonzero if the bit is 1. Write into *where the index
1923 of where the bit will be. */
1924
1925 static
getCRbit_anywhere(UInt bi,Int * where)1926 IRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where )
1927 {
1928 UInt n = bi / 4;
1929 UInt off = bi % 4;
1930 vassert(bi < 32);
1931 if (off == 3) {
1932 /* Fetch the SO bit for this CR field */
1933 /* Note: And32 is redundant paranoia iff guest state only has 0
1934 or 1 in that slot. */
1935 *where = 0;
1936 return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
1937 } else {
1938 /* Fetch the <, > or == bit for this CR field */
1939 *where = 3-off;
1940 return binop( Iop_And32,
1941 unop(Iop_8Uto32, getCR321(n)),
1942 mkU32(1 << (3-off)) );
1943 }
1944 }
1945
1946 /* Set the CR0 flags following an arithmetic operation.
1947 (Condition Register CR0 Field Definition, PPC32 p60)
1948 */
1949 static IRExpr* getXER_SO ( void );
set_CR0(IRExpr * result)1950 static void set_CR0 ( IRExpr* result )
1951 {
1952 vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_I32 ||
1953 typeOfIRExpr(irsb->tyenv,result) == Ity_I64);
1954 if (mode64) {
1955 putCR321( 0, unop(Iop_64to8,
1956 binop(Iop_CmpORD64S, result, mkU64(0))) );
1957 } else {
1958 putCR321( 0, unop(Iop_32to8,
1959 binop(Iop_CmpORD32S, result, mkU32(0))) );
1960 }
1961 putCR0( 0, getXER_SO() );
1962 }
1963
1964
1965 /* Set the CR6 flags following an AltiVec compare operation.
1966 * NOTE: This also works for VSX single-precision compares.
1967 * */
set_AV_CR6(IRExpr * result,Bool test_all_ones)1968 static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones )
1969 {
1970 /* CR6[0:3] = {all_ones, 0, all_zeros, 0}
1971 all_ones = (v[0] && v[1] && v[2] && v[3])
1972 all_zeros = ~(v[0] || v[1] || v[2] || v[3])
1973 */
1974 IRTemp v0 = newTemp(Ity_V128);
1975 IRTemp v1 = newTemp(Ity_V128);
1976 IRTemp v2 = newTemp(Ity_V128);
1977 IRTemp v3 = newTemp(Ity_V128);
1978 IRTemp rOnes = newTemp(Ity_I8);
1979 IRTemp rZeros = newTemp(Ity_I8);
1980
1981 vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_V128);
1982
1983 assign( v0, result );
1984 assign( v1, binop(Iop_ShrV128, result, mkU8(32)) );
1985 assign( v2, binop(Iop_ShrV128, result, mkU8(64)) );
1986 assign( v3, binop(Iop_ShrV128, result, mkU8(96)) );
1987
1988 assign( rZeros, unop(Iop_1Uto8,
1989 binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
1990 unop(Iop_Not32,
1991 unop(Iop_V128to32,
1992 binop(Iop_OrV128,
1993 binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)),
1994 binop(Iop_OrV128, mkexpr(v2), mkexpr(v3))))
1995 ))) );
1996
1997 if (test_all_ones) {
1998 assign( rOnes, unop(Iop_1Uto8,
1999 binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
2000 unop(Iop_V128to32,
2001 binop(Iop_AndV128,
2002 binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)),
2003 binop(Iop_AndV128, mkexpr(v2), mkexpr(v3)))
2004 ))) );
2005 putCR321( 6, binop(Iop_Or8,
2006 binop(Iop_Shl8, mkexpr(rOnes), mkU8(3)),
2007 binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) );
2008 } else {
2009 putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) );
2010 }
2011 putCR0( 6, mkU8(0) );
2012 }
2013
2014
2015
2016 /*------------------------------------------------------------*/
2017 /*--- Helpers for XER flags. ---*/
2018 /*------------------------------------------------------------*/
2019
putXER_SO(IRExpr * e)2020 static void putXER_SO ( IRExpr* e )
2021 {
2022 IRExpr* so;
2023 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2024 so = binop(Iop_And8, e, mkU8(1));
2025 stmt( IRStmt_Put( OFFB_XER_SO, so ) );
2026 }
2027
putXER_OV(IRExpr * e)2028 static void putXER_OV ( IRExpr* e )
2029 {
2030 IRExpr* ov;
2031 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2032 ov = binop(Iop_And8, e, mkU8(1));
2033 stmt( IRStmt_Put( OFFB_XER_OV, ov ) );
2034 }
2035
putXER_CA(IRExpr * e)2036 static void putXER_CA ( IRExpr* e )
2037 {
2038 IRExpr* ca;
2039 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2040 ca = binop(Iop_And8, e, mkU8(1));
2041 stmt( IRStmt_Put( OFFB_XER_CA, ca ) );
2042 }
2043
putXER_BC(IRExpr * e)2044 static void putXER_BC ( IRExpr* e )
2045 {
2046 IRExpr* bc;
2047 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2048 bc = binop(Iop_And8, e, mkU8(0x7F));
2049 stmt( IRStmt_Put( OFFB_XER_BC, bc ) );
2050 }
2051
getXER_SO(void)2052 static IRExpr* /* :: Ity_I8 */ getXER_SO ( void )
2053 {
2054 return IRExpr_Get( OFFB_XER_SO, Ity_I8 );
2055 }
2056
getXER_SO32(void)2057 static IRExpr* /* :: Ity_I32 */ getXER_SO32 ( void )
2058 {
2059 return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) );
2060 }
2061
getXER_OV(void)2062 static IRExpr* /* :: Ity_I8 */ getXER_OV ( void )
2063 {
2064 return IRExpr_Get( OFFB_XER_OV, Ity_I8 );
2065 }
2066
getXER_OV32(void)2067 static IRExpr* /* :: Ity_I32 */ getXER_OV32 ( void )
2068 {
2069 return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) );
2070 }
2071
getXER_CA32(void)2072 static IRExpr* /* :: Ity_I32 */ getXER_CA32 ( void )
2073 {
2074 IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 );
2075 return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) );
2076 }
2077
getXER_BC(void)2078 static IRExpr* /* :: Ity_I8 */ getXER_BC ( void )
2079 {
2080 return IRExpr_Get( OFFB_XER_BC, Ity_I8 );
2081 }
2082
getXER_BC32(void)2083 static IRExpr* /* :: Ity_I32 */ getXER_BC32 ( void )
2084 {
2085 IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 );
2086 return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) );
2087 }
2088
2089
2090 /* RES is the result of doing OP on ARGL and ARGR. Set %XER.OV and
2091 %XER.SO accordingly. */
2092
set_XER_OV_32(UInt op,IRExpr * res,IRExpr * argL,IRExpr * argR)2093 static void set_XER_OV_32( UInt op, IRExpr* res,
2094 IRExpr* argL, IRExpr* argR )
2095 {
2096 IRTemp t64;
2097 IRExpr* xer_ov;
2098 vassert(op < PPCG_FLAG_OP_NUMBER);
2099 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I32);
2100 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32);
2101 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32);
2102
2103 # define INT32_MIN 0x80000000
2104
2105 # define XOR2(_aa,_bb) \
2106 binop(Iop_Xor32,(_aa),(_bb))
2107
2108 # define XOR3(_cc,_dd,_ee) \
2109 binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee))
2110
2111 # define AND3(_ff,_gg,_hh) \
2112 binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh))
2113
2114 #define NOT(_jj) \
2115 unop(Iop_Not32, (_jj))
2116
2117 switch (op) {
2118 case /* 0 */ PPCG_FLAG_OP_ADD:
2119 case /* 1 */ PPCG_FLAG_OP_ADDE:
2120 /* (argL^argR^-1) & (argL^res) & (1<<31) ?1:0 */
2121 // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
2122 xer_ov
2123 = AND3( XOR3(argL,argR,mkU32(-1)),
2124 XOR2(argL,res),
2125 mkU32(INT32_MIN) );
2126 /* xer_ov can only be 0 or 1<<31 */
2127 xer_ov
2128 = binop(Iop_Shr32, xer_ov, mkU8(31) );
2129 break;
2130
2131 case /* 2 */ PPCG_FLAG_OP_DIVW:
2132 /* (argL == INT32_MIN && argR == -1) || argR == 0 */
2133 xer_ov
2134 = mkOR1(
2135 mkAND1(
2136 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)),
2137 binop(Iop_CmpEQ32, argR, mkU32(-1))
2138 ),
2139 binop(Iop_CmpEQ32, argR, mkU32(0) )
2140 );
2141 xer_ov
2142 = unop(Iop_1Uto32, xer_ov);
2143 break;
2144
2145 case /* 3 */ PPCG_FLAG_OP_DIVWU:
2146 /* argR == 0 */
2147 xer_ov
2148 = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0)));
2149 break;
2150
2151 case /* 4 */ PPCG_FLAG_OP_MULLW:
2152 /* OV true if result can't be represented in 32 bits
2153 i.e sHi != sign extension of sLo */
2154 t64 = newTemp(Ity_I64);
2155 assign( t64, binop(Iop_MullS32, argL, argR) );
2156 xer_ov
2157 = binop( Iop_CmpNE32,
2158 unop(Iop_64HIto32, mkexpr(t64)),
2159 binop( Iop_Sar32,
2160 unop(Iop_64to32, mkexpr(t64)),
2161 mkU8(31))
2162 );
2163 xer_ov
2164 = unop(Iop_1Uto32, xer_ov);
2165 break;
2166
2167 case /* 5 */ PPCG_FLAG_OP_NEG:
2168 /* argL == INT32_MIN */
2169 xer_ov
2170 = unop( Iop_1Uto32,
2171 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) );
2172 break;
2173
2174 case /* 6 */ PPCG_FLAG_OP_SUBF:
2175 case /* 7 */ PPCG_FLAG_OP_SUBFC:
2176 case /* 8 */ PPCG_FLAG_OP_SUBFE:
2177 /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */
2178 xer_ov
2179 = AND3( XOR3(NOT(argL),argR,mkU32(-1)),
2180 XOR2(NOT(argL),res),
2181 mkU32(INT32_MIN) );
2182 /* xer_ov can only be 0 or 1<<31 */
2183 xer_ov
2184 = binop(Iop_Shr32, xer_ov, mkU8(31) );
2185 break;
2186
2187 case PPCG_FLAG_OP_DIVWEU:
2188 xer_ov
2189 = binop( Iop_Or32,
2190 unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
2191 unop( Iop_1Uto32, binop( Iop_CmpLT32U, argR, argL ) ) );
2192 break;
2193
2194 case PPCG_FLAG_OP_DIVWE:
2195
2196 /* If argR == 0 of if the result cannot fit in the 32-bit destination register,
2197 * then OV <- 1. If dest reg is 0 AND both dividend and divisor are non-zero,
2198 * an overflow is implied.
2199 */
2200 xer_ov = binop( Iop_Or32,
2201 unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
2202 unop( Iop_1Uto32, mkAND1( binop( Iop_CmpEQ32, res, mkU32( 0 ) ),
2203 mkAND1( binop( Iop_CmpNE32, argL, mkU32( 0 ) ),
2204 binop( Iop_CmpNE32, argR, mkU32( 0 ) ) ) ) ) );
2205 break;
2206
2207
2208
2209 default:
2210 vex_printf("set_XER_OV: op = %u\n", op);
2211 vpanic("set_XER_OV(ppc)");
2212 }
2213
2214 /* xer_ov MUST denote either 0 or 1, no other value allowed */
2215 putXER_OV( unop(Iop_32to8, xer_ov) );
2216
2217 /* Update the summary overflow */
2218 putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
2219
2220 # undef INT32_MIN
2221 # undef AND3
2222 # undef XOR3
2223 # undef XOR2
2224 # undef NOT
2225 }
2226
set_XER_OV_64(UInt op,IRExpr * res,IRExpr * argL,IRExpr * argR)2227 static void set_XER_OV_64( UInt op, IRExpr* res,
2228 IRExpr* argL, IRExpr* argR )
2229 {
2230 IRExpr* xer_ov;
2231 vassert(op < PPCG_FLAG_OP_NUMBER);
2232 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I64);
2233 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64);
2234 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64);
2235
2236 # define INT64_MIN 0x8000000000000000ULL
2237
2238 # define XOR2(_aa,_bb) \
2239 binop(Iop_Xor64,(_aa),(_bb))
2240
2241 # define XOR3(_cc,_dd,_ee) \
2242 binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee))
2243
2244 # define AND3(_ff,_gg,_hh) \
2245 binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh))
2246
2247 #define NOT(_jj) \
2248 unop(Iop_Not64, (_jj))
2249
2250 switch (op) {
2251 case /* 0 */ PPCG_FLAG_OP_ADD:
2252 case /* 1 */ PPCG_FLAG_OP_ADDE:
2253 /* (argL^argR^-1) & (argL^res) & (1<<63) ? 1:0 */
2254 // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
2255 xer_ov
2256 = AND3( XOR3(argL,argR,mkU64(-1)),
2257 XOR2(argL,res),
2258 mkU64(INT64_MIN) );
2259 /* xer_ov can only be 0 or 1<<63 */
2260 xer_ov
2261 = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
2262 break;
2263
2264 case /* 2 */ PPCG_FLAG_OP_DIVW:
2265 /* (argL == INT64_MIN && argR == -1) || argR == 0 */
2266 xer_ov
2267 = mkOR1(
2268 mkAND1(
2269 binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)),
2270 binop(Iop_CmpEQ64, argR, mkU64(-1))
2271 ),
2272 binop(Iop_CmpEQ64, argR, mkU64(0) )
2273 );
2274 break;
2275
2276 case /* 3 */ PPCG_FLAG_OP_DIVWU:
2277 /* argR == 0 */
2278 xer_ov
2279 = binop(Iop_CmpEQ64, argR, mkU64(0));
2280 break;
2281
2282 case /* 4 */ PPCG_FLAG_OP_MULLW: {
2283 /* OV true if result can't be represented in 64 bits
2284 i.e sHi != sign extension of sLo */
2285 xer_ov
2286 = binop( Iop_CmpNE32,
2287 unop(Iop_64HIto32, res),
2288 binop( Iop_Sar32,
2289 unop(Iop_64to32, res),
2290 mkU8(31))
2291 );
2292 break;
2293 }
2294
2295 case /* 5 */ PPCG_FLAG_OP_NEG:
2296 /* argL == INT64_MIN */
2297 xer_ov
2298 = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN));
2299 break;
2300
2301 case /* 6 */ PPCG_FLAG_OP_SUBF:
2302 case /* 7 */ PPCG_FLAG_OP_SUBFC:
2303 case /* 8 */ PPCG_FLAG_OP_SUBFE:
2304 /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */
2305 xer_ov
2306 = AND3( XOR3(NOT(argL),argR,mkU64(-1)),
2307 XOR2(NOT(argL),res),
2308 mkU64(INT64_MIN) );
2309 /* xer_ov can only be 0 or 1<<63 */
2310 xer_ov
2311 = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
2312 break;
2313
2314 case PPCG_FLAG_OP_DIVDE:
2315
2316 /* If argR == 0, we must set the OV bit. But there's another condition
2317 * where we can get overflow set for divde . . . when the
2318 * result cannot fit in the 64-bit destination register. If dest reg is 0 AND
2319 * both dividend and divisor are non-zero, it implies an overflow.
2320 */
2321 xer_ov
2322 = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
2323 mkAND1( binop( Iop_CmpEQ64, res, mkU64( 0 ) ),
2324 mkAND1( binop( Iop_CmpNE64, argL, mkU64( 0 ) ),
2325 binop( Iop_CmpNE64, argR, mkU64( 0 ) ) ) ) );
2326 break;
2327
2328 case PPCG_FLAG_OP_DIVDEU:
2329 /* If argR == 0 or if argL >= argR, set OV. */
2330 xer_ov = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
2331 binop( Iop_CmpLE64U, argR, argL ) );
2332 break;
2333
2334 case /* 18 */ PPCG_FLAG_OP_MULLD: {
2335 IRTemp t128;
2336 /* OV true if result can't be represented in 64 bits
2337 i.e sHi != sign extension of sLo */
2338 t128 = newTemp(Ity_I128);
2339 assign( t128, binop(Iop_MullS64, argL, argR) );
2340 xer_ov
2341 = binop( Iop_CmpNE64,
2342 unop(Iop_128HIto64, mkexpr(t128)),
2343 binop( Iop_Sar64,
2344 unop(Iop_128to64, mkexpr(t128)),
2345 mkU8(63))
2346 );
2347 break;
2348 }
2349
2350 default:
2351 vex_printf("set_XER_OV: op = %u\n", op);
2352 vpanic("set_XER_OV(ppc64)");
2353 }
2354
2355 /* xer_ov MUST denote either 0 or 1, no other value allowed */
2356 putXER_OV( unop(Iop_1Uto8, xer_ov) );
2357
2358 /* Update the summary overflow */
2359 putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
2360
2361 # undef INT64_MIN
2362 # undef AND3
2363 # undef XOR3
2364 # undef XOR2
2365 # undef NOT
2366 }
2367
set_XER_OV(IRType ty,UInt op,IRExpr * res,IRExpr * argL,IRExpr * argR)2368 static void set_XER_OV ( IRType ty, UInt op, IRExpr* res,
2369 IRExpr* argL, IRExpr* argR )
2370 {
2371 if (ty == Ity_I32)
2372 set_XER_OV_32( op, res, argL, argR );
2373 else
2374 set_XER_OV_64( op, res, argL, argR );
2375 }
2376
2377
2378
2379 /* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA
2380 value being OLDCA. Set %XER.CA accordingly. */
2381
set_XER_CA_32(UInt op,IRExpr * res,IRExpr * argL,IRExpr * argR,IRExpr * oldca)2382 static void set_XER_CA_32 ( UInt op, IRExpr* res,
2383 IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2384 {
2385 IRExpr* xer_ca;
2386 vassert(op < PPCG_FLAG_OP_NUMBER);
2387 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I32);
2388 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32);
2389 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32);
2390 vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I32);
2391
2392 /* Incoming oldca is assumed to hold the values 0 or 1 only. This
2393 seems reasonable given that it's always generated by
2394 getXER_CA32(), which masks it accordingly. In any case it being
2395 0 or 1 is an invariant of the ppc guest state representation;
2396 if it has any other value, that invariant has been violated. */
2397
2398 switch (op) {
2399 case /* 0 */ PPCG_FLAG_OP_ADD:
2400 /* res <u argL */
2401 xer_ca
2402 = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL));
2403 break;
2404
2405 case /* 1 */ PPCG_FLAG_OP_ADDE:
2406 /* res <u argL || (old_ca==1 && res==argL) */
2407 xer_ca
2408 = mkOR1(
2409 binop(Iop_CmpLT32U, res, argL),
2410 mkAND1(
2411 binop(Iop_CmpEQ32, oldca, mkU32(1)),
2412 binop(Iop_CmpEQ32, res, argL)
2413 )
2414 );
2415 xer_ca
2416 = unop(Iop_1Uto32, xer_ca);
2417 break;
2418
2419 case /* 8 */ PPCG_FLAG_OP_SUBFE:
2420 /* res <u argR || (old_ca==1 && res==argR) */
2421 xer_ca
2422 = mkOR1(
2423 binop(Iop_CmpLT32U, res, argR),
2424 mkAND1(
2425 binop(Iop_CmpEQ32, oldca, mkU32(1)),
2426 binop(Iop_CmpEQ32, res, argR)
2427 )
2428 );
2429 xer_ca
2430 = unop(Iop_1Uto32, xer_ca);
2431 break;
2432
2433 case /* 7 */ PPCG_FLAG_OP_SUBFC:
2434 case /* 9 */ PPCG_FLAG_OP_SUBFI:
2435 /* res <=u argR */
2436 xer_ca
2437 = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR));
2438 break;
2439
2440 case /* 10 */ PPCG_FLAG_OP_SRAW:
2441 /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
2442 If it is <= 31, behave like SRAWI; else XER.CA is the sign
2443 bit of argL. */
2444 /* This term valid for shift amount < 32 only */
2445 xer_ca
2446 = binop(
2447 Iop_And32,
2448 binop(Iop_Sar32, argL, mkU8(31)),
2449 binop( Iop_And32,
2450 argL,
2451 binop( Iop_Sub32,
2452 binop(Iop_Shl32, mkU32(1),
2453 unop(Iop_32to8,argR)),
2454 mkU32(1) )
2455 )
2456 );
2457 xer_ca
2458 = IRExpr_ITE(
2459 /* shift amt > 31 ? */
2460 binop(Iop_CmpLT32U, mkU32(31), argR),
2461 /* yes -- get sign bit of argL */
2462 binop(Iop_Shr32, argL, mkU8(31)),
2463 /* no -- be like srawi */
2464 unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)))
2465 );
2466 break;
2467
2468 case /* 11 */ PPCG_FLAG_OP_SRAWI:
2469 /* xer_ca is 1 iff src was negative and bits_shifted_out !=
2470 0. Since the shift amount is known to be in the range
2471 0 .. 31 inclusive the following seems viable:
2472 xer.ca == 1 iff the following is nonzero:
2473 (argL >>s 31) -- either all 0s or all 1s
2474 & (argL & (1<<argR)-1) -- the stuff shifted out */
2475 xer_ca
2476 = binop(
2477 Iop_And32,
2478 binop(Iop_Sar32, argL, mkU8(31)),
2479 binop( Iop_And32,
2480 argL,
2481 binop( Iop_Sub32,
2482 binop(Iop_Shl32, mkU32(1),
2483 unop(Iop_32to8,argR)),
2484 mkU32(1) )
2485 )
2486 );
2487 xer_ca
2488 = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)));
2489 break;
2490
2491 default:
2492 vex_printf("set_XER_CA: op = %u\n", op);
2493 vpanic("set_XER_CA(ppc)");
2494 }
2495
2496 /* xer_ca MUST denote either 0 or 1, no other value allowed */
2497 putXER_CA( unop(Iop_32to8, xer_ca) );
2498 }
2499
set_XER_CA_64(UInt op,IRExpr * res,IRExpr * argL,IRExpr * argR,IRExpr * oldca)2500 static void set_XER_CA_64 ( UInt op, IRExpr* res,
2501 IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2502 {
2503 IRExpr* xer_ca;
2504 vassert(op < PPCG_FLAG_OP_NUMBER);
2505 vassert(typeOfIRExpr(irsb->tyenv,res) == Ity_I64);
2506 vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64);
2507 vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64);
2508 vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I64);
2509
2510 /* Incoming oldca is assumed to hold the values 0 or 1 only. This
2511 seems reasonable given that it's always generated by
2512 getXER_CA32(), which masks it accordingly. In any case it being
2513 0 or 1 is an invariant of the ppc guest state representation;
2514 if it has any other value, that invariant has been violated. */
2515
2516 switch (op) {
2517 case /* 0 */ PPCG_FLAG_OP_ADD:
2518 /* res <u argL */
2519 xer_ca
2520 = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL));
2521 break;
2522
2523 case /* 1 */ PPCG_FLAG_OP_ADDE:
2524 /* res <u argL || (old_ca==1 && res==argL) */
2525 xer_ca
2526 = mkOR1(
2527 binop(Iop_CmpLT64U, res, argL),
2528 mkAND1(
2529 binop(Iop_CmpEQ64, oldca, mkU64(1)),
2530 binop(Iop_CmpEQ64, res, argL)
2531 )
2532 );
2533 xer_ca
2534 = unop(Iop_1Uto32, xer_ca);
2535 break;
2536
2537 case /* 8 */ PPCG_FLAG_OP_SUBFE:
2538 /* res <u argR || (old_ca==1 && res==argR) */
2539 xer_ca
2540 = mkOR1(
2541 binop(Iop_CmpLT64U, res, argR),
2542 mkAND1(
2543 binop(Iop_CmpEQ64, oldca, mkU64(1)),
2544 binop(Iop_CmpEQ64, res, argR)
2545 )
2546 );
2547 xer_ca
2548 = unop(Iop_1Uto32, xer_ca);
2549 break;
2550
2551 case /* 7 */ PPCG_FLAG_OP_SUBFC:
2552 case /* 9 */ PPCG_FLAG_OP_SUBFI:
2553 /* res <=u argR */
2554 xer_ca
2555 = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR));
2556 break;
2557
2558
2559 case /* 10 */ PPCG_FLAG_OP_SRAW:
2560 /* The shift amount is guaranteed to be in 0 .. 31 inclusive.
2561 If it is <= 31, behave like SRAWI; else XER.CA is the sign
2562 bit of argL. */
2563 /* This term valid for shift amount < 31 only */
2564
2565 xer_ca
2566 = binop(
2567 Iop_And64,
2568 binop(Iop_Sar64, argL, mkU8(31)),
2569 binop( Iop_And64,
2570 argL,
2571 binop( Iop_Sub64,
2572 binop(Iop_Shl64, mkU64(1),
2573 unop(Iop_64to8,argR)),
2574 mkU64(1) )
2575 )
2576 );
2577 xer_ca
2578 = IRExpr_ITE(
2579 /* shift amt > 31 ? */
2580 binop(Iop_CmpLT64U, mkU64(31), argR),
2581 /* yes -- get sign bit of argL */
2582 unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))),
2583 /* no -- be like srawi */
2584 unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)))
2585 );
2586 break;
2587
2588 case /* 11 */ PPCG_FLAG_OP_SRAWI:
2589 /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
2590 Since the shift amount is known to be in the range 0 .. 31
2591 inclusive the following seems viable:
2592 xer.ca == 1 iff the following is nonzero:
2593 (argL >>s 31) -- either all 0s or all 1s
2594 & (argL & (1<<argR)-1) -- the stuff shifted out */
2595
2596 xer_ca
2597 = binop(
2598 Iop_And64,
2599 binop(Iop_Sar64, argL, mkU8(31)),
2600 binop( Iop_And64,
2601 argL,
2602 binop( Iop_Sub64,
2603 binop(Iop_Shl64, mkU64(1),
2604 unop(Iop_64to8,argR)),
2605 mkU64(1) )
2606 )
2607 );
2608 xer_ca
2609 = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
2610 break;
2611
2612
2613 case /* 12 */ PPCG_FLAG_OP_SRAD:
2614 /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
2615 If it is <= 63, behave like SRADI; else XER.CA is the sign
2616 bit of argL. */
2617 /* This term valid for shift amount < 63 only */
2618
2619 xer_ca
2620 = binop(
2621 Iop_And64,
2622 binop(Iop_Sar64, argL, mkU8(63)),
2623 binop( Iop_And64,
2624 argL,
2625 binop( Iop_Sub64,
2626 binop(Iop_Shl64, mkU64(1),
2627 unop(Iop_64to8,argR)),
2628 mkU64(1) )
2629 )
2630 );
2631 xer_ca
2632 = IRExpr_ITE(
2633 /* shift amt > 63 ? */
2634 binop(Iop_CmpLT64U, mkU64(63), argR),
2635 /* yes -- get sign bit of argL */
2636 unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))),
2637 /* no -- be like sradi */
2638 unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)))
2639 );
2640 break;
2641
2642
2643 case /* 13 */ PPCG_FLAG_OP_SRADI:
2644 /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
2645 Since the shift amount is known to be in the range 0 .. 63
2646 inclusive, the following seems viable:
2647 xer.ca == 1 iff the following is nonzero:
2648 (argL >>s 63) -- either all 0s or all 1s
2649 & (argL & (1<<argR)-1) -- the stuff shifted out */
2650
2651 xer_ca
2652 = binop(
2653 Iop_And64,
2654 binop(Iop_Sar64, argL, mkU8(63)),
2655 binop( Iop_And64,
2656 argL,
2657 binop( Iop_Sub64,
2658 binop(Iop_Shl64, mkU64(1),
2659 unop(Iop_64to8,argR)),
2660 mkU64(1) )
2661 )
2662 );
2663 xer_ca
2664 = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
2665 break;
2666
2667 default:
2668 vex_printf("set_XER_CA: op = %u\n", op);
2669 vpanic("set_XER_CA(ppc64)");
2670 }
2671
2672 /* xer_ca MUST denote either 0 or 1, no other value allowed */
2673 putXER_CA( unop(Iop_32to8, xer_ca) );
2674 }
2675
set_XER_CA(IRType ty,UInt op,IRExpr * res,IRExpr * argL,IRExpr * argR,IRExpr * oldca)2676 static void set_XER_CA ( IRType ty, UInt op, IRExpr* res,
2677 IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2678 {
2679 if (ty == Ity_I32)
2680 set_XER_CA_32( op, res, argL, argR, oldca );
2681 else
2682 set_XER_CA_64( op, res, argL, argR, oldca );
2683 }
2684
2685
2686
2687 /*------------------------------------------------------------*/
2688 /*--- Read/write to guest-state --- */
2689 /*------------------------------------------------------------*/
2690
getGST(PPC_GST reg)2691 static IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg )
2692 {
2693 IRType ty = mode64 ? Ity_I64 : Ity_I32;
2694 switch (reg) {
2695 case PPC_GST_SPRG3_RO:
2696 return IRExpr_Get( OFFB_SPRG3_RO, ty );
2697
2698 case PPC_GST_CIA:
2699 return IRExpr_Get( OFFB_CIA, ty );
2700
2701 case PPC_GST_LR:
2702 return IRExpr_Get( OFFB_LR, ty );
2703
2704 case PPC_GST_CTR:
2705 return IRExpr_Get( OFFB_CTR, ty );
2706
2707 case PPC_GST_VRSAVE:
2708 return IRExpr_Get( OFFB_VRSAVE, Ity_I32 );
2709
2710 case PPC_GST_VSCR:
2711 return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ),
2712 mkU32(MASK_VSCR_VALID));
2713
2714 case PPC_GST_CR: {
2715 /* Synthesise the entire CR into a single word. Expensive. */
2716 # define FIELD(_n) \
2717 binop(Iop_Shl32, \
2718 unop(Iop_8Uto32, \
2719 binop(Iop_Or8, \
2720 binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \
2721 binop(Iop_And8, getCR0(_n), mkU8(1)) \
2722 ) \
2723 ), \
2724 mkU8(4 * (7-(_n))) \
2725 )
2726 return binop(Iop_Or32,
2727 binop(Iop_Or32,
2728 binop(Iop_Or32, FIELD(0), FIELD(1)),
2729 binop(Iop_Or32, FIELD(2), FIELD(3))
2730 ),
2731 binop(Iop_Or32,
2732 binop(Iop_Or32, FIELD(4), FIELD(5)),
2733 binop(Iop_Or32, FIELD(6), FIELD(7))
2734 )
2735 );
2736 # undef FIELD
2737 }
2738
2739 case PPC_GST_XER:
2740 return binop(Iop_Or32,
2741 binop(Iop_Or32,
2742 binop( Iop_Shl32, getXER_SO32(), mkU8(31)),
2743 binop( Iop_Shl32, getXER_OV32(), mkU8(30))),
2744 binop(Iop_Or32,
2745 binop( Iop_Shl32, getXER_CA32(), mkU8(29)),
2746 getXER_BC32()));
2747
2748 case PPC_GST_TFHAR:
2749 return IRExpr_Get( OFFB_TFHAR, ty );
2750
2751 case PPC_GST_TEXASR:
2752 return IRExpr_Get( OFFB_TEXASR, ty );
2753
2754 case PPC_GST_TEXASRU:
2755 return IRExpr_Get( OFFB_TEXASRU, ty );
2756
2757 case PPC_GST_TFIAR:
2758 return IRExpr_Get( OFFB_TFIAR, ty );
2759
2760 case PPC_GST_PPR:
2761 return IRExpr_Get( OFFB_PPR, ty );
2762
2763 case PPC_GST_PPR32:
2764 return unop( Iop_64HIto32, IRExpr_Get( OFFB_PPR, ty ) );
2765
2766 case PPC_GST_PSPB:
2767 return IRExpr_Get( OFFB_PSPB, ty );
2768
2769 default:
2770 vex_printf("getGST(ppc): reg = %u", reg);
2771 vpanic("getGST(ppc)");
2772 }
2773 }
2774
2775 /* Get a masked word from the given reg */
getGST_masked(PPC_GST reg,UInt mask)2776 static IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, UInt mask )
2777 {
2778 IRTemp val = newTemp(Ity_I32);
2779 vassert( reg < PPC_GST_MAX );
2780
2781 switch (reg) {
2782
2783 case PPC_GST_FPSCR: {
2784 /* Vex-generated code expects the FPSCR to be set as follows:
2785 all exceptions masked, round-to-nearest.
2786 This corresponds to a FPSCR value of 0x0. */
2787
2788 /* In the lower 32 bits of FPSCR, we're only keeping track of
2789 * the binary floating point rounding mode, so if the mask isn't
2790 * asking for this, just return 0x0.
2791 */
2792 if (mask & MASK_FPSCR_RN) {
2793 assign( val, unop( Iop_8Uto32, IRExpr_Get( OFFB_FPROUND, Ity_I8 ) ) );
2794 } else {
2795 assign( val, mkU32(0x0) );
2796 }
2797 break;
2798 }
2799
2800 default:
2801 vex_printf("getGST_masked(ppc): reg = %u", reg);
2802 vpanic("getGST_masked(ppc)");
2803 }
2804
2805 if (mask != 0xFFFFFFFF) {
2806 return binop(Iop_And32, mkexpr(val), mkU32(mask));
2807 } else {
2808 return mkexpr(val);
2809 }
2810 }
2811
2812 /* Get a masked word from the given reg */
getGST_masked_upper(PPC_GST reg,ULong mask)2813 static IRExpr* /* ::Ity_I32 */getGST_masked_upper(PPC_GST reg, ULong mask) {
2814 IRExpr * val;
2815 vassert( reg < PPC_GST_MAX );
2816
2817 switch (reg) {
2818
2819 case PPC_GST_FPSCR: {
2820 /* In the upper 32 bits of FPSCR, we're only keeping track
2821 * of the decimal floating point rounding mode, so if the mask
2822 * isn't asking for this, just return 0x0.
2823 */
2824 if (mask & MASK_FPSCR_DRN) {
2825 val = binop( Iop_And32,
2826 unop( Iop_8Uto32, IRExpr_Get( OFFB_DFPROUND, Ity_I8 ) ),
2827 unop( Iop_64HIto32, mkU64( mask ) ) );
2828 } else {
2829 val = mkU32( 0x0ULL );
2830 }
2831 break;
2832 }
2833
2834 default:
2835 vex_printf( "getGST_masked_upper(ppc): reg = %u", reg );
2836 vpanic( "getGST_masked_upper(ppc)" );
2837 }
2838 return val;
2839 }
2840
2841
2842 /* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation)
2843 and return it at the bottom of an I32; the top 27 bits are
2844 guaranteed to be zero. */
getGST_field(PPC_GST reg,UInt fld)2845 static IRExpr* /* ::Ity_I32 */ getGST_field ( PPC_GST reg, UInt fld )
2846 {
2847 UInt shft, mask;
2848
2849 vassert( fld < 8 );
2850 vassert( reg < PPC_GST_MAX );
2851
2852 shft = 4*(7-fld);
2853 mask = 0xF<<shft;
2854
2855 switch (reg) {
2856 case PPC_GST_XER:
2857 vassert(fld ==7);
2858 return binop(Iop_Or32,
2859 binop(Iop_Or32,
2860 binop(Iop_Shl32, getXER_SO32(), mkU8(3)),
2861 binop(Iop_Shl32, getXER_OV32(), mkU8(2))),
2862 binop( Iop_Shl32, getXER_CA32(), mkU8(1)));
2863 break;
2864
2865 default:
2866 if (shft == 0)
2867 return getGST_masked( reg, mask );
2868 else
2869 return binop(Iop_Shr32,
2870 getGST_masked( reg, mask ),
2871 mkU8(toUChar( shft )));
2872 }
2873 }
2874
putGST(PPC_GST reg,IRExpr * src)2875 static void putGST ( PPC_GST reg, IRExpr* src )
2876 {
2877 IRType ty = mode64 ? Ity_I64 : Ity_I32;
2878 IRType ty_src = typeOfIRExpr(irsb->tyenv,src );
2879 vassert( reg < PPC_GST_MAX );
2880 switch (reg) {
2881 case PPC_GST_IP_AT_SYSCALL:
2882 vassert( ty_src == ty );
2883 stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) );
2884 break;
2885 case PPC_GST_CIA:
2886 vassert( ty_src == ty );
2887 stmt( IRStmt_Put( OFFB_CIA, src ) );
2888 break;
2889 case PPC_GST_LR:
2890 vassert( ty_src == ty );
2891 stmt( IRStmt_Put( OFFB_LR, src ) );
2892 break;
2893 case PPC_GST_CTR:
2894 vassert( ty_src == ty );
2895 stmt( IRStmt_Put( OFFB_CTR, src ) );
2896 break;
2897 case PPC_GST_VRSAVE:
2898 vassert( ty_src == Ity_I32 );
2899 stmt( IRStmt_Put( OFFB_VRSAVE,src));
2900 break;
2901 case PPC_GST_VSCR:
2902 vassert( ty_src == Ity_I32 );
2903 stmt( IRStmt_Put( OFFB_VSCR,
2904 binop(Iop_And32, src,
2905 mkU32(MASK_VSCR_VALID)) ) );
2906 break;
2907 case PPC_GST_XER:
2908 vassert( ty_src == Ity_I32 );
2909 putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) );
2910 putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) );
2911 putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) );
2912 putXER_BC( unop(Iop_32to8, src) );
2913 break;
2914
2915 case PPC_GST_EMWARN:
2916 vassert( ty_src == Ity_I32 );
2917 stmt( IRStmt_Put( OFFB_EMNOTE,src) );
2918 break;
2919
2920 case PPC_GST_CMSTART:
2921 vassert( ty_src == ty );
2922 stmt( IRStmt_Put( OFFB_CMSTART, src) );
2923 break;
2924
2925 case PPC_GST_CMLEN:
2926 vassert( ty_src == ty );
2927 stmt( IRStmt_Put( OFFB_CMLEN, src) );
2928 break;
2929
2930 case PPC_GST_TEXASR:
2931 vassert( ty_src == Ity_I64 );
2932 stmt( IRStmt_Put( OFFB_TEXASR, src ) );
2933 break;
2934
2935 case PPC_GST_TEXASRU:
2936 vassert( ty_src == Ity_I32 );
2937 stmt( IRStmt_Put( OFFB_TEXASRU, src ) );
2938 break;
2939
2940 case PPC_GST_TFIAR:
2941 vassert( ty_src == Ity_I64 );
2942 stmt( IRStmt_Put( OFFB_TFIAR, src ) );
2943 break;
2944 case PPC_GST_TFHAR:
2945 vassert( ty_src == Ity_I64 );
2946 stmt( IRStmt_Put( OFFB_TFHAR, src ) );
2947 break;
2948
2949 case PPC_GST_PPR32:
2950 case PPC_GST_PPR:
2951 {
2952 /* The Program Priority Register (PPR) stores the priority in
2953 * bits [52:50]. The user setable priorities are:
2954 *
2955 * 001 very low
2956 * 010 low
2957 * 011 medium low
2958 * 100 medium
2959 * 101 medium high
2960 *
2961 * If the argument is not between 0b001 and 0b100 the priority is set
2962 * to 0b100. The priority can only be set to 0b101 if the the Problem
2963 * State Boost Register is non-zero. The value of the PPR is not
2964 * changed if the input is not valid.
2965 */
2966
2967 IRTemp not_valid = newTemp(Ity_I64);
2968 IRTemp has_perm = newTemp(Ity_I64);
2969 IRTemp new_src = newTemp(Ity_I64);
2970 IRTemp PSPB_val = newTemp(Ity_I64);
2971 IRTemp value = newTemp(Ity_I64);
2972
2973 vassert(( ty_src == Ity_I64 ) || ( ty_src == Ity_I32 ));
2974 assign( PSPB_val, binop( Iop_32HLto64,
2975 mkU32( 0 ),
2976 IRExpr_Get( OFFB_PSPB, Ity_I32 ) ) );
2977 if( reg == PPC_GST_PPR32 ) {
2978 vassert( ty_src == Ity_I32 );
2979 assign( value, binop( Iop_32HLto64,
2980 mkU32(0),
2981 binop( Iop_And32,
2982 binop( Iop_Shr32, src, mkU8( 18 ) ),
2983 mkU32( 0x7 ) ) ) );
2984 } else {
2985 vassert( ty_src == Ity_I64 );
2986 assign( value, binop( Iop_And64,
2987 binop( Iop_Shr64, src, mkU8( 50 ) ),
2988 mkU64( 0x7 ) ) );
2989 }
2990 assign( has_perm,
2991 binop( Iop_And64,
2992 unop( Iop_1Sto64,
2993 binop( Iop_CmpEQ64,
2994 mkexpr( PSPB_val ),
2995 mkU64( 0 ) ) ),
2996 unop( Iop_1Sto64,
2997 binop( Iop_CmpEQ64,
2998 mkU64( 0x5 ),
2999 mkexpr( value ) ) ) ) );
3000 assign( not_valid,
3001 binop( Iop_Or64,
3002 unop( Iop_1Sto64,
3003 binop( Iop_CmpEQ64,
3004 mkexpr( value ),
3005 mkU64( 0 ) ) ),
3006 unop( Iop_1Sto64,
3007 binop( Iop_CmpLT64U,
3008 mkU64( 0x5 ),
3009 mkexpr( value ) ) ) ) );
3010 assign( new_src,
3011 binop( Iop_Or64,
3012 binop( Iop_And64,
3013 unop( Iop_Not64,
3014 mkexpr( not_valid ) ),
3015 src ),
3016 binop( Iop_And64,
3017 mkexpr( not_valid ),
3018 binop( Iop_Or64,
3019 binop( Iop_And64,
3020 mkexpr( has_perm),
3021 binop( Iop_Shl64,
3022 mkexpr( value ),
3023 mkU8( 50 ) ) ),
3024 binop( Iop_And64,
3025 IRExpr_Get( OFFB_PPR, ty ),
3026 unop( Iop_Not64,
3027 mkexpr( has_perm )
3028 ) ) ) ) ) );
3029
3030 /* make sure we only set the valid bit field [52:50] */
3031 stmt( IRStmt_Put( OFFB_PPR,
3032 binop( Iop_And64,
3033 mkexpr( new_src ),
3034 mkU64( 0x1C000000000000) ) ) );
3035 break;
3036 }
3037 default:
3038 vex_printf("putGST(ppc): reg = %u", reg);
3039 vpanic("putGST(ppc)");
3040 }
3041 }
3042
3043 /* Write masked src to the given reg */
putGST_masked(PPC_GST reg,IRExpr * src,ULong mask)3044 static void putGST_masked ( PPC_GST reg, IRExpr* src, ULong mask )
3045 {
3046 IRType ty = mode64 ? Ity_I64 : Ity_I32;
3047 vassert( reg < PPC_GST_MAX );
3048 vassert( typeOfIRExpr( irsb->tyenv,src ) == Ity_I64 );
3049
3050 switch (reg) {
3051 case PPC_GST_FPSCR: {
3052 /* Allow writes to either binary or decimal floating point
3053 Rounding Mode.
3054 */
3055 /* If any part of |mask| covers FPSCR.RN, update the bits of
3056 FPSCR.RN by copying in |src| for locations where the
3057 corresponding bit in |mask| is 1, and leaving it unchanged
3058 for corresponding |mask| zero bits. */
3059 if (mask & MASK_FPSCR_RN) {
3060 stmt(
3061 IRStmt_Put(
3062 OFFB_FPROUND,
3063 unop(
3064 Iop_32to8,
3065 binop(
3066 Iop_Or32,
3067 binop(
3068 Iop_And32,
3069 unop(Iop_64to32, src),
3070 mkU32(MASK_FPSCR_RN & mask)
3071 ),
3072 binop(
3073 Iop_And32,
3074 unop(Iop_8Uto32, IRExpr_Get(OFFB_FPROUND,Ity_I8)),
3075 mkU32(MASK_FPSCR_RN & ~mask)
3076 )
3077 )
3078 )
3079 )
3080 );
3081 }
3082 /* Similarly, update FPSCR.DRN if any bits of |mask|
3083 corresponding to FPSCR.DRN are set. */
3084 if (mask & MASK_FPSCR_DRN) {
3085 stmt(
3086 IRStmt_Put(
3087 OFFB_DFPROUND,
3088 unop(
3089 Iop_32to8,
3090 binop(
3091 Iop_Or32,
3092 binop(
3093 Iop_And32,
3094 unop(Iop_64HIto32, src),
3095 mkU32((MASK_FPSCR_DRN & mask) >> 32)
3096 ),
3097 binop(
3098 Iop_And32,
3099 unop(Iop_8Uto32, IRExpr_Get(OFFB_DFPROUND,Ity_I8)),
3100 mkU32((MASK_FPSCR_DRN & ~mask) >> 32)
3101 )
3102 )
3103 )
3104 )
3105 );
3106 }
3107
3108 /* Give EmNote for attempted writes to:
3109 - Exception Controls
3110 - Non-IEEE Mode
3111 */
3112 if (mask & 0xFC) { // Exception Control, Non-IEE mode
3113 VexEmNote ew = EmWarn_PPCexns;
3114
3115 /* If any of the src::exception_control bits are actually set,
3116 side-exit to the next insn, reporting the warning,
3117 so that Valgrind's dispatcher sees the warning. */
3118 putGST( PPC_GST_EMWARN, mkU32(ew) );
3119 stmt(
3120 IRStmt_Exit(
3121 binop(Iop_CmpNE32, mkU32(ew), mkU32(EmNote_NONE)),
3122 Ijk_EmWarn,
3123 mkSzConst( ty, nextInsnAddr()), OFFB_CIA ));
3124 }
3125
3126 /* Ignore all other writes */
3127 break;
3128 }
3129
3130 default:
3131 vex_printf("putGST_masked(ppc): reg = %u", reg);
3132 vpanic("putGST_masked(ppc)");
3133 }
3134 }
3135
3136 /* Write the least significant nibble of src to the specified
3137 REG[FLD] (as per IBM/hardware notation). */
putGST_field(PPC_GST reg,IRExpr * src,UInt fld)3138 static void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld )
3139 {
3140 UInt shft;
3141 ULong mask;
3142
3143 vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 );
3144 vassert( fld < 16 );
3145 vassert( reg < PPC_GST_MAX );
3146
3147 if (fld < 8)
3148 shft = 4*(7-fld);
3149 else
3150 shft = 4*(15-fld);
3151 mask = 0xF;
3152 mask = mask << shft;
3153
3154 switch (reg) {
3155 case PPC_GST_CR:
3156 putCR0 (fld, binop(Iop_And8, mkU8(1 ), unop(Iop_32to8, src)));
3157 putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src)));
3158 break;
3159
3160 default:
3161 {
3162 IRExpr * src64 = unop( Iop_32Uto64, src );
3163
3164 if (shft == 0) {
3165 putGST_masked( reg, src64, mask );
3166 } else {
3167 putGST_masked( reg,
3168 binop( Iop_Shl64, src64, mkU8( toUChar( shft ) ) ),
3169 mask );
3170 }
3171 }
3172 }
3173 }
3174
3175 /*------------------------------------------------------------*/
3176 /* Helpers for VSX instructions that do floating point
3177 * operations and need to determine if a src contains a
3178 * special FP value.
3179 *
3180 *------------------------------------------------------------*/
3181
3182 #define NONZERO_FRAC_MASK 0x000fffffffffffffULL
3183 #define FP_FRAC_PART(x) binop( Iop_And64, \
3184 mkexpr( x ), \
3185 mkU64( NONZERO_FRAC_MASK ) )
3186
3187 // Returns exponent part of a single precision floating point as I32
fp_exp_part_sp(IRTemp src)3188 static IRExpr * fp_exp_part_sp(IRTemp src)
3189 {
3190 return binop( Iop_And32,
3191 binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ),
3192 mkU32( 0xff ) );
3193 }
3194
3195 // Returns exponent part of floating point as I32
fp_exp_part(IRTemp src,Bool sp)3196 static IRExpr * fp_exp_part(IRTemp src, Bool sp)
3197 {
3198 IRExpr * exp;
3199 if (sp)
3200 return fp_exp_part_sp(src);
3201
3202 if (!mode64)
3203 exp = binop( Iop_And32, binop( Iop_Shr32, unop( Iop_64HIto32,
3204 mkexpr( src ) ),
3205 mkU8( 20 ) ), mkU32( 0x7ff ) );
3206 else
3207 exp = unop( Iop_64to32,
3208 binop( Iop_And64,
3209 binop( Iop_Shr64, mkexpr( src ), mkU8( 52 ) ),
3210 mkU64( 0x7ff ) ) );
3211 return exp;
3212 }
3213
is_Inf_sp(IRTemp src)3214 static IRExpr * is_Inf_sp(IRTemp src)
3215 {
3216 IRTemp frac_part = newTemp(Ity_I32);
3217 IRExpr * Inf_exp;
3218
3219 assign( frac_part, binop( Iop_And32, mkexpr(src), mkU32(0x007fffff)) );
3220 Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, True /*single precision*/ ), mkU32( 0xff ) );
3221 return mkAND1( Inf_exp, binop( Iop_CmpEQ32, mkexpr( frac_part ), mkU32( 0 ) ) );
3222 }
3223
3224
3225 // Infinity: exp = 7ff and fraction is zero; s = 0/1
is_Inf(IRTemp src,Bool sp)3226 static IRExpr * is_Inf(IRTemp src, Bool sp)
3227 {
3228 IRExpr * Inf_exp, * hi32, * low32;
3229 IRTemp frac_part;
3230
3231 if (sp)
3232 return is_Inf_sp(src);
3233
3234 frac_part = newTemp(Ity_I64);
3235 assign( frac_part, FP_FRAC_PART(src) );
3236 Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ), mkU32( 0x7ff ) );
3237 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
3238 low32 = unop( Iop_64to32, mkexpr( frac_part ) );
3239 return mkAND1( Inf_exp, binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
3240 mkU32( 0 ) ) );
3241 }
3242
is_Zero_sp(IRTemp src)3243 static IRExpr * is_Zero_sp(IRTemp src)
3244 {
3245 IRTemp sign_less_part = newTemp(Ity_I32);
3246 assign( sign_less_part, binop( Iop_And32, mkexpr( src ), mkU32( SIGN_MASK32 ) ) );
3247 return binop( Iop_CmpEQ32, mkexpr( sign_less_part ), mkU32( 0 ) );
3248 }
3249
3250 // Zero: exp is zero and fraction is zero; s = 0/1
is_Zero(IRTemp src,Bool sp)3251 static IRExpr * is_Zero(IRTemp src, Bool sp)
3252 {
3253 IRExpr * hi32, * low32;
3254 IRTemp sign_less_part;
3255 if (sp)
3256 return is_Zero_sp(src);
3257
3258 sign_less_part = newTemp(Ity_I64);
3259
3260 assign( sign_less_part, binop( Iop_And64, mkexpr( src ), mkU64( SIGN_MASK ) ) );
3261 hi32 = unop( Iop_64HIto32, mkexpr( sign_less_part ) );
3262 low32 = unop( Iop_64to32, mkexpr( sign_less_part ) );
3263 return binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
3264 mkU32( 0 ) );
3265 }
3266
3267 /* SNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '1'
3268 * QNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '0'
3269 * This function returns an IRExpr value of '1' for any type of NaN.
3270 */
is_NaN(IRTemp src)3271 static IRExpr * is_NaN(IRTemp src)
3272 {
3273 IRExpr * NaN_exp, * hi32, * low32;
3274 IRTemp frac_part = newTemp(Ity_I64);
3275
3276 assign( frac_part, FP_FRAC_PART(src) );
3277 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
3278 low32 = unop( Iop_64to32, mkexpr( frac_part ) );
3279 NaN_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ),
3280 mkU32( 0x7ff ) );
3281
3282 return mkAND1( NaN_exp, binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
3283 mkU32( 0 ) ) );
3284 }
3285
3286 /* This function returns an IRExpr value of '1' for any type of NaN.
3287 * The passed 'src' argument is assumed to be Ity_I32.
3288 */
is_NaN_32(IRTemp src)3289 static IRExpr * is_NaN_32(IRTemp src)
3290 {
3291 #define NONZERO_FRAC_MASK32 0x007fffffULL
3292 #define FP_FRAC_PART32(x) binop( Iop_And32, \
3293 mkexpr( x ), \
3294 mkU32( NONZERO_FRAC_MASK32 ) )
3295
3296 IRExpr * frac_part = FP_FRAC_PART32(src);
3297 IRExpr * exp_part = binop( Iop_And32,
3298 binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ),
3299 mkU32( 0x0ff ) );
3300 IRExpr * NaN_exp = binop( Iop_CmpEQ32, exp_part, mkU32( 0xff ) );
3301
3302 return mkAND1( NaN_exp, binop( Iop_CmpNE32, frac_part, mkU32( 0 ) ) );
3303 }
3304
3305 /* This function takes an Ity_I32 input argument interpreted
3306 * as a single-precision floating point value. If src is a
3307 * SNaN, it is changed to a QNaN and returned; otherwise,
3308 * the original value is returned.
3309 */
handle_SNaN_to_QNaN_32(IRExpr * src)3310 static IRExpr * handle_SNaN_to_QNaN_32(IRExpr * src)
3311 {
3312 #define SNAN_MASK32 0x00400000
3313 IRTemp tmp = newTemp(Ity_I32);
3314 IRTemp mask = newTemp(Ity_I32);
3315 IRTemp is_SNAN = newTemp(Ity_I1);
3316
3317 vassert( typeOfIRExpr(irsb->tyenv, src ) == Ity_I32 );
3318 assign(tmp, src);
3319
3320 /* check if input is SNaN, if it is convert to QNaN */
3321 assign( is_SNAN,
3322 mkAND1( is_NaN_32( tmp ),
3323 binop( Iop_CmpEQ32,
3324 binop( Iop_And32, mkexpr( tmp ),
3325 mkU32( SNAN_MASK32 ) ),
3326 mkU32( 0 ) ) ) );
3327 /* create mask with QNaN bit set to make it a QNaN if tmp is SNaN */
3328 assign ( mask, binop( Iop_And32,
3329 unop( Iop_1Sto32, mkexpr( is_SNAN ) ),
3330 mkU32( SNAN_MASK32 ) ) );
3331 return binop( Iop_Or32, mkexpr( mask ), mkexpr( tmp) );
3332 }
3333
3334
3335 /* This helper function performs the negation part of operations of the form:
3336 * "Negate Multiply-<op>"
3337 * where "<op>" is either "Add" or "Sub".
3338 *
3339 * This function takes one argument -- the floating point intermediate result (converted to
3340 * Ity_I64 via Iop_ReinterpF64asI64) that was obtained from the "Multip-<op>" part of
3341 * the operation described above.
3342 */
getNegatedResult(IRTemp intermediateResult)3343 static IRTemp getNegatedResult(IRTemp intermediateResult)
3344 {
3345 ULong signbit_mask = 0x8000000000000000ULL;
3346 IRTemp signbit_32 = newTemp(Ity_I32);
3347 IRTemp resultantSignbit = newTemp(Ity_I1);
3348 IRTemp negatedResult = newTemp(Ity_I64);
3349 assign( signbit_32, binop( Iop_Shr32,
3350 unop( Iop_64HIto32,
3351 binop( Iop_And64, mkexpr( intermediateResult ),
3352 mkU64( signbit_mask ) ) ),
3353 mkU8( 31 ) ) );
3354 /* We negate the signbit if and only if the intermediate result from the
3355 * multiply-<op> was NOT a NaN. This is an XNOR predicate.
3356 */
3357 assign( resultantSignbit,
3358 unop( Iop_Not1,
3359 binop( Iop_CmpEQ32,
3360 binop( Iop_Xor32,
3361 mkexpr( signbit_32 ),
3362 unop( Iop_1Uto32, is_NaN( intermediateResult ) ) ),
3363 mkU32( 1 ) ) ) );
3364
3365 assign( negatedResult,
3366 binop( Iop_Or64,
3367 binop( Iop_And64,
3368 mkexpr( intermediateResult ),
3369 mkU64( ~signbit_mask ) ),
3370 binop( Iop_32HLto64,
3371 binop( Iop_Shl32,
3372 unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
3373 mkU8( 31 ) ),
3374 mkU32( 0 ) ) ) );
3375
3376 return negatedResult;
3377 }
3378
3379 /* This helper function performs the negation part of operations of the form:
3380 * "Negate Multiply-<op>"
3381 * where "<op>" is either "Add" or "Sub".
3382 *
3383 * This function takes one argument -- the floating point intermediate result (converted to
3384 * Ity_I32 via Iop_ReinterpF32asI32) that was obtained from the "Multip-<op>" part of
3385 * the operation described above.
3386 */
getNegatedResult_32(IRTemp intermediateResult)3387 static IRTemp getNegatedResult_32(IRTemp intermediateResult)
3388 {
3389 UInt signbit_mask = 0x80000000;
3390 IRTemp signbit_32 = newTemp(Ity_I32);
3391 IRTemp resultantSignbit = newTemp(Ity_I1);
3392 IRTemp negatedResult = newTemp(Ity_I32);
3393 assign( signbit_32, binop( Iop_Shr32,
3394 binop( Iop_And32, mkexpr( intermediateResult ),
3395 mkU32( signbit_mask ) ),
3396 mkU8( 31 ) ) );
3397 /* We negate the signbit if and only if the intermediate result from the
3398 * multiply-<op> was NOT a NaN. This is an XNOR predicate.
3399 */
3400 assign( resultantSignbit,
3401 unop( Iop_Not1,
3402 binop( Iop_CmpEQ32,
3403 binop( Iop_Xor32,
3404 mkexpr( signbit_32 ),
3405 unop( Iop_1Uto32, is_NaN_32( intermediateResult ) ) ),
3406 mkU32( 1 ) ) ) );
3407
3408 assign( negatedResult,
3409 binop( Iop_Or32,
3410 binop( Iop_And32,
3411 mkexpr( intermediateResult ),
3412 mkU32( ~signbit_mask ) ),
3413 binop( Iop_Shl32,
3414 unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
3415 mkU8( 31 ) ) ) );
3416
3417 return negatedResult;
3418 }
3419
3420 /*------------------------------------------------------------*/
3421 /* Transactional memory helpers
3422 *
3423 *------------------------------------------------------------*/
3424
generate_TMreason(UInt failure_code,UInt persistant,UInt nest_overflow,UInt tm_exact)3425 static ULong generate_TMreason( UInt failure_code,
3426 UInt persistant,
3427 UInt nest_overflow,
3428 UInt tm_exact )
3429 {
3430 ULong tm_err_code =
3431 ( (ULong) 0) << (63-6) /* Failure code */
3432 | ( (ULong) persistant) << (63-7) /* Failure persistant */
3433 | ( (ULong) 0) << (63-8) /* Disallowed */
3434 | ( (ULong) nest_overflow) << (63-9) /* Nesting Overflow */
3435 | ( (ULong) 0) << (63-10) /* Footprint Overflow */
3436 | ( (ULong) 0) << (63-11) /* Self-Induced Conflict */
3437 | ( (ULong) 0) << (63-12) /* Non-Transactional Conflict */
3438 | ( (ULong) 0) << (63-13) /* Transactional Conflict */
3439 | ( (ULong) 0) << (63-14) /* Translation Invalidation Conflict */
3440 | ( (ULong) 0) << (63-15) /* Implementation-specific */
3441 | ( (ULong) 0) << (63-16) /* Instruction Fetch Conflict */
3442 | ( (ULong) 0) << (63-30) /* Reserved */
3443 | ( (ULong) 0) << (63-31) /* Abort */
3444 | ( (ULong) 0) << (63-32) /* Suspend */
3445 | ( (ULong) 0) << (63-33) /* Reserved */
3446 | ( (ULong) 0) << (63-35) /* Privilege */
3447 | ( (ULong) 0) << (63-36) /* Failure Summary */
3448 | ( (ULong) tm_exact) << (63-37) /* TFIAR Exact */
3449 | ( (ULong) 0) << (63-38) /* ROT */
3450 | ( (ULong) 0) << (63-51) /* Reserved */
3451 | ( (ULong) 0) << (63-63); /* Transaction Level */
3452
3453 return tm_err_code;
3454 }
3455
storeTMfailure(Addr64 err_address,ULong tm_reason,Addr64 handler_address)3456 static void storeTMfailure( Addr64 err_address, ULong tm_reason,
3457 Addr64 handler_address )
3458 {
3459 putGST( PPC_GST_TFIAR, mkU64( err_address ) );
3460 putGST( PPC_GST_TEXASR, mkU64( tm_reason ) );
3461 putGST( PPC_GST_TEXASRU, mkU32( 0 ) );
3462 putGST( PPC_GST_TFHAR, mkU64( handler_address ) );
3463 }
3464
3465 /*------------------------------------------------------------*/
3466 /*--- Integer Instruction Translation --- */
3467 /*------------------------------------------------------------*/
3468
3469 /*
3470 Integer Arithmetic Instructions
3471 */
dis_int_arith(UInt theInstr)3472 static Bool dis_int_arith ( UInt theInstr )
3473 {
3474 /* D-Form, XO-Form */
3475 UChar opc1 = ifieldOPC(theInstr);
3476 UChar rD_addr = ifieldRegDS(theInstr);
3477 UChar rA_addr = ifieldRegA(theInstr);
3478 UInt uimm16 = ifieldUIMM16(theInstr);
3479 UChar rB_addr = ifieldRegB(theInstr);
3480 UChar flag_OE = ifieldBIT10(theInstr);
3481 UInt opc2 = ifieldOPClo9(theInstr);
3482 UChar flag_rC = ifieldBIT0(theInstr);
3483
3484 Long simm16 = extend_s_16to64(uimm16);
3485 IRType ty = mode64 ? Ity_I64 : Ity_I32;
3486 IRTemp rA = newTemp(ty);
3487 IRTemp rB = newTemp(ty);
3488 IRTemp rD = newTemp(ty);
3489
3490 Bool do_rc = False;
3491
3492 assign( rA, getIReg(rA_addr) );
3493 assign( rB, getIReg(rB_addr) ); // XO-Form: rD, rA, rB
3494
3495 switch (opc1) {
3496 /* D-Form */
3497 case 0x0C: // addic (Add Immediate Carrying, PPC32 p351
3498 DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
3499 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
3500 mkSzExtendS16(ty, uimm16) ) );
3501 set_XER_CA( ty, PPCG_FLAG_OP_ADD,
3502 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
3503 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
3504 break;
3505
3506 case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352)
3507 DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
3508 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
3509 mkSzExtendS16(ty, uimm16) ) );
3510 set_XER_CA( ty, PPCG_FLAG_OP_ADD,
3511 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
3512 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
3513 do_rc = True; // Always record to CR
3514 flag_rC = 1;
3515 break;
3516
3517 case 0x0E: // addi (Add Immediate, PPC32 p350)
3518 // li rD,val == addi rD,0,val
3519 // la disp(rA) == addi rD,rA,disp
3520 if ( rA_addr == 0 ) {
3521 DIP("li r%u,%d\n", rD_addr, (Int)simm16);
3522 assign( rD, mkSzExtendS16(ty, uimm16) );
3523 } else {
3524 DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
3525 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
3526 mkSzExtendS16(ty, uimm16) ) );
3527 }
3528 break;
3529
3530 case 0x0F: // addis (Add Immediate Shifted, PPC32 p353)
3531 // lis rD,val == addis rD,0,val
3532 if ( rA_addr == 0 ) {
3533 DIP("lis r%u,%d\n", rD_addr, (Int)simm16);
3534 assign( rD, mkSzExtendS32(ty, uimm16 << 16) );
3535 } else {
3536 DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (UInt)simm16);
3537 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
3538 mkSzExtendS32(ty, uimm16 << 16) ) );
3539 }
3540 break;
3541
3542 case 0x07: // mulli (Multiply Low Immediate, PPC32 p490)
3543 DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
3544 if (mode64)
3545 assign( rD, unop(Iop_128to64,
3546 binop(Iop_MullS64, mkexpr(rA),
3547 mkSzExtendS16(ty, uimm16))) );
3548 else
3549 assign( rD, unop(Iop_64to32,
3550 binop(Iop_MullS32, mkexpr(rA),
3551 mkSzExtendS16(ty, uimm16))) );
3552 break;
3553
3554 case 0x08: // subfic (Subtract from Immediate Carrying, PPC32 p540)
3555 DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
3556 // rD = simm16 - rA
3557 assign( rD, binop( mkSzOp(ty, Iop_Sub8),
3558 mkSzExtendS16(ty, uimm16),
3559 mkexpr(rA)) );
3560 set_XER_CA( ty, PPCG_FLAG_OP_SUBFI,
3561 mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
3562 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
3563 break;
3564
3565 /* XO-Form */
3566 case 0x1F:
3567 do_rc = True; // All below record to CR
3568
3569 switch (opc2) {
3570 case 0x10A: // add (Add, PPC32 p347)
3571 DIP("add%s%s r%u,r%u,r%u\n",
3572 flag_OE ? "o" : "", flag_rC ? ".":"",
3573 rD_addr, rA_addr, rB_addr);
3574 assign( rD, binop( mkSzOp(ty, Iop_Add8),
3575 mkexpr(rA), mkexpr(rB) ) );
3576 if (flag_OE) {
3577 set_XER_OV( ty, PPCG_FLAG_OP_ADD,
3578 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3579 }
3580 break;
3581
3582 case 0x00A: // addc (Add Carrying, PPC32 p348)
3583 DIP("addc%s%s r%u,r%u,r%u\n",
3584 flag_OE ? "o" : "", flag_rC ? ".":"",
3585 rD_addr, rA_addr, rB_addr);
3586 assign( rD, binop( mkSzOp(ty, Iop_Add8),
3587 mkexpr(rA), mkexpr(rB)) );
3588 set_XER_CA( ty, PPCG_FLAG_OP_ADD,
3589 mkexpr(rD), mkexpr(rA), mkexpr(rB),
3590 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
3591 if (flag_OE) {
3592 set_XER_OV( ty, PPCG_FLAG_OP_ADD,
3593 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3594 }
3595 break;
3596
3597 case 0x08A: { // adde (Add Extended, PPC32 p349)
3598 IRTemp old_xer_ca = newTemp(ty);
3599 DIP("adde%s%s r%u,r%u,r%u\n",
3600 flag_OE ? "o" : "", flag_rC ? ".":"",
3601 rD_addr, rA_addr, rB_addr);
3602 // rD = rA + rB + XER[CA]
3603 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3604 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
3605 binop( mkSzOp(ty, Iop_Add8),
3606 mkexpr(rB), mkexpr(old_xer_ca))) );
3607 set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
3608 mkexpr(rD), mkexpr(rA), mkexpr(rB),
3609 mkexpr(old_xer_ca) );
3610 if (flag_OE) {
3611 set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
3612 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3613 }
3614 break;
3615 }
3616
3617 case 0x0EA: { // addme (Add to Minus One Extended, PPC32 p354)
3618 IRTemp old_xer_ca = newTemp(ty);
3619 IRExpr *min_one;
3620 if (rB_addr != 0) {
3621 vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n");
3622 return False;
3623 }
3624 DIP("addme%s%s r%u,r%u,r%u\n",
3625 flag_OE ? "o" : "", flag_rC ? ".":"",
3626 rD_addr, rA_addr, rB_addr);
3627 // rD = rA + (-1) + XER[CA]
3628 // => Just another form of adde
3629 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3630 min_one = mkSzImm(ty, (Long)-1);
3631 assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
3632 binop( mkSzOp(ty, Iop_Add8),
3633 min_one, mkexpr(old_xer_ca)) ));
3634 set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
3635 mkexpr(rD), mkexpr(rA), min_one,
3636 mkexpr(old_xer_ca) );
3637 if (flag_OE) {
3638 set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
3639 mkexpr(rD), mkexpr(rA), min_one );
3640 }
3641 break;
3642 }
3643
3644 case 0x0CA: { // addze (Add to Zero Extended, PPC32 p355)
3645 IRTemp old_xer_ca = newTemp(ty);
3646 if (rB_addr != 0) {
3647 vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n");
3648 return False;
3649 }
3650 DIP("addze%s%s r%u,r%u,r%u\n",
3651 flag_OE ? "o" : "", flag_rC ? ".":"",
3652 rD_addr, rA_addr, rB_addr);
3653 // rD = rA + (0) + XER[CA]
3654 // => Just another form of adde
3655 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3656 assign( rD, binop( mkSzOp(ty, Iop_Add8),
3657 mkexpr(rA), mkexpr(old_xer_ca)) );
3658 set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
3659 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
3660 mkexpr(old_xer_ca) );
3661 if (flag_OE) {
3662 set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
3663 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
3664 }
3665 break;
3666 }
3667
3668 case 0x1EB: // divw (Divide Word, PPC32 p388)
3669 DIP("divw%s%s r%u,r%u,r%u\n",
3670 flag_OE ? "o" : "", flag_rC ? ".":"",
3671 rD_addr, rA_addr, rB_addr);
3672 if (mode64) {
3673 /* Note:
3674 XER settings are mode independent, and reflect the
3675 overflow of the low-order 32bit result
3676 CR0[LT|GT|EQ] are undefined if flag_rC && mode64
3677 */
3678 /* rD[hi32] are undefined: setting them to sign of lo32
3679 - makes set_CR0 happy */
3680 IRExpr* dividend = mk64lo32Sto64( mkexpr(rA) );
3681 IRExpr* divisor = mk64lo32Sto64( mkexpr(rB) );
3682 assign( rD, mk64lo32Uto64( binop(Iop_DivS64, dividend,
3683 divisor) ) );
3684 if (flag_OE) {
3685 set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
3686 mkexpr(rD), dividend, divisor );
3687 }
3688 } else {
3689 assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) );
3690 if (flag_OE) {
3691 set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
3692 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3693 }
3694 }
3695 /* Note:
3696 if (0x8000_0000 / -1) or (x / 0)
3697 => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
3698 => But _no_ exception raised. */
3699 break;
3700
3701 case 0x1CB: // divwu (Divide Word Unsigned, PPC32 p389)
3702 DIP("divwu%s%s r%u,r%u,r%u\n",
3703 flag_OE ? "o" : "", flag_rC ? ".":"",
3704 rD_addr, rA_addr, rB_addr);
3705 if (mode64) {
3706 /* Note:
3707 XER settings are mode independent, and reflect the
3708 overflow of the low-order 32bit result
3709 CR0[LT|GT|EQ] are undefined if flag_rC && mode64
3710 */
3711 IRExpr* dividend = mk64lo32Uto64( mkexpr(rA) );
3712 IRExpr* divisor = mk64lo32Uto64( mkexpr(rB) );
3713 assign( rD, mk64lo32Uto64( binop(Iop_DivU64, dividend,
3714 divisor) ) );
3715 if (flag_OE) {
3716 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
3717 mkexpr(rD), dividend, divisor );
3718 }
3719 } else {
3720 assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) );
3721 if (flag_OE) {
3722 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
3723 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3724 }
3725 }
3726 /* Note: ditto comment divw, for (x / 0) */
3727 break;
3728
3729 case 0x04B: // mulhw (Multiply High Word, PPC32 p488)
3730 if (flag_OE != 0) {
3731 vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n");
3732 return False;
3733 }
3734 DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3735 rD_addr, rA_addr, rB_addr);
3736 if (mode64) {
3737 /* rD[hi32] are undefined: setting them to sign of lo32
3738 - makes set_CR0 happy */
3739 assign( rD, binop(Iop_Sar64,
3740 binop(Iop_Mul64,
3741 mk64lo32Sto64( mkexpr(rA) ),
3742 mk64lo32Sto64( mkexpr(rB) )),
3743 mkU8(32)) );
3744 } else {
3745 assign( rD, unop(Iop_64HIto32,
3746 binop(Iop_MullS32,
3747 mkexpr(rA), mkexpr(rB))) );
3748 }
3749 break;
3750
3751 case 0x00B: // mulhwu (Multiply High Word Unsigned, PPC32 p489)
3752 if (flag_OE != 0) {
3753 vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n");
3754 return False;
3755 }
3756 DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3757 rD_addr, rA_addr, rB_addr);
3758 if (mode64) {
3759 /* rD[hi32] are undefined: setting them to sign of lo32
3760 - makes set_CR0 happy */
3761 assign( rD, binop(Iop_Sar64,
3762 binop(Iop_Mul64,
3763 mk64lo32Uto64( mkexpr(rA) ),
3764 mk64lo32Uto64( mkexpr(rB) ) ),
3765 mkU8(32)) );
3766 } else {
3767 assign( rD, unop(Iop_64HIto32,
3768 binop(Iop_MullU32,
3769 mkexpr(rA), mkexpr(rB))) );
3770 }
3771 break;
3772
3773 case 0x0EB: // mullw (Multiply Low Word, PPC32 p491)
3774 DIP("mullw%s%s r%u,r%u,r%u\n",
3775 flag_OE ? "o" : "", flag_rC ? ".":"",
3776 rD_addr, rA_addr, rB_addr);
3777 if (mode64) {
3778 /* rD[hi32] are undefined: setting them to sign of lo32
3779 - set_XER_OV() and set_CR0() depend on this */
3780 IRExpr *a = unop(Iop_64to32, mkexpr(rA) );
3781 IRExpr *b = unop(Iop_64to32, mkexpr(rB) );
3782 assign( rD, binop(Iop_MullS32, a, b) );
3783 if (flag_OE) {
3784 set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
3785 mkexpr(rD),
3786 unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) );
3787 }
3788 } else {
3789 assign( rD, unop(Iop_64to32,
3790 binop(Iop_MullU32,
3791 mkexpr(rA), mkexpr(rB))) );
3792 if (flag_OE) {
3793 set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
3794 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3795 }
3796 }
3797 break;
3798
3799 case 0x068: // neg (Negate, PPC32 p493)
3800 if (rB_addr != 0) {
3801 vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n");
3802 return False;
3803 }
3804 DIP("neg%s%s r%u,r%u\n",
3805 flag_OE ? "o" : "", flag_rC ? ".":"",
3806 rD_addr, rA_addr);
3807 // rD = (~rA) + 1
3808 assign( rD, binop( mkSzOp(ty, Iop_Add8),
3809 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ),
3810 mkSzImm(ty, 1)) );
3811 if (flag_OE) {
3812 set_XER_OV( ty, PPCG_FLAG_OP_NEG,
3813 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3814 }
3815 break;
3816
3817 case 0x028: // subf (Subtract From, PPC32 p537)
3818 DIP("subf%s%s r%u,r%u,r%u\n",
3819 flag_OE ? "o" : "", flag_rC ? ".":"",
3820 rD_addr, rA_addr, rB_addr);
3821 // rD = rB - rA
3822 assign( rD, binop( mkSzOp(ty, Iop_Sub8),
3823 mkexpr(rB), mkexpr(rA)) );
3824 if (flag_OE) {
3825 set_XER_OV( ty, PPCG_FLAG_OP_SUBF,
3826 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3827 }
3828 break;
3829
3830 case 0x008: // subfc (Subtract from Carrying, PPC32 p538)
3831 DIP("subfc%s%s r%u,r%u,r%u\n",
3832 flag_OE ? "o" : "", flag_rC ? ".":"",
3833 rD_addr, rA_addr, rB_addr);
3834 // rD = rB - rA
3835 assign( rD, binop( mkSzOp(ty, Iop_Sub8),
3836 mkexpr(rB), mkexpr(rA)) );
3837 set_XER_CA( ty, PPCG_FLAG_OP_SUBFC,
3838 mkexpr(rD), mkexpr(rA), mkexpr(rB),
3839 mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
3840 if (flag_OE) {
3841 set_XER_OV( ty, PPCG_FLAG_OP_SUBFC,
3842 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3843 }
3844 break;
3845
3846 case 0x088: {// subfe (Subtract from Extended, PPC32 p539)
3847 IRTemp old_xer_ca = newTemp(ty);
3848 DIP("subfe%s%s r%u,r%u,r%u\n",
3849 flag_OE ? "o" : "", flag_rC ? ".":"",
3850 rD_addr, rA_addr, rB_addr);
3851 // rD = (log not)rA + rB + XER[CA]
3852 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3853 assign( rD, binop( mkSzOp(ty, Iop_Add8),
3854 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
3855 binop( mkSzOp(ty, Iop_Add8),
3856 mkexpr(rB), mkexpr(old_xer_ca))) );
3857 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
3858 mkexpr(rD), mkexpr(rA), mkexpr(rB),
3859 mkexpr(old_xer_ca) );
3860 if (flag_OE) {
3861 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
3862 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3863 }
3864 break;
3865 }
3866
3867 case 0x0E8: { // subfme (Subtract from -1 Extended, PPC32 p541)
3868 IRTemp old_xer_ca = newTemp(ty);
3869 IRExpr *min_one;
3870 if (rB_addr != 0) {
3871 vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n");
3872 return False;
3873 }
3874 DIP("subfme%s%s r%u,r%u\n",
3875 flag_OE ? "o" : "", flag_rC ? ".":"",
3876 rD_addr, rA_addr);
3877 // rD = (log not)rA + (-1) + XER[CA]
3878 // => Just another form of subfe
3879 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3880 min_one = mkSzImm(ty, (Long)-1);
3881 assign( rD, binop( mkSzOp(ty, Iop_Add8),
3882 unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
3883 binop( mkSzOp(ty, Iop_Add8),
3884 min_one, mkexpr(old_xer_ca))) );
3885 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
3886 mkexpr(rD), mkexpr(rA), min_one,
3887 mkexpr(old_xer_ca) );
3888 if (flag_OE) {
3889 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
3890 mkexpr(rD), mkexpr(rA), min_one );
3891 }
3892 break;
3893 }
3894
3895 case 0x0C8: { // subfze (Subtract from Zero Extended, PPC32 p542)
3896 IRTemp old_xer_ca = newTemp(ty);
3897 if (rB_addr != 0) {
3898 vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n");
3899 return False;
3900 }
3901 DIP("subfze%s%s r%u,r%u\n",
3902 flag_OE ? "o" : "", flag_rC ? ".":"",
3903 rD_addr, rA_addr);
3904 // rD = (log not)rA + (0) + XER[CA]
3905 // => Just another form of subfe
3906 assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3907 assign( rD, binop( mkSzOp(ty, Iop_Add8),
3908 unop( mkSzOp(ty, Iop_Not8),
3909 mkexpr(rA)), mkexpr(old_xer_ca)) );
3910 set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
3911 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
3912 mkexpr(old_xer_ca) );
3913 if (flag_OE) {
3914 set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
3915 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
3916 }
3917 break;
3918 }
3919
3920
3921 /* 64bit Arithmetic */
3922 case 0x49: // mulhd (Multiply High DWord, PPC64 p539)
3923 if (flag_OE != 0) {
3924 vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n");
3925 return False;
3926 }
3927 DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3928 rD_addr, rA_addr, rB_addr);
3929 assign( rD, unop(Iop_128HIto64,
3930 binop(Iop_MullS64,
3931 mkexpr(rA), mkexpr(rB))) );
3932
3933 break;
3934
3935 case 0x9: // mulhdu (Multiply High DWord Unsigned, PPC64 p540)
3936 if (flag_OE != 0) {
3937 vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n");
3938 return False;
3939 }
3940 DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3941 rD_addr, rA_addr, rB_addr);
3942 assign( rD, unop(Iop_128HIto64,
3943 binop(Iop_MullU64,
3944 mkexpr(rA), mkexpr(rB))) );
3945 break;
3946
3947 case 0xE9: // mulld (Multiply Low DWord, PPC64 p543)
3948 DIP("mulld%s%s r%u,r%u,r%u\n",
3949 flag_OE ? "o" : "", flag_rC ? ".":"",
3950 rD_addr, rA_addr, rB_addr);
3951 assign( rD, binop(Iop_Mul64, mkexpr(rA), mkexpr(rB)) );
3952 if (flag_OE) {
3953 set_XER_OV( ty, PPCG_FLAG_OP_MULLD,
3954 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3955 }
3956 break;
3957
3958 case 0x1E9: // divd (Divide DWord, PPC64 p419)
3959 DIP("divd%s%s r%u,r%u,r%u\n",
3960 flag_OE ? "o" : "", flag_rC ? ".":"",
3961 rD_addr, rA_addr, rB_addr);
3962 assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) );
3963 if (flag_OE) {
3964 set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
3965 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3966 }
3967 break;
3968 /* Note:
3969 if (0x8000_0000_0000_0000 / -1) or (x / 0)
3970 => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
3971 => But _no_ exception raised. */
3972
3973 case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420)
3974 DIP("divdu%s%s r%u,r%u,r%u\n",
3975 flag_OE ? "o" : "", flag_rC ? ".":"",
3976 rD_addr, rA_addr, rB_addr);
3977 assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) );
3978 if (flag_OE) {
3979 set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
3980 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3981 }
3982 break;
3983 /* Note: ditto comment divd, for (x / 0) */
3984
3985 case 0x18B: // divweu (Divide Word Extended Unsigned)
3986 {
3987 /*
3988 * If (RA) >= (RB), or if an attempt is made to perform the division
3989 * <anything> / 0
3990 * then the contents of register RD are undefined as are (if Rc=1) the contents of
3991 * the LT, GT, and EQ bits of CR Field 0. In these cases, if OE=1 then OV is set
3992 * to 1.
3993 */
3994 IRTemp res = newTemp(Ity_I32);
3995 IRExpr * dividend, * divisor;
3996 DIP("divweu%s%s r%u,r%u,r%u\n",
3997 flag_OE ? "o" : "", flag_rC ? ".":"",
3998 rD_addr, rA_addr, rB_addr);
3999 if (mode64) {
4000 dividend = unop( Iop_64to32, mkexpr( rA ) );
4001 divisor = unop( Iop_64to32, mkexpr( rB ) );
4002 assign( res, binop( Iop_DivU32E, dividend, divisor ) );
4003 assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
4004 } else {
4005 dividend = mkexpr( rA );
4006 divisor = mkexpr( rB );
4007 assign( res, binop( Iop_DivU32E, dividend, divisor ) );
4008 assign( rD, mkexpr( res) );
4009 }
4010
4011 if (flag_OE) {
4012 set_XER_OV_32( PPCG_FLAG_OP_DIVWEU,
4013 mkexpr(res), dividend, divisor );
4014 }
4015 break;
4016 }
4017
4018 case 0x1AB: // divwe (Divide Word Extended)
4019 {
4020 /*
4021 * If the quotient cannot be represented in 32 bits, or if an
4022 * attempt is made to perform the division
4023 * <anything> / 0
4024 * then the contents of register RD are undefined as are (if
4025 * Rc=1) the contents of the LT, GT, and EQ bits of CR
4026 * Field 0. In these cases, if OE=1 then OV is set to 1.
4027 */
4028
4029 IRTemp res = newTemp(Ity_I32);
4030 IRExpr * dividend, * divisor;
4031 DIP("divwe%s%s r%u,r%u,r%u\n",
4032 flag_OE ? "o" : "", flag_rC ? ".":"",
4033 rD_addr, rA_addr, rB_addr);
4034 if (mode64) {
4035 dividend = unop( Iop_64to32, mkexpr( rA ) );
4036 divisor = unop( Iop_64to32, mkexpr( rB ) );
4037 assign( res, binop( Iop_DivS32E, dividend, divisor ) );
4038 assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
4039 } else {
4040 dividend = mkexpr( rA );
4041 divisor = mkexpr( rB );
4042 assign( res, binop( Iop_DivS32E, dividend, divisor ) );
4043 assign( rD, mkexpr( res) );
4044 }
4045
4046 if (flag_OE) {
4047 set_XER_OV_32( PPCG_FLAG_OP_DIVWE,
4048 mkexpr(res), dividend, divisor );
4049 }
4050 break;
4051 }
4052
4053
4054 case 0x1A9: // divde (Divide Doubleword Extended)
4055 /*
4056 * If the quotient cannot be represented in 64 bits, or if an
4057 * attempt is made to perform the division
4058 * <anything> / 0
4059 * then the contents of register RD are undefined as are (if
4060 * Rc=1) the contents of the LT, GT, and EQ bits of CR
4061 * Field 0. In these cases, if OE=1 then OV is set to 1.
4062 */
4063 DIP("divde%s%s r%u,r%u,r%u\n",
4064 flag_OE ? "o" : "", flag_rC ? ".":"",
4065 rD_addr, rA_addr, rB_addr);
4066 assign( rD, binop(Iop_DivS64E, mkexpr(rA), mkexpr(rB)) );
4067 if (flag_OE) {
4068 set_XER_OV_64( PPCG_FLAG_OP_DIVDE, mkexpr( rD ),
4069 mkexpr( rA ), mkexpr( rB ) );
4070 }
4071 break;
4072
4073 case 0x189: // divdeuo (Divide Doubleword Extended Unsigned)
4074 // Same CR and OV rules as given for divweu above
4075 DIP("divdeu%s%s r%u,r%u,r%u\n",
4076 flag_OE ? "o" : "", flag_rC ? ".":"",
4077 rD_addr, rA_addr, rB_addr);
4078 assign( rD, binop(Iop_DivU64E, mkexpr(rA), mkexpr(rB)) );
4079 if (flag_OE) {
4080 set_XER_OV_64( PPCG_FLAG_OP_DIVDEU, mkexpr( rD ),
4081 mkexpr( rA ), mkexpr( rB ) );
4082 }
4083 break;
4084
4085 default:
4086 vex_printf("dis_int_arith(ppc)(opc2)\n");
4087 return False;
4088 }
4089 break;
4090
4091 default:
4092 vex_printf("dis_int_arith(ppc)(opc1)\n");
4093 return False;
4094 }
4095
4096 putIReg( rD_addr, mkexpr(rD) );
4097
4098 if (do_rc && flag_rC) {
4099 set_CR0( mkexpr(rD) );
4100 }
4101 return True;
4102 }
4103
4104
4105
4106 /*
4107 Integer Compare Instructions
4108 */
dis_int_cmp(UInt theInstr)4109 static Bool dis_int_cmp ( UInt theInstr )
4110 {
4111 /* D-Form, X-Form */
4112 UChar opc1 = ifieldOPC(theInstr);
4113 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) );
4114 UChar b22 = toUChar( IFIELD( theInstr, 22, 1 ) );
4115 UChar flag_L = toUChar( IFIELD( theInstr, 21, 1 ) );
4116 UChar rA_addr = ifieldRegA(theInstr);
4117 UInt uimm16 = ifieldUIMM16(theInstr);
4118 UChar rB_addr = ifieldRegB(theInstr);
4119 UInt opc2 = ifieldOPClo10(theInstr);
4120 UChar b0 = ifieldBIT0(theInstr);
4121
4122 IRType ty = mode64 ? Ity_I64 : Ity_I32;
4123 IRExpr *a = getIReg(rA_addr);
4124 IRExpr *b;
4125
4126 if (!mode64 && flag_L==1) { // L==1 invalid for 32 bit.
4127 vex_printf("dis_int_cmp(ppc)(flag_L)\n");
4128 return False;
4129 }
4130
4131 if (b22 != 0) {
4132 vex_printf("dis_int_cmp(ppc)(b22)\n");
4133 return False;
4134 }
4135
4136 switch (opc1) {
4137 case 0x0B: // cmpi (Compare Immediate, PPC32 p368)
4138 DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr,
4139 (Int)extend_s_16to32(uimm16));
4140 b = mkSzExtendS16( ty, uimm16 );
4141 if (flag_L == 1) {
4142 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
4143 } else {
4144 a = mkNarrowTo32( ty, a );
4145 b = mkNarrowTo32( ty, b );
4146 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b)));
4147 }
4148 putCR0( crfD, getXER_SO() );
4149 break;
4150
4151 case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370)
4152 DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16);
4153 b = mkSzImm( ty, uimm16 );
4154 if (flag_L == 1) {
4155 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
4156 } else {
4157 a = mkNarrowTo32( ty, a );
4158 b = mkNarrowTo32( ty, b );
4159 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
4160 }
4161 putCR0( crfD, getXER_SO() );
4162 break;
4163
4164 /* X Form */
4165 case 0x1F:
4166 if (b0 != 0) {
4167 vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n");
4168 return False;
4169 }
4170 b = getIReg(rB_addr);
4171
4172 switch (opc2) {
4173 case 0x000: // cmp (Compare, PPC32 p367)
4174 DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
4175 /* Comparing a reg with itself produces a result which
4176 doesn't depend on the contents of the reg. Therefore
4177 remove the false dependency, which has been known to cause
4178 memcheck to produce false errors. */
4179 if (rA_addr == rB_addr)
4180 a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
4181 ? mkU64(0) : mkU32(0);
4182 if (flag_L == 1) {
4183 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
4184 } else {
4185 a = mkNarrowTo32( ty, a );
4186 b = mkNarrowTo32( ty, b );
4187 putCR321(crfD, unop(Iop_32to8,binop(Iop_CmpORD32S, a, b)));
4188 }
4189 putCR0( crfD, getXER_SO() );
4190 break;
4191
4192 case 0x020: // cmpl (Compare Logical, PPC32 p369)
4193 DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
4194 /* Comparing a reg with itself produces a result which
4195 doesn't depend on the contents of the reg. Therefore
4196 remove the false dependency, which has been known to cause
4197 memcheck to produce false errors. */
4198 if (rA_addr == rB_addr)
4199 a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
4200 ? mkU64(0) : mkU32(0);
4201 if (flag_L == 1) {
4202 putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
4203 } else {
4204 a = mkNarrowTo32( ty, a );
4205 b = mkNarrowTo32( ty, b );
4206 putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
4207 }
4208 putCR0( crfD, getXER_SO() );
4209 break;
4210
4211 default:
4212 vex_printf("dis_int_cmp(ppc)(opc2)\n");
4213 return False;
4214 }
4215 break;
4216
4217 default:
4218 vex_printf("dis_int_cmp(ppc)(opc1)\n");
4219 return False;
4220 }
4221
4222 return True;
4223 }
4224
4225
4226 /*
4227 Integer Logical Instructions
4228 */
dis_int_logic(UInt theInstr)4229 static Bool dis_int_logic ( UInt theInstr )
4230 {
4231 /* D-Form, X-Form */
4232 UChar opc1 = ifieldOPC(theInstr);
4233 UChar rS_addr = ifieldRegDS(theInstr);
4234 UChar rA_addr = ifieldRegA(theInstr);
4235 UInt uimm16 = ifieldUIMM16(theInstr);
4236 UChar rB_addr = ifieldRegB(theInstr);
4237 UInt opc2 = ifieldOPClo10(theInstr);
4238 UChar flag_rC = ifieldBIT0(theInstr);
4239
4240 IRType ty = mode64 ? Ity_I64 : Ity_I32;
4241 IRTemp rS = newTemp(ty);
4242 IRTemp rA = newTemp(ty);
4243 IRTemp rB = newTemp(ty);
4244 IRExpr* irx;
4245 Bool do_rc = False;
4246
4247 assign( rS, getIReg(rS_addr) );
4248 assign( rB, getIReg(rB_addr) );
4249
4250 switch (opc1) {
4251 case 0x1C: // andi. (AND Immediate, PPC32 p358)
4252 DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
4253 assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
4254 mkSzImm(ty, uimm16)) );
4255 do_rc = True; // Always record to CR
4256 flag_rC = 1;
4257 break;
4258
4259 case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359)
4260 DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
4261 assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
4262 mkSzImm(ty, uimm16 << 16)) );
4263 do_rc = True; // Always record to CR
4264 flag_rC = 1;
4265 break;
4266
4267 case 0x18: // ori (OR Immediate, PPC32 p497)
4268 DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
4269 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
4270 mkSzImm(ty, uimm16)) );
4271 break;
4272
4273 case 0x19: // oris (OR Immediate Shifted, PPC32 p498)
4274 DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
4275 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
4276 mkSzImm(ty, uimm16 << 16)) );
4277 break;
4278
4279 case 0x1A: // xori (XOR Immediate, PPC32 p550)
4280 DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
4281 assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
4282 mkSzImm(ty, uimm16)) );
4283 break;
4284
4285 case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551)
4286 DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
4287 assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
4288 mkSzImm(ty, uimm16 << 16)) );
4289 break;
4290
4291 /* X Form */
4292 case 0x1F:
4293 do_rc = True; // All below record to CR, except for where we return at case end.
4294
4295 switch (opc2) {
4296 case 0x01C: // and (AND, PPC32 p356)
4297 DIP("and%s r%u,r%u,r%u\n",
4298 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4299 assign(rA, binop( mkSzOp(ty, Iop_And8),
4300 mkexpr(rS), mkexpr(rB)));
4301 break;
4302
4303 case 0x03C: // andc (AND with Complement, PPC32 p357)
4304 DIP("andc%s r%u,r%u,r%u\n",
4305 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4306 assign(rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
4307 unop( mkSzOp(ty, Iop_Not8),
4308 mkexpr(rB))));
4309 break;
4310
4311 case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371)
4312 IRExpr* lo32;
4313 if (rB_addr!=0) {
4314 vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n");
4315 return False;
4316 }
4317 DIP("cntlzw%s r%u,r%u\n",
4318 flag_rC ? ".":"", rA_addr, rS_addr);
4319
4320 // mode64: count in low word only
4321 lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS);
4322
4323 // Iop_Clz32 undefined for arg==0, so deal with that case:
4324 irx = binop(Iop_CmpNE32, lo32, mkU32(0));
4325 assign(rA, mkWidenFrom32(ty,
4326 IRExpr_ITE( irx,
4327 unop(Iop_Clz32, lo32),
4328 mkU32(32)),
4329 False));
4330
4331 // TODO: alternatively: assign(rA, verbose_Clz32(rS));
4332 break;
4333 }
4334
4335 case 0x11C: // eqv (Equivalent, PPC32 p396)
4336 DIP("eqv%s r%u,r%u,r%u\n",
4337 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4338 assign( rA, unop( mkSzOp(ty, Iop_Not8),
4339 binop( mkSzOp(ty, Iop_Xor8),
4340 mkexpr(rS), mkexpr(rB))) );
4341 break;
4342
4343 case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397
4344 if (rB_addr!=0) {
4345 vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n");
4346 return False;
4347 }
4348 DIP("extsb%s r%u,r%u\n",
4349 flag_rC ? ".":"", rA_addr, rS_addr);
4350 if (mode64)
4351 assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) );
4352 else
4353 assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) );
4354 break;
4355
4356 case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398)
4357 if (rB_addr!=0) {
4358 vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n");
4359 return False;
4360 }
4361 DIP("extsh%s r%u,r%u\n",
4362 flag_rC ? ".":"", rA_addr, rS_addr);
4363 if (mode64)
4364 assign( rA, unop(Iop_16Sto64,
4365 unop(Iop_64to16, mkexpr(rS))) );
4366 else
4367 assign( rA, unop(Iop_16Sto32,
4368 unop(Iop_32to16, mkexpr(rS))) );
4369 break;
4370
4371 case 0x1DC: // nand (NAND, PPC32 p492)
4372 DIP("nand%s r%u,r%u,r%u\n",
4373 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4374 assign( rA, unop( mkSzOp(ty, Iop_Not8),
4375 binop( mkSzOp(ty, Iop_And8),
4376 mkexpr(rS), mkexpr(rB))) );
4377 break;
4378
4379 case 0x07C: // nor (NOR, PPC32 p494)
4380 DIP("nor%s r%u,r%u,r%u\n",
4381 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4382 assign( rA, unop( mkSzOp(ty, Iop_Not8),
4383 binop( mkSzOp(ty, Iop_Or8),
4384 mkexpr(rS), mkexpr(rB))) );
4385 break;
4386
4387 case 0x1BC: // or (OR, PPC32 p495)
4388 if ((!flag_rC) && rS_addr == rB_addr) {
4389 DIP("mr r%u,r%u\n", rA_addr, rS_addr);
4390 assign( rA, mkexpr(rS) );
4391 } else {
4392 DIP("or%s r%u,r%u,r%u\n",
4393 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4394 assign( rA, binop( mkSzOp(ty, Iop_Or8),
4395 mkexpr(rS), mkexpr(rB)) );
4396 }
4397 break;
4398
4399 case 0x19C: // orc (OR with Complement, PPC32 p496)
4400 DIP("orc%s r%u,r%u,r%u\n",
4401 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4402 assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
4403 unop(mkSzOp(ty, Iop_Not8), mkexpr(rB))));
4404 break;
4405
4406 case 0x13C: // xor (XOR, PPC32 p549)
4407 DIP("xor%s r%u,r%u,r%u\n",
4408 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4409 assign( rA, binop( mkSzOp(ty, Iop_Xor8),
4410 mkexpr(rS), mkexpr(rB)) );
4411 break;
4412
4413
4414 /* 64bit Integer Logical Instructions */
4415 case 0x3DA: // extsw (Extend Sign Word, PPC64 p430)
4416 if (rB_addr!=0) {
4417 vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n");
4418 return False;
4419 }
4420 DIP("extsw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr);
4421 assign(rA, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(rS))));
4422 break;
4423
4424 case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401)
4425 if (rB_addr!=0) {
4426 vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n");
4427 return False;
4428 }
4429 DIP("cntlzd%s r%u,r%u\n",
4430 flag_rC ? ".":"", rA_addr, rS_addr);
4431 // Iop_Clz64 undefined for arg==0, so deal with that case:
4432 irx = binop(Iop_CmpNE64, mkexpr(rS), mkU64(0));
4433 assign(rA, IRExpr_ITE( irx,
4434 unop(Iop_Clz64, mkexpr(rS)),
4435 mkU64(64) ));
4436 // TODO: alternatively: assign(rA, verbose_Clz64(rS));
4437 break;
4438
4439 case 0x1FC: // cmpb (Power6: compare bytes)
4440 DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
4441
4442 if (mode64)
4443 assign( rA, unop( Iop_V128to64,
4444 binop( Iop_CmpEQ8x16,
4445 binop( Iop_64HLtoV128, mkU64(0), mkexpr(rS) ),
4446 binop( Iop_64HLtoV128, mkU64(0), mkexpr(rB) )
4447 )) );
4448 else
4449 assign( rA, unop( Iop_V128to32,
4450 binop( Iop_CmpEQ8x16,
4451 unop( Iop_32UtoV128, mkexpr(rS) ),
4452 unop( Iop_32UtoV128, mkexpr(rB) )
4453 )) );
4454 break;
4455
4456 case 0x2DF: { // mftgpr (move floating-point to general purpose register)
4457 IRTemp frB = newTemp(Ity_F64);
4458 DIP("mftgpr r%u,fr%u\n", rS_addr, rB_addr);
4459
4460 assign( frB, getFReg(rB_addr)); // always F64
4461 if (mode64)
4462 assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
4463 else
4464 assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) );
4465
4466 putIReg( rS_addr, mkexpr(rA));
4467 return True;
4468 }
4469
4470 case 0x25F: { // mffgpr (move floating-point from general purpose register)
4471 IRTemp frA = newTemp(Ity_F64);
4472 DIP("mffgpr fr%u,r%u\n", rS_addr, rB_addr);
4473
4474 if (mode64)
4475 assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) );
4476 else
4477 assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) );
4478
4479 putFReg( rS_addr, mkexpr(frA));
4480 return True;
4481 }
4482 case 0x1FA: // popcntd (population count doubleword
4483 {
4484 DIP("popcntd r%u,r%u\n", rA_addr, rS_addr);
4485 IRTemp result = gen_POPCOUNT(ty, rS, DWORD);
4486 putIReg( rA_addr, mkexpr(result) );
4487 return True;
4488 }
4489 case 0x17A: // popcntw (Population Count Words)
4490 {
4491 DIP("popcntw r%u,r%u\n", rA_addr, rS_addr);
4492 if (mode64) {
4493 IRTemp resultHi, resultLo;
4494 IRTemp argLo = newTemp(Ity_I32);
4495 IRTemp argHi = newTemp(Ity_I32);
4496 assign(argLo, unop(Iop_64to32, mkexpr(rS)));
4497 assign(argHi, unop(Iop_64HIto32, mkexpr(rS)));
4498 resultLo = gen_POPCOUNT(Ity_I32, argLo, WORD);
4499 resultHi = gen_POPCOUNT(Ity_I32, argHi, WORD);
4500 putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), mkexpr(resultLo)));
4501 } else {
4502 IRTemp result = gen_POPCOUNT(ty, rS, WORD);
4503 putIReg( rA_addr, mkexpr(result) );
4504 }
4505 return True;
4506 }
4507 case 0x7A: // popcntb (Population Count Byte)
4508 {
4509 DIP("popcntb r%u,r%u\n", rA_addr, rS_addr);
4510
4511 if (mode64) {
4512 IRTemp resultHi, resultLo;
4513 IRTemp argLo = newTemp(Ity_I32);
4514 IRTemp argHi = newTemp(Ity_I32);
4515 assign(argLo, unop(Iop_64to32, mkexpr(rS)));
4516 assign(argHi, unop(Iop_64HIto32, mkexpr(rS)));
4517 resultLo = gen_POPCOUNT(Ity_I32, argLo, BYTE);
4518 resultHi = gen_POPCOUNT(Ity_I32, argHi, BYTE);
4519 putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi),
4520 mkexpr(resultLo)));
4521 } else {
4522 IRTemp result = gen_POPCOUNT(ty, rS, BYTE);
4523 putIReg( rA_addr, mkexpr(result) );
4524 }
4525 return True;
4526 }
4527 case 0x0FC: // bpermd (Bit Permute Doubleword)
4528 {
4529 /* This is a lot of rigmarole to emulate bpermd like this, as it
4530 * could be done much faster by implementing a call to the native
4531 * instruction. However, where possible I want to avoid using new
4532 * native instructions so that we can use valgrind to emulate those
4533 * instructions on older PPC64 hardware.
4534 */
4535 #define BPERMD_IDX_MASK 0x00000000000000FFULL
4536 #define BPERMD_BIT_MASK 0x8000000000000000ULL
4537 int i;
4538 IRExpr * rS_expr = mkexpr(rS);
4539 IRExpr * res = binop(Iop_And64, mkU64(0), mkU64(0));
4540 DIP("bpermd r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
4541 for (i = 0; i < 8; i++) {
4542 IRTemp idx_tmp = newTemp( Ity_I64 );
4543 IRTemp perm_bit = newTemp( Ity_I64 );
4544 IRTemp idx = newTemp( Ity_I8 );
4545 IRTemp idx_LT64 = newTemp( Ity_I1 );
4546 IRTemp idx_LT64_ity64 = newTemp( Ity_I64 );
4547
4548 assign( idx_tmp,
4549 binop( Iop_And64, mkU64( BPERMD_IDX_MASK ), rS_expr ) );
4550 assign( idx_LT64,
4551 binop( Iop_CmpLT64U, mkexpr( idx_tmp ), mkU64( 64 ) ) );
4552 assign( idx,
4553 binop( Iop_And8,
4554 unop( Iop_1Sto8,
4555 mkexpr(idx_LT64) ),
4556 unop( Iop_64to8, mkexpr( idx_tmp ) ) ) );
4557 /* If idx_LT64 == 0, we must force the perm bit to '0'. Below, we se idx
4558 * to determine which bit of rB to use for the perm bit, and then we shift
4559 * that bit to the MSB position. We AND that with a 64-bit-ized idx_LT64
4560 * to set the final perm bit.
4561 */
4562 assign( idx_LT64_ity64,
4563 unop( Iop_32Uto64, unop( Iop_1Uto32, mkexpr(idx_LT64 ) ) ) );
4564 assign( perm_bit,
4565 binop( Iop_And64,
4566 mkexpr( idx_LT64_ity64 ),
4567 binop( Iop_Shr64,
4568 binop( Iop_And64,
4569 mkU64( BPERMD_BIT_MASK ),
4570 binop( Iop_Shl64,
4571 mkexpr( rB ),
4572 mkexpr( idx ) ) ),
4573 mkU8( 63 ) ) ) );
4574 res = binop( Iop_Or64,
4575 res,
4576 binop( Iop_Shl64,
4577 mkexpr( perm_bit ),
4578 mkU8( i ) ) );
4579 rS_expr = binop( Iop_Shr64, rS_expr, mkU8( 8 ) );
4580 }
4581 putIReg(rA_addr, res);
4582 return True;
4583 }
4584
4585 default:
4586 vex_printf("dis_int_logic(ppc)(opc2)\n");
4587 return False;
4588 }
4589 break;
4590
4591 default:
4592 vex_printf("dis_int_logic(ppc)(opc1)\n");
4593 return False;
4594 }
4595
4596 putIReg( rA_addr, mkexpr(rA) );
4597
4598 if (do_rc && flag_rC) {
4599 set_CR0( mkexpr(rA) );
4600 }
4601 return True;
4602 }
4603
4604 /*
4605 Integer Parity Instructions
4606 */
dis_int_parity(UInt theInstr)4607 static Bool dis_int_parity ( UInt theInstr )
4608 {
4609 /* X-Form */
4610 UChar opc1 = ifieldOPC(theInstr);
4611 UChar rS_addr = ifieldRegDS(theInstr);
4612 UChar rA_addr = ifieldRegA(theInstr);
4613 UChar rB_addr = ifieldRegB(theInstr);
4614 UInt opc2 = ifieldOPClo10(theInstr);
4615 UChar b0 = ifieldBIT0(theInstr);
4616 IRType ty = mode64 ? Ity_I64 : Ity_I32;
4617
4618 IRTemp rS = newTemp(ty);
4619 IRTemp rA = newTemp(ty);
4620 IRTemp iTot1 = newTemp(Ity_I32);
4621 IRTemp iTot2 = newTemp(Ity_I32);
4622 IRTemp iTot3 = newTemp(Ity_I32);
4623 IRTemp iTot4 = newTemp(Ity_I32);
4624 IRTemp iTot5 = newTemp(Ity_I32);
4625 IRTemp iTot6 = newTemp(Ity_I32);
4626 IRTemp iTot7 = newTemp(Ity_I32);
4627 IRTemp iTot8 = newTemp(Ity_I32);
4628 IRTemp rS1 = newTemp(ty);
4629 IRTemp rS2 = newTemp(ty);
4630 IRTemp rS3 = newTemp(ty);
4631 IRTemp rS4 = newTemp(ty);
4632 IRTemp rS5 = newTemp(ty);
4633 IRTemp rS6 = newTemp(ty);
4634 IRTemp rS7 = newTemp(ty);
4635 IRTemp iHi = newTemp(Ity_I32);
4636 IRTemp iLo = newTemp(Ity_I32);
4637 IROp to_bit = (mode64 ? Iop_64to1 : Iop_32to1);
4638 IROp shr_op = (mode64 ? Iop_Shr64 : Iop_Shr32);
4639
4640 if (opc1 != 0x1f || rB_addr || b0) {
4641 vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n");
4642 return False;
4643 }
4644
4645 assign( rS, getIReg(rS_addr) );
4646
4647 switch (opc2) {
4648 case 0xba: // prtyd (Parity Doubleword, ISA 2.05 p320)
4649 DIP("prtyd r%u,r%u\n", rA_addr, rS_addr);
4650 assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
4651 assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
4652 assign( iTot2, binop(Iop_Add32,
4653 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
4654 mkexpr(iTot1)) );
4655 assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
4656 assign( iTot3, binop(Iop_Add32,
4657 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
4658 mkexpr(iTot2)) );
4659 assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
4660 assign( iTot4, binop(Iop_Add32,
4661 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
4662 mkexpr(iTot3)) );
4663 if (mode64) {
4664 assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
4665 assign( iTot5, binop(Iop_Add32,
4666 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))),
4667 mkexpr(iTot4)) );
4668 assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
4669 assign( iTot6, binop(Iop_Add32,
4670 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
4671 mkexpr(iTot5)) );
4672 assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
4673 assign( iTot7, binop(Iop_Add32,
4674 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
4675 mkexpr(iTot6)) );
4676 assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)) );
4677 assign( iTot8, binop(Iop_Add32,
4678 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
4679 mkexpr(iTot7)) );
4680 assign( rA, unop(Iop_32Uto64,
4681 binop(Iop_And32, mkexpr(iTot8), mkU32(1))) );
4682 } else
4683 assign( rA, mkexpr(iTot4) );
4684
4685 break;
4686 case 0x9a: // prtyw (Parity Word, ISA 2.05 p320)
4687 assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
4688 assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
4689 assign( iTot2, binop(Iop_Add32,
4690 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
4691 mkexpr(iTot1)) );
4692 assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
4693 assign( iTot3, binop(Iop_Add32,
4694 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
4695 mkexpr(iTot2)) );
4696 assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
4697 assign( iTot4, binop(Iop_Add32,
4698 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
4699 mkexpr(iTot3)) );
4700 assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) );
4701
4702 if (mode64) {
4703 assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
4704 assign( iTot5, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))) );
4705 assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
4706 assign( iTot6, binop(Iop_Add32,
4707 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
4708 mkexpr(iTot5)) );
4709 assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
4710 assign( iTot7, binop(Iop_Add32,
4711 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
4712 mkexpr(iTot6)) );
4713 assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)));
4714 assign( iTot8, binop(Iop_Add32,
4715 unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
4716 mkexpr(iTot7)) );
4717 assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ),
4718 assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) );
4719 } else
4720 assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) );
4721 break;
4722 default:
4723 vex_printf("dis_int_parity(ppc)(opc2)\n");
4724 return False;
4725 }
4726
4727 putIReg( rA_addr, mkexpr(rA) );
4728
4729 return True;
4730 }
4731
4732
4733 /*
4734 Integer Rotate Instructions
4735 */
dis_int_rot(UInt theInstr)4736 static Bool dis_int_rot ( UInt theInstr )
4737 {
4738 /* M-Form, MDS-Form */
4739 UChar opc1 = ifieldOPC(theInstr);
4740 UChar rS_addr = ifieldRegDS(theInstr);
4741 UChar rA_addr = ifieldRegA(theInstr);
4742 UChar rB_addr = ifieldRegB(theInstr);
4743 UChar sh_imm = rB_addr;
4744 UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) );
4745 UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) );
4746 UChar msk_imm = toUChar( IFIELD( theInstr, 5, 6 ) );
4747 UChar opc2 = toUChar( IFIELD( theInstr, 2, 3 ) );
4748 UChar b1 = ifieldBIT1(theInstr);
4749 UChar flag_rC = ifieldBIT0(theInstr);
4750
4751 IRType ty = mode64 ? Ity_I64 : Ity_I32;
4752 IRTemp rS = newTemp(ty);
4753 IRTemp rA = newTemp(ty);
4754 IRTemp rB = newTemp(ty);
4755 IRTemp rot = newTemp(ty);
4756 IRExpr *r;
4757 UInt mask32;
4758 ULong mask64;
4759
4760 assign( rS, getIReg(rS_addr) );
4761 assign( rB, getIReg(rB_addr) );
4762
4763 switch (opc1) {
4764 case 0x14: {
4765 // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500)
4766 DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
4767 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
4768 if (mode64) {
4769 // tmp32 = (ROTL(rS_Lo32, Imm)
4770 // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64)
4771 mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
4772 r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
4773 r = unop(Iop_32Uto64, r);
4774 assign( rot, binop(Iop_Or64, r,
4775 binop(Iop_Shl64, r, mkU8(32))) );
4776 assign( rA,
4777 binop(Iop_Or64,
4778 binop(Iop_And64, mkexpr(rot), mkU64(mask64)),
4779 binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) );
4780 }
4781 else {
4782 // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask);
4783 mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
4784 r = ROTL(mkexpr(rS), mkU8(sh_imm));
4785 assign( rA,
4786 binop(Iop_Or32,
4787 binop(Iop_And32, mkU32(mask32), r),
4788 binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) );
4789 }
4790 break;
4791 }
4792
4793 case 0x15: {
4794 // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501)
4795 vassert(MaskBeg < 32);
4796 vassert(MaskEnd < 32);
4797 vassert(sh_imm < 32);
4798
4799 if (mode64) {
4800 IRTemp rTmp = newTemp(Ity_I64);
4801 mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
4802 DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
4803 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
4804 // tmp32 = (ROTL(rS_Lo32, Imm)
4805 // rA = ((tmp32 || tmp32) & mask64)
4806 r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
4807 r = unop(Iop_32Uto64, r);
4808 assign( rTmp, r );
4809 r = NULL;
4810 assign( rot, binop(Iop_Or64, mkexpr(rTmp),
4811 binop(Iop_Shl64, mkexpr(rTmp), mkU8(32))) );
4812 assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
4813 }
4814 else {
4815 if (MaskBeg == 0 && sh_imm+MaskEnd == 31) {
4816 /* Special-case the ,n,0,31-n form as that is just n-bit
4817 shift left, PPC32 p501 */
4818 DIP("slwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
4819 rA_addr, rS_addr, sh_imm);
4820 assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) );
4821 }
4822 else if (MaskEnd == 31 && sh_imm+MaskBeg == 32) {
4823 /* Special-case the ,32-n,n,31 form as that is just n-bit
4824 unsigned shift right, PPC32 p501 */
4825 DIP("srwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
4826 rA_addr, rS_addr, MaskBeg);
4827 assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) );
4828 }
4829 else {
4830 /* General case. */
4831 mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
4832 DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
4833 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
4834 // rA = ROTL(rS, Imm) & mask
4835 assign( rA, binop(Iop_And32,
4836 ROTL(mkexpr(rS), mkU8(sh_imm)),
4837 mkU32(mask32)) );
4838 }
4839 }
4840 break;
4841 }
4842
4843 case 0x17: {
4844 // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503
4845 DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? ".":"",
4846 rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd);
4847 if (mode64) {
4848 mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
4849 /* weird insn alert!
4850 tmp32 = (ROTL(rS_Lo32, rB[0-4])
4851 rA = ((tmp32 || tmp32) & mask64)
4852 */
4853 // note, ROTL does the masking, so we don't do it here
4854 r = ROTL( unop(Iop_64to32, mkexpr(rS)),
4855 unop(Iop_64to8, mkexpr(rB)) );
4856 r = unop(Iop_32Uto64, r);
4857 assign(rot, binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32))));
4858 assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
4859 } else {
4860 mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
4861 // rA = ROTL(rS, rB[0-4]) & mask
4862 // note, ROTL does the masking, so we don't do it here
4863 assign( rA, binop(Iop_And32,
4864 ROTL(mkexpr(rS),
4865 unop(Iop_32to8, mkexpr(rB))),
4866 mkU32(mask32)) );
4867 }
4868 break;
4869 }
4870
4871 /* 64bit Integer Rotates */
4872 case 0x1E: {
4873 msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1);
4874 sh_imm |= b1 << 5;
4875
4876 vassert( msk_imm < 64 );
4877 vassert( sh_imm < 64 );
4878
4879 switch (opc2) {
4880 case 0x4: {
4881 /* r = ROTL64( rS, rB_lo6) */
4882 r = ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) );
4883
4884 if (b1 == 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555)
4885 DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
4886 rA_addr, rS_addr, rB_addr, msk_imm);
4887 // note, ROTL does the masking, so we don't do it here
4888 mask64 = MASK64(0, 63-msk_imm);
4889 assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4890 break;
4891 } else { // rldcr (Rotl DWord, Clear Right, PPC64 p556)
4892 DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
4893 rA_addr, rS_addr, rB_addr, msk_imm);
4894 mask64 = MASK64(63-msk_imm, 63);
4895 assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4896 break;
4897 }
4898 break;
4899 }
4900 case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557)
4901 DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4902 rA_addr, rS_addr, sh_imm, msk_imm);
4903 r = ROTL(mkexpr(rS), mkU8(sh_imm));
4904 mask64 = MASK64(sh_imm, 63-msk_imm);
4905 assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4906 break;
4907 // later: deal with special case: (msk_imm==0) => SHL(sh_imm)
4908 /*
4909 Hmm... looks like this'll do the job more simply:
4910 r = SHL(rS, sh_imm)
4911 m = ~(1 << (63-msk_imm))
4912 assign(rA, r & m);
4913 */
4914
4915 case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558)
4916 if (mode64
4917 && sh_imm + msk_imm == 64 && msk_imm >= 1 && msk_imm <= 63) {
4918 /* special-case the ,64-n,n form as that is just
4919 unsigned shift-right by n */
4920 DIP("srdi%s r%u,r%u,%u\n",
4921 flag_rC ? ".":"", rA_addr, rS_addr, msk_imm);
4922 assign( rA, binop(Iop_Shr64, mkexpr(rS), mkU8(msk_imm)) );
4923 } else {
4924 DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4925 rA_addr, rS_addr, sh_imm, msk_imm);
4926 r = ROTL(mkexpr(rS), mkU8(sh_imm));
4927 mask64 = MASK64(0, 63-msk_imm);
4928 assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4929 }
4930 break;
4931
4932 case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559)
4933 if (mode64
4934 && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) {
4935 /* special-case the ,n,63-n form as that is just
4936 shift-left by n */
4937 DIP("sldi%s r%u,r%u,%u\n",
4938 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
4939 assign( rA, binop(Iop_Shl64, mkexpr(rS), mkU8(sh_imm)) );
4940 } else {
4941 DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4942 rA_addr, rS_addr, sh_imm, msk_imm);
4943 r = ROTL(mkexpr(rS), mkU8(sh_imm));
4944 mask64 = MASK64(63-msk_imm, 63);
4945 assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4946 }
4947 break;
4948
4949 case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560)
4950 IRTemp rA_orig = newTemp(ty);
4951 DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4952 rA_addr, rS_addr, sh_imm, msk_imm);
4953 r = ROTL(mkexpr(rS), mkU8(sh_imm));
4954 mask64 = MASK64(sh_imm, 63-msk_imm);
4955 assign( rA_orig, getIReg(rA_addr) );
4956 assign( rA, binop(Iop_Or64,
4957 binop(Iop_And64, mkU64(mask64), r),
4958 binop(Iop_And64, mkU64(~mask64),
4959 mkexpr(rA_orig))) );
4960 break;
4961 }
4962 default:
4963 vex_printf("dis_int_rot(ppc)(opc2)\n");
4964 return False;
4965 }
4966 break;
4967 }
4968
4969 default:
4970 vex_printf("dis_int_rot(ppc)(opc1)\n");
4971 return False;
4972 }
4973
4974 putIReg( rA_addr, mkexpr(rA) );
4975
4976 if (flag_rC) {
4977 set_CR0( mkexpr(rA) );
4978 }
4979 return True;
4980 }
4981
4982
4983 /*
4984 Integer Load Instructions
4985 */
dis_int_load(UInt theInstr)4986 static Bool dis_int_load ( UInt theInstr )
4987 {
4988 /* D-Form, X-Form, DS-Form */
4989 UChar opc1 = ifieldOPC(theInstr);
4990 UChar rD_addr = ifieldRegDS(theInstr);
4991 UChar rA_addr = ifieldRegA(theInstr);
4992 UInt uimm16 = ifieldUIMM16(theInstr);
4993 UChar rB_addr = ifieldRegB(theInstr);
4994 UInt opc2 = ifieldOPClo10(theInstr);
4995 UChar b1 = ifieldBIT1(theInstr);
4996 UChar b0 = ifieldBIT0(theInstr);
4997
4998 Int simm16 = extend_s_16to32(uimm16);
4999 IRType ty = mode64 ? Ity_I64 : Ity_I32;
5000 IRTemp EA = newTemp(ty);
5001 IRExpr* val;
5002
5003 switch (opc1) {
5004 case 0x1F: // register offset
5005 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
5006 break;
5007 case 0x38: // immediate offset: 64bit: lq: maskoff
5008 // lowest 4 bits of immediate before forming EA
5009 simm16 = simm16 & 0xFFFFFFF0;
5010 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
5011 break;
5012 case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off
5013 // lowest 2 bits of immediate before forming EA
5014 simm16 = simm16 & 0xFFFFFFFC;
5015 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
5016 break;
5017 default: // immediate offset
5018 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
5019 break;
5020 }
5021
5022 switch (opc1) {
5023 case 0x22: // lbz (Load B & Zero, PPC32 p433)
5024 DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
5025 val = load(Ity_I8, mkexpr(EA));
5026 putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
5027 break;
5028
5029 case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434)
5030 if (rA_addr == 0 || rA_addr == rD_addr) {
5031 vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n");
5032 return False;
5033 }
5034 DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
5035 val = load(Ity_I8, mkexpr(EA));
5036 putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
5037 putIReg( rA_addr, mkexpr(EA) );
5038 break;
5039
5040 case 0x2A: // lha (Load HW Alg, PPC32 p445)
5041 DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
5042 val = load(Ity_I16, mkexpr(EA));
5043 putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
5044 break;
5045
5046 case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446)
5047 if (rA_addr == 0 || rA_addr == rD_addr) {
5048 vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n");
5049 return False;
5050 }
5051 DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
5052 val = load(Ity_I16, mkexpr(EA));
5053 putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
5054 putIReg( rA_addr, mkexpr(EA) );
5055 break;
5056
5057 case 0x28: // lhz (Load HW & Zero, PPC32 p450)
5058 DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
5059 val = load(Ity_I16, mkexpr(EA));
5060 putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
5061 break;
5062
5063 case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451)
5064 if (rA_addr == 0 || rA_addr == rD_addr) {
5065 vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n");
5066 return False;
5067 }
5068 DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
5069 val = load(Ity_I16, mkexpr(EA));
5070 putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
5071 putIReg( rA_addr, mkexpr(EA) );
5072 break;
5073
5074 case 0x20: // lwz (Load W & Zero, PPC32 p460)
5075 DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
5076 val = load(Ity_I32, mkexpr(EA));
5077 putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
5078 break;
5079
5080 case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461))
5081 if (rA_addr == 0 || rA_addr == rD_addr) {
5082 vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n");
5083 return False;
5084 }
5085 DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
5086 val = load(Ity_I32, mkexpr(EA));
5087 putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
5088 putIReg( rA_addr, mkexpr(EA) );
5089 break;
5090
5091 /* X Form */
5092 case 0x1F:
5093 if (b0 != 0) {
5094 vex_printf("dis_int_load(ppc)(Ox1F,b0)\n");
5095 return False;
5096 }
5097
5098 switch (opc2) {
5099 case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435)
5100 DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5101 if (rA_addr == 0 || rA_addr == rD_addr) {
5102 vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
5103 return False;
5104 }
5105 val = load(Ity_I8, mkexpr(EA));
5106 putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
5107 putIReg( rA_addr, mkexpr(EA) );
5108 break;
5109
5110 case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436)
5111 DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5112 val = load(Ity_I8, mkexpr(EA));
5113 putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
5114 break;
5115
5116 case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447)
5117 if (rA_addr == 0 || rA_addr == rD_addr) {
5118 vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n");
5119 return False;
5120 }
5121 DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5122 val = load(Ity_I16, mkexpr(EA));
5123 putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
5124 putIReg( rA_addr, mkexpr(EA) );
5125 break;
5126
5127 case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448)
5128 DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5129 val = load(Ity_I16, mkexpr(EA));
5130 putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
5131 break;
5132
5133 case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452)
5134 if (rA_addr == 0 || rA_addr == rD_addr) {
5135 vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n");
5136 return False;
5137 }
5138 DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5139 val = load(Ity_I16, mkexpr(EA));
5140 putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
5141 putIReg( rA_addr, mkexpr(EA) );
5142 break;
5143
5144 case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453)
5145 DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5146 val = load(Ity_I16, mkexpr(EA));
5147 putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
5148 break;
5149
5150 case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462)
5151 if (rA_addr == 0 || rA_addr == rD_addr) {
5152 vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
5153 return False;
5154 }
5155 DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5156 val = load(Ity_I32, mkexpr(EA));
5157 putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
5158 putIReg( rA_addr, mkexpr(EA) );
5159 break;
5160
5161 case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463)
5162 DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5163 val = load(Ity_I32, mkexpr(EA));
5164 putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
5165 break;
5166
5167
5168 /* 64bit Loads */
5169 case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475)
5170 if (rA_addr == 0 || rA_addr == rD_addr) {
5171 vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n");
5172 return False;
5173 }
5174 DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5175 putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
5176 putIReg( rA_addr, mkexpr(EA) );
5177 break;
5178
5179 case 0x015: // ldx (Load DWord, Indexed, PPC64 p476)
5180 DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5181 putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
5182 break;
5183
5184 case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501)
5185 if (rA_addr == 0 || rA_addr == rD_addr) {
5186 vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n");
5187 return False;
5188 }
5189 DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5190 putIReg( rD_addr,
5191 unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
5192 putIReg( rA_addr, mkexpr(EA) );
5193 break;
5194
5195 case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502)
5196 DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5197 putIReg( rD_addr,
5198 unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
5199 break;
5200
5201 default:
5202 vex_printf("dis_int_load(ppc)(opc2)\n");
5203 return False;
5204 }
5205 break;
5206
5207 /* DS Form - 64bit Loads. In each case EA will have been formed
5208 with the lowest 2 bits masked off the immediate offset. */
5209 case 0x3A:
5210 switch ((b1<<1) | b0) {
5211 case 0x0: // ld (Load DWord, PPC64 p472)
5212 DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
5213 putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
5214 break;
5215
5216 case 0x1: // ldu (Load DWord, Update, PPC64 p474)
5217 if (rA_addr == 0 || rA_addr == rD_addr) {
5218 vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n");
5219 return False;
5220 }
5221 DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
5222 putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
5223 putIReg( rA_addr, mkexpr(EA) );
5224 break;
5225
5226 case 0x2: // lwa (Load Word Alg, PPC64 p499)
5227 DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
5228 putIReg( rD_addr,
5229 unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
5230 break;
5231
5232 default:
5233 vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
5234 return False;
5235 }
5236 break;
5237
5238 case 0x38: {
5239 IRTemp high = newTemp(ty);
5240 IRTemp low = newTemp(ty);
5241 /* DQ Form - 128bit Loads. Lowest bits [1:0] are the PT field. */
5242 DIP("lq r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
5243 /* NOTE: there are some changes to XER[41:42] that have not been
5244 * implemented.
5245 */
5246 // trap if EA misaligned on 16 byte address
5247 if (mode64) {
5248 if (host_endness == VexEndnessBE) {
5249 assign(high, load(ty, mkexpr( EA ) ) );
5250 assign(low, load(ty, binop( Iop_Add64,
5251 mkexpr( EA ),
5252 mkU64( 8 ) ) ) );
5253 } else {
5254 assign(low, load(ty, mkexpr( EA ) ) );
5255 assign(high, load(ty, binop( Iop_Add64,
5256 mkexpr( EA ),
5257 mkU64( 8 ) ) ) );
5258 }
5259 } else {
5260 assign(high, load(ty, binop( Iop_Add32,
5261 mkexpr( EA ),
5262 mkU32( 4 ) ) ) );
5263 assign(low, load(ty, binop( Iop_Add32,
5264 mkexpr( EA ),
5265 mkU32( 12 ) ) ) );
5266 }
5267 gen_SIGBUS_if_misaligned( EA, 16 );
5268 putIReg( rD_addr, mkexpr( high) );
5269 putIReg( rD_addr+1, mkexpr( low) );
5270 break;
5271 }
5272 default:
5273 vex_printf("dis_int_load(ppc)(opc1)\n");
5274 return False;
5275 }
5276 return True;
5277 }
5278
5279
5280
5281 /*
5282 Integer Store Instructions
5283 */
dis_int_store(UInt theInstr,const VexAbiInfo * vbi)5284 static Bool dis_int_store ( UInt theInstr, const VexAbiInfo* vbi )
5285 {
5286 /* D-Form, X-Form, DS-Form */
5287 UChar opc1 = ifieldOPC(theInstr);
5288 UInt rS_addr = ifieldRegDS(theInstr);
5289 UInt rA_addr = ifieldRegA(theInstr);
5290 UInt uimm16 = ifieldUIMM16(theInstr);
5291 UInt rB_addr = ifieldRegB(theInstr);
5292 UInt opc2 = ifieldOPClo10(theInstr);
5293 UChar b1 = ifieldBIT1(theInstr);
5294 UChar b0 = ifieldBIT0(theInstr);
5295
5296 Int simm16 = extend_s_16to32(uimm16);
5297 IRType ty = mode64 ? Ity_I64 : Ity_I32;
5298 IRTemp rS = newTemp(ty);
5299 IRTemp rB = newTemp(ty);
5300 IRTemp EA = newTemp(ty);
5301
5302 assign( rB, getIReg(rB_addr) );
5303 assign( rS, getIReg(rS_addr) );
5304
5305 switch (opc1) {
5306 case 0x1F: // register offset
5307 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
5308 break;
5309 case 0x3E: // immediate offset: 64bit: std/stdu/stq: mask off
5310 // lowest 2 bits of immediate before forming EA
5311 simm16 = simm16 & 0xFFFFFFFC;
5312 default: // immediate offset
5313 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
5314 break;
5315 }
5316
5317 switch (opc1) {
5318 case 0x26: // stb (Store B, PPC32 p509)
5319 DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5320 store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
5321 break;
5322
5323 case 0x27: // stbu (Store B, Update, PPC32 p510)
5324 if (rA_addr == 0 ) {
5325 vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n");
5326 return False;
5327 }
5328 DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5329 putIReg( rA_addr, mkexpr(EA) );
5330 store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
5331 break;
5332
5333 case 0x2C: // sth (Store HW, PPC32 p522)
5334 DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5335 store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
5336 break;
5337
5338 case 0x2D: // sthu (Store HW, Update, PPC32 p524)
5339 if (rA_addr == 0) {
5340 vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n");
5341 return False;
5342 }
5343 DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5344 putIReg( rA_addr, mkexpr(EA) );
5345 store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
5346 break;
5347
5348 case 0x24: // stw (Store W, PPC32 p530)
5349 DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5350 store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
5351 break;
5352
5353 case 0x25: // stwu (Store W, Update, PPC32 p534)
5354 if (rA_addr == 0) {
5355 vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n");
5356 return False;
5357 }
5358 DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5359 putIReg( rA_addr, mkexpr(EA) );
5360 store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
5361 break;
5362
5363 /* X Form : all these use EA_indexed */
5364 case 0x1F:
5365 if (b0 != 0) {
5366 vex_printf("dis_int_store(ppc)(0x1F,b0)\n");
5367 return False;
5368 }
5369
5370 switch (opc2) {
5371 case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511)
5372 if (rA_addr == 0) {
5373 vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n");
5374 return False;
5375 }
5376 DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5377 putIReg( rA_addr, mkexpr(EA) );
5378 store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
5379 break;
5380
5381 case 0x0D7: // stbx (Store B Indexed, PPC32 p512)
5382 DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5383 store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
5384 break;
5385
5386 case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525)
5387 if (rA_addr == 0) {
5388 vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n");
5389 return False;
5390 }
5391 DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5392 putIReg( rA_addr, mkexpr(EA) );
5393 store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
5394 break;
5395
5396 case 0x197: // sthx (Store HW Indexed, PPC32 p526)
5397 DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5398 store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
5399 break;
5400
5401 case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535)
5402 if (rA_addr == 0) {
5403 vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n");
5404 return False;
5405 }
5406 DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5407 putIReg( rA_addr, mkexpr(EA) );
5408 store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
5409 break;
5410
5411 case 0x097: // stwx (Store W Indexed, PPC32 p536)
5412 DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5413 store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
5414 break;
5415
5416
5417 /* 64bit Stores */
5418 case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584)
5419 if (rA_addr == 0) {
5420 vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n");
5421 return False;
5422 }
5423 DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5424 putIReg( rA_addr, mkexpr(EA) );
5425 store( mkexpr(EA), mkexpr(rS) );
5426 break;
5427
5428 case 0x095: // stdx (Store DWord Indexed, PPC64 p585)
5429 DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5430 store( mkexpr(EA), mkexpr(rS) );
5431 break;
5432
5433 default:
5434 vex_printf("dis_int_store(ppc)(opc2)\n");
5435 return False;
5436 }
5437 break;
5438
5439 /* DS Form - 64bit Stores. In each case EA will have been formed
5440 with the lowest 2 bits masked off the immediate offset. */
5441 case 0x3E:
5442 switch ((b1<<1) | b0) {
5443 case 0x0: // std (Store DWord, PPC64 p580)
5444 if (!mode64)
5445 return False;
5446
5447 DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5448 store( mkexpr(EA), mkexpr(rS) );
5449 break;
5450
5451 case 0x1: // stdu (Store DWord, Update, PPC64 p583)
5452 if (!mode64)
5453 return False;
5454
5455 DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5456 putIReg( rA_addr, mkexpr(EA) );
5457 store( mkexpr(EA), mkexpr(rS) );
5458 break;
5459
5460 case 0x2: { // stq (Store QuadWord, Update, PPC64 p583)
5461 IRTemp EA_hi = newTemp(ty);
5462 IRTemp EA_lo = newTemp(ty);
5463 DIP("stq r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5464
5465 if (mode64) {
5466 if (host_endness == VexEndnessBE) {
5467
5468 /* upper 64-bits */
5469 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) );
5470
5471 /* lower 64-bits */
5472 assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+8 ) );
5473 } else {
5474 /* upper 64-bits */
5475 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+8 ) );
5476
5477 /* lower 64-bits */
5478 assign( EA_lo, ea_rAor0_simm( rA_addr, simm16 ) );
5479 }
5480 } else {
5481 /* upper half of upper 64-bits */
5482 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+4 ) );
5483
5484 /* lower half of upper 64-bits */
5485 assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+12 ) );
5486 }
5487 store( mkexpr(EA_hi), mkexpr(rS) );
5488 store( mkexpr(EA_lo), getIReg( rS_addr+1 ) );
5489 break;
5490 }
5491 default:
5492 vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
5493 return False;
5494 }
5495 break;
5496
5497 default:
5498 vex_printf("dis_int_store(ppc)(opc1)\n");
5499 return False;
5500 }
5501 return True;
5502 }
5503
5504
5505
5506 /*
5507 Integer Load/Store Multiple Instructions
5508 */
dis_int_ldst_mult(UInt theInstr)5509 static Bool dis_int_ldst_mult ( UInt theInstr )
5510 {
5511 /* D-Form */
5512 UChar opc1 = ifieldOPC(theInstr);
5513 UChar rD_addr = ifieldRegDS(theInstr);
5514 UChar rS_addr = rD_addr;
5515 UChar rA_addr = ifieldRegA(theInstr);
5516 UInt uimm16 = ifieldUIMM16(theInstr);
5517
5518 Int simm16 = extend_s_16to32(uimm16);
5519 IRType ty = mode64 ? Ity_I64 : Ity_I32;
5520 IROp mkAdd = mode64 ? Iop_Add64 : Iop_Add32;
5521 IRTemp EA = newTemp(ty);
5522 UInt r = 0;
5523 UInt ea_off = 0;
5524 IRExpr* irx_addr;
5525
5526 assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
5527
5528 switch (opc1) {
5529 case 0x2E: // lmw (Load Multiple Word, PPC32 p454)
5530 if (rA_addr >= rD_addr) {
5531 vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n");
5532 return False;
5533 }
5534 DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
5535 for (r = rD_addr; r <= 31; r++) {
5536 irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off));
5537 putIReg( r, mkWidenFrom32(ty, load(Ity_I32, irx_addr ),
5538 False) );
5539 ea_off += 4;
5540 }
5541 break;
5542
5543 case 0x2F: // stmw (Store Multiple Word, PPC32 p527)
5544 DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5545 for (r = rS_addr; r <= 31; r++) {
5546 irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off));
5547 store( irx_addr, mkNarrowTo32(ty, getIReg(r)) );
5548 ea_off += 4;
5549 }
5550 break;
5551
5552 default:
5553 vex_printf("dis_int_ldst_mult(ppc)(opc1)\n");
5554 return False;
5555 }
5556 return True;
5557 }
5558
5559
5560
5561 /*
5562 Integer Load/Store String Instructions
5563 */
5564 static
generate_lsw_sequence(IRTemp tNBytes,IRTemp EA,Int rD,Int maxBytes)5565 void generate_lsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32
5566 IRTemp EA, // EA
5567 Int rD, // first dst register
5568 Int maxBytes ) // 32 or 128
5569 {
5570 Int i, shift = 24;
5571 IRExpr* e_nbytes = mkexpr(tNBytes);
5572 IRExpr* e_EA = mkexpr(EA);
5573 IRType ty = mode64 ? Ity_I64 : Ity_I32;
5574
5575 vassert(rD >= 0 && rD < 32);
5576 rD--; if (rD < 0) rD = 31;
5577
5578 for (i = 0; i < maxBytes; i++) {
5579 /* if (nBytes < (i+1)) goto NIA; */
5580 stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
5581 Ijk_Boring,
5582 mkSzConst( ty, nextInsnAddr()), OFFB_CIA ));
5583 /* when crossing into a new dest register, set it to zero. */
5584 if ((i % 4) == 0) {
5585 rD++; if (rD == 32) rD = 0;
5586 putIReg(rD, mkSzImm(ty, 0));
5587 shift = 24;
5588 }
5589 /* rD |= (8Uto32(*(EA+i))) << shift */
5590 vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
5591 putIReg(
5592 rD,
5593 mkWidenFrom32(
5594 ty,
5595 binop(
5596 Iop_Or32,
5597 mkNarrowTo32(ty, getIReg(rD)),
5598 binop(
5599 Iop_Shl32,
5600 unop(
5601 Iop_8Uto32,
5602 load( Ity_I8,
5603 binop( mkSzOp(ty,Iop_Add8),
5604 e_EA, mkSzImm(ty,i)))
5605 ),
5606 mkU8(toUChar(shift))
5607 )
5608 ),
5609 /*Signed*/False
5610 )
5611 );
5612 shift -= 8;
5613 }
5614 }
5615
5616 static
generate_stsw_sequence(IRTemp tNBytes,IRTemp EA,Int rS,Int maxBytes)5617 void generate_stsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32
5618 IRTemp EA, // EA
5619 Int rS, // first src register
5620 Int maxBytes ) // 32 or 128
5621 {
5622 Int i, shift = 24;
5623 IRExpr* e_nbytes = mkexpr(tNBytes);
5624 IRExpr* e_EA = mkexpr(EA);
5625 IRType ty = mode64 ? Ity_I64 : Ity_I32;
5626
5627 vassert(rS >= 0 && rS < 32);
5628 rS--; if (rS < 0) rS = 31;
5629
5630 for (i = 0; i < maxBytes; i++) {
5631 /* if (nBytes < (i+1)) goto NIA; */
5632 stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
5633 Ijk_Boring,
5634 mkSzConst( ty, nextInsnAddr() ), OFFB_CIA ));
5635 /* check for crossing into a new src register. */
5636 if ((i % 4) == 0) {
5637 rS++; if (rS == 32) rS = 0;
5638 shift = 24;
5639 }
5640 /* *(EA+i) = 32to8(rS >> shift) */
5641 vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
5642 store(
5643 binop( mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)),
5644 unop( Iop_32to8,
5645 binop( Iop_Shr32,
5646 mkNarrowTo32( ty, getIReg(rS) ),
5647 mkU8( toUChar(shift) )))
5648 );
5649 shift -= 8;
5650 }
5651 }
5652
dis_int_ldst_str(UInt theInstr,Bool * stopHere)5653 static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere )
5654 {
5655 /* X-Form */
5656 UChar opc1 = ifieldOPC(theInstr);
5657 UChar rD_addr = ifieldRegDS(theInstr);
5658 UChar rS_addr = rD_addr;
5659 UChar rA_addr = ifieldRegA(theInstr);
5660 UChar rB_addr = ifieldRegB(theInstr);
5661 UChar NumBytes = rB_addr;
5662 UInt opc2 = ifieldOPClo10(theInstr);
5663 UChar b0 = ifieldBIT0(theInstr);
5664
5665 IRType ty = mode64 ? Ity_I64 : Ity_I32;
5666 IRTemp t_EA = newTemp(ty);
5667 IRTemp t_nbytes = IRTemp_INVALID;
5668
5669 *stopHere = False;
5670
5671 if (opc1 != 0x1F || b0 != 0) {
5672 vex_printf("dis_int_ldst_str(ppc)(opc1)\n");
5673 return False;
5674 }
5675
5676 switch (opc2) {
5677 case 0x255: // lswi (Load String Word Immediate, PPC32 p455)
5678 /* NB: does not reject the case where RA is in the range of
5679 registers to be loaded. It should. */
5680 DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes);
5681 assign( t_EA, ea_rAor0(rA_addr) );
5682 if (NumBytes == 8 && !mode64) {
5683 /* Special case hack */
5684 /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */
5685 putIReg( rD_addr,
5686 load(Ity_I32, mkexpr(t_EA)) );
5687 putIReg( (rD_addr+1) % 32,
5688 load(Ity_I32,
5689 binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) );
5690 } else {
5691 t_nbytes = newTemp(Ity_I32);
5692 assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
5693 generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
5694 *stopHere = True;
5695 }
5696 return True;
5697
5698 case 0x215: // lswx (Load String Word Indexed, PPC32 p456)
5699 /* NB: does not reject the case where RA is in the range of
5700 registers to be loaded. It should. Although considering
5701 that that can only be detected at run time, it's not easy to
5702 do so. */
5703 if (rD_addr == rA_addr || rD_addr == rB_addr)
5704 return False;
5705 if (rD_addr == 0 && rA_addr == 0)
5706 return False;
5707 DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5708 t_nbytes = newTemp(Ity_I32);
5709 assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
5710 assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
5711 generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 );
5712 *stopHere = True;
5713 return True;
5714
5715 case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528)
5716 DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes);
5717 assign( t_EA, ea_rAor0(rA_addr) );
5718 if (NumBytes == 8 && !mode64) {
5719 /* Special case hack */
5720 /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */
5721 store( mkexpr(t_EA),
5722 getIReg(rD_addr) );
5723 store( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)),
5724 getIReg((rD_addr+1) % 32) );
5725 } else {
5726 t_nbytes = newTemp(Ity_I32);
5727 assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
5728 generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
5729 *stopHere = True;
5730 }
5731 return True;
5732
5733 case 0x295: // stswx (Store String Word Indexed, PPC32 p529)
5734 DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5735 t_nbytes = newTemp(Ity_I32);
5736 assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
5737 assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
5738 generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 );
5739 *stopHere = True;
5740 return True;
5741
5742 default:
5743 vex_printf("dis_int_ldst_str(ppc)(opc2)\n");
5744 return False;
5745 }
5746 return True;
5747 }
5748
5749
5750 /* ------------------------------------------------------------------
5751 Integer Branch Instructions
5752 ------------------------------------------------------------------ */
5753
5754 /*
5755 Branch helper function
5756 ok = BO[2] | ((CTR[0] != 0) ^ BO[1])
5757 Returns an I32 which is 0x00000000 if the ctr condition failed
5758 and 0xFFFFFFFF otherwise.
5759 */
branch_ctr_ok(UInt BO)5760 static IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO )
5761 {
5762 IRType ty = mode64 ? Ity_I64 : Ity_I32;
5763 IRTemp ok = newTemp(Ity_I32);
5764
5765 if ((BO >> 2) & 1) { // independent of ctr
5766 assign( ok, mkU32(0xFFFFFFFF) );
5767 } else {
5768 if ((BO >> 1) & 1) { // ctr == 0 ?
5769 assign( ok, unop( Iop_1Sto32,
5770 binop( mkSzOp(ty, Iop_CmpEQ8),
5771 getGST( PPC_GST_CTR ),
5772 mkSzImm(ty,0))) );
5773 } else { // ctr != 0 ?
5774 assign( ok, unop( Iop_1Sto32,
5775 binop( mkSzOp(ty, Iop_CmpNE8),
5776 getGST( PPC_GST_CTR ),
5777 mkSzImm(ty,0))) );
5778 }
5779 }
5780 return mkexpr(ok);
5781 }
5782
5783
5784 /*
5785 Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3])
5786 Returns an I32 which is either 0 if the condition failed or
5787 some arbitrary nonzero value otherwise. */
5788
branch_cond_ok(UInt BO,UInt BI)5789 static IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI )
5790 {
5791 Int where;
5792 IRTemp res = newTemp(Ity_I32);
5793 IRTemp cr_bi = newTemp(Ity_I32);
5794
5795 if ((BO >> 4) & 1) {
5796 assign( res, mkU32(1) );
5797 } else {
5798 // ok = (CR[BI] == BO[3]) Note, the following relies on
5799 // getCRbit_anywhere returning a value which
5800 // is either zero or has exactly 1 bit set.
5801 assign( cr_bi, getCRbit_anywhere( BI, &where ) );
5802
5803 if ((BO >> 3) & 1) {
5804 /* We can use cr_bi as-is. */
5805 assign( res, mkexpr(cr_bi) );
5806 } else {
5807 /* We have to invert the sense of the information held in
5808 cr_bi. For that we need to know which bit
5809 getCRbit_anywhere regards as significant. */
5810 assign( res, binop(Iop_Xor32, mkexpr(cr_bi),
5811 mkU32(1<<where)) );
5812 }
5813 }
5814 return mkexpr(res);
5815 }
5816
5817
5818 /*
5819 Integer Branch Instructions
5820 */
dis_branch(UInt theInstr,const VexAbiInfo * vbi,DisResult * dres,Bool (* resteerOkFn)(void *,Addr),void * callback_opaque)5821 static Bool dis_branch ( UInt theInstr,
5822 const VexAbiInfo* vbi,
5823 /*OUT*/DisResult* dres,
5824 Bool (*resteerOkFn)(void*,Addr),
5825 void* callback_opaque )
5826 {
5827 UChar opc1 = ifieldOPC(theInstr);
5828 UChar BO = ifieldRegDS(theInstr);
5829 UChar BI = ifieldRegA(theInstr);
5830 UInt BD_u16 = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */
5831 UChar b11to15 = ifieldRegB(theInstr);
5832 UInt opc2 = ifieldOPClo10(theInstr);
5833 UInt LI_u26 = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */
5834 UChar flag_AA = ifieldBIT1(theInstr);
5835 UChar flag_LK = ifieldBIT0(theInstr);
5836
5837 IRType ty = mode64 ? Ity_I64 : Ity_I32;
5838 Addr64 tgt = 0;
5839 UInt BD = extend_s_16to32(BD_u16);
5840 IRTemp do_branch = newTemp(Ity_I32);
5841 IRTemp ctr_ok = newTemp(Ity_I32);
5842 IRTemp cond_ok = newTemp(Ity_I32);
5843 IRExpr* e_nia = mkSzImm(ty, nextInsnAddr());
5844 IRConst* c_nia = mkSzConst(ty, nextInsnAddr());
5845 IRTemp lr_old = newTemp(ty);
5846
5847 /* Hack to pass through code that just wants to read the PC */
5848 if (theInstr == 0x429F0005) {
5849 DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI);
5850 putGST( PPC_GST_LR, e_nia );
5851 return True;
5852 }
5853
5854 /* The default what-next. Individual cases can override it. */
5855 dres->whatNext = Dis_StopHere;
5856 vassert(dres->jk_StopHere == Ijk_INVALID);
5857
5858 switch (opc1) {
5859 case 0x12: // b (Branch, PPC32 p360)
5860 if (flag_AA) {
5861 tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) );
5862 } else {
5863 tgt = mkSzAddr( ty, guest_CIA_curr_instr +
5864 (Long)extend_s_26to64(LI_u26) );
5865 }
5866 if (mode64) {
5867 DIP("b%s%s 0x%llx\n",
5868 flag_LK ? "l" : "", flag_AA ? "a" : "", tgt);
5869 } else {
5870 DIP("b%s%s 0x%x\n",
5871 flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt);
5872 }
5873
5874 if (flag_LK) {
5875 putGST( PPC_GST_LR, e_nia );
5876 if (vbi->guest_ppc_zap_RZ_at_bl
5877 && vbi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) {
5878 IRTemp t_tgt = newTemp(ty);
5879 assign(t_tgt, mode64 ? mkU64(tgt) : mkU32(tgt) );
5880 make_redzone_AbiHint( vbi, t_tgt,
5881 "branch-and-link (unconditional call)" );
5882 }
5883 }
5884
5885 if (resteerOkFn( callback_opaque, tgt )) {
5886 dres->whatNext = Dis_ResteerU;
5887 dres->continueAt = tgt;
5888 } else {
5889 dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring; ;
5890 putGST( PPC_GST_CIA, mkSzImm(ty, tgt) );
5891 }
5892 break;
5893
5894 case 0x10: // bc (Branch Conditional, PPC32 p361)
5895 DIP("bc%s%s 0x%x, 0x%x, 0x%x\n",
5896 flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD);
5897
5898 if (!(BO & 0x4)) {
5899 putGST( PPC_GST_CTR,
5900 binop(mkSzOp(ty, Iop_Sub8),
5901 getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
5902 }
5903
5904 /* This is a bit subtle. ctr_ok is either all 0s or all 1s.
5905 cond_ok is either zero or nonzero, since that's the cheapest
5906 way to compute it. Anding them together gives a value which
5907 is either zero or non zero and so that's what we must test
5908 for in the IRStmt_Exit. */
5909 assign( ctr_ok, branch_ctr_ok( BO ) );
5910 assign( cond_ok, branch_cond_ok( BO, BI ) );
5911 assign( do_branch,
5912 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
5913
5914 if (flag_AA) {
5915 tgt = mkSzAddr(ty, extend_s_16to64(BD_u16));
5916 } else {
5917 tgt = mkSzAddr(ty, guest_CIA_curr_instr +
5918 (Long)extend_s_16to64(BD_u16));
5919 }
5920 if (flag_LK)
5921 putGST( PPC_GST_LR, e_nia );
5922
5923 stmt( IRStmt_Exit(
5924 binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)),
5925 flag_LK ? Ijk_Call : Ijk_Boring,
5926 mkSzConst(ty, tgt), OFFB_CIA ) );
5927
5928 dres->jk_StopHere = Ijk_Boring;
5929 putGST( PPC_GST_CIA, e_nia );
5930 break;
5931
5932 case 0x13:
5933 /* For bclr and bcctr, it appears that the lowest two bits of
5934 b11to15 are a branch hint, and so we only need to ensure it's
5935 of the form 000XX. */
5936 if ((b11to15 & ~3) != 0) {
5937 vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", b11to15);
5938 return False;
5939 }
5940
5941 switch (opc2) {
5942 case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363)
5943 if ((BO & 0x4) == 0) { // "decr and test CTR" option invalid
5944 vex_printf("dis_int_branch(ppc)(bcctr,BO)\n");
5945 return False;
5946 }
5947 DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
5948
5949 assign( cond_ok, branch_cond_ok( BO, BI ) );
5950
5951 /* FIXME: this is confusing. lr_old holds the old value
5952 of ctr, not lr :-) */
5953 assign( lr_old, addr_align( getGST( PPC_GST_CTR ), 4 ));
5954
5955 if (flag_LK)
5956 putGST( PPC_GST_LR, e_nia );
5957
5958 stmt( IRStmt_Exit(
5959 binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)),
5960 Ijk_Boring,
5961 c_nia, OFFB_CIA ));
5962
5963 if (flag_LK && vbi->guest_ppc_zap_RZ_at_bl) {
5964 make_redzone_AbiHint( vbi, lr_old,
5965 "b-ctr-l (indirect call)" );
5966 }
5967
5968 dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring;;
5969 putGST( PPC_GST_CIA, mkexpr(lr_old) );
5970 break;
5971
5972 case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365)
5973 Bool vanilla_return = False;
5974 if ((BO & 0x14 /* 1z1zz */) == 0x14 && flag_LK == 0) {
5975 DIP("blr\n");
5976 vanilla_return = True;
5977 } else {
5978 DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
5979 }
5980
5981 if (!(BO & 0x4)) {
5982 putGST( PPC_GST_CTR,
5983 binop(mkSzOp(ty, Iop_Sub8),
5984 getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
5985 }
5986
5987 /* See comments above for 'bc' about this */
5988 assign( ctr_ok, branch_ctr_ok( BO ) );
5989 assign( cond_ok, branch_cond_ok( BO, BI ) );
5990 assign( do_branch,
5991 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
5992
5993 assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 ));
5994
5995 if (flag_LK)
5996 putGST( PPC_GST_LR, e_nia );
5997
5998 stmt( IRStmt_Exit(
5999 binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)),
6000 Ijk_Boring,
6001 c_nia, OFFB_CIA ));
6002
6003 if (vanilla_return && vbi->guest_ppc_zap_RZ_at_blr) {
6004 make_redzone_AbiHint( vbi, lr_old,
6005 "branch-to-lr (unconditional return)" );
6006 }
6007
6008 /* blrl is pretty strange; it's like a return that sets the
6009 return address of its caller to the insn following this
6010 one. Mark it as a return. */
6011 dres->jk_StopHere = Ijk_Ret; /* was flag_LK ? Ijk_Call : Ijk_Ret; */
6012 putGST( PPC_GST_CIA, mkexpr(lr_old) );
6013 break;
6014 }
6015 default:
6016 vex_printf("dis_int_branch(ppc)(opc2)\n");
6017 return False;
6018 }
6019 break;
6020
6021 default:
6022 vex_printf("dis_int_branch(ppc)(opc1)\n");
6023 return False;
6024 }
6025
6026 return True;
6027 }
6028
6029
6030
6031 /*
6032 Condition Register Logical Instructions
6033 */
dis_cond_logic(UInt theInstr)6034 static Bool dis_cond_logic ( UInt theInstr )
6035 {
6036 /* XL-Form */
6037 UChar opc1 = ifieldOPC(theInstr);
6038 UChar crbD_addr = ifieldRegDS(theInstr);
6039 UChar crfD_addr = toUChar( IFIELD(theInstr, 23, 3) );
6040 UChar crbA_addr = ifieldRegA(theInstr);
6041 UChar crfS_addr = toUChar( IFIELD(theInstr, 18, 3) );
6042 UChar crbB_addr = ifieldRegB(theInstr);
6043 UInt opc2 = ifieldOPClo10(theInstr);
6044 UChar b0 = ifieldBIT0(theInstr);
6045
6046 IRTemp crbD = newTemp(Ity_I32);
6047 IRTemp crbA = newTemp(Ity_I32);
6048 IRTemp crbB = newTemp(Ity_I32);
6049
6050 if (opc1 != 19 || b0 != 0) {
6051 vex_printf("dis_cond_logic(ppc)(opc1)\n");
6052 return False;
6053 }
6054
6055 if (opc2 == 0) { // mcrf (Move Cond Reg Field, PPC32 p464)
6056 if (((crbD_addr & 0x3) != 0) ||
6057 ((crbA_addr & 0x3) != 0) || (crbB_addr != 0)) {
6058 vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n");
6059 return False;
6060 }
6061 DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr);
6062 putCR0( crfD_addr, getCR0( crfS_addr) );
6063 putCR321( crfD_addr, getCR321(crfS_addr) );
6064 } else {
6065 assign( crbA, getCRbit(crbA_addr) );
6066 if (crbA_addr == crbB_addr)
6067 crbB = crbA;
6068 else
6069 assign( crbB, getCRbit(crbB_addr) );
6070
6071 switch (opc2) {
6072 case 0x101: // crand (Cond Reg AND, PPC32 p372)
6073 DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
6074 assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) );
6075 break;
6076 case 0x081: // crandc (Cond Reg AND w. Complement, PPC32 p373)
6077 DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
6078 assign( crbD, binop(Iop_And32,
6079 mkexpr(crbA),
6080 unop(Iop_Not32, mkexpr(crbB))) );
6081 break;
6082 case 0x121: // creqv (Cond Reg Equivalent, PPC32 p374)
6083 DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
6084 assign( crbD, unop(Iop_Not32,
6085 binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) );
6086 break;
6087 case 0x0E1: // crnand (Cond Reg NAND, PPC32 p375)
6088 DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
6089 assign( crbD, unop(Iop_Not32,
6090 binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) );
6091 break;
6092 case 0x021: // crnor (Cond Reg NOR, PPC32 p376)
6093 DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
6094 assign( crbD, unop(Iop_Not32,
6095 binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) );
6096 break;
6097 case 0x1C1: // cror (Cond Reg OR, PPC32 p377)
6098 DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
6099 assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) );
6100 break;
6101 case 0x1A1: // crorc (Cond Reg OR w. Complement, PPC32 p378)
6102 DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
6103 assign( crbD, binop(Iop_Or32,
6104 mkexpr(crbA),
6105 unop(Iop_Not32, mkexpr(crbB))) );
6106 break;
6107 case 0x0C1: // crxor (Cond Reg XOR, PPC32 p379)
6108 DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
6109 assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) );
6110 break;
6111 default:
6112 vex_printf("dis_cond_logic(ppc)(opc2)\n");
6113 return False;
6114 }
6115
6116 putCRbit( crbD_addr, mkexpr(crbD) );
6117 }
6118 return True;
6119 }
6120
6121
6122 /*
6123 Trap instructions
6124 */
6125
6126 /* Do the code generation for a trap. Returned Bool is true iff
6127 this is an unconditional trap. If the two arg IRExpr*s are
6128 Ity_I32s then the comparison is 32-bit. If they are Ity_I64s
6129 then they are 64-bit, and we must be disassembling 64-bit
6130 instructions. */
do_trap(UChar TO,IRExpr * argL0,IRExpr * argR0,Addr64 cia)6131 static Bool do_trap ( UChar TO,
6132 IRExpr* argL0, IRExpr* argR0, Addr64 cia )
6133 {
6134 IRTemp argL, argR;
6135 IRExpr *argLe, *argRe, *cond, *tmp;
6136
6137 Bool is32bit = typeOfIRExpr(irsb->tyenv, argL0 ) == Ity_I32;
6138
6139 IROp opAND = is32bit ? Iop_And32 : Iop_And64;
6140 IROp opOR = is32bit ? Iop_Or32 : Iop_Or64;
6141 IROp opCMPORDS = is32bit ? Iop_CmpORD32S : Iop_CmpORD64S;
6142 IROp opCMPORDU = is32bit ? Iop_CmpORD32U : Iop_CmpORD64U;
6143 IROp opCMPNE = is32bit ? Iop_CmpNE32 : Iop_CmpNE64;
6144 IROp opCMPEQ = is32bit ? Iop_CmpEQ32 : Iop_CmpEQ64;
6145 IRExpr* const0 = is32bit ? mkU32(0) : mkU64(0);
6146 IRExpr* const2 = is32bit ? mkU32(2) : mkU64(2);
6147 IRExpr* const4 = is32bit ? mkU32(4) : mkU64(4);
6148 IRExpr* const8 = is32bit ? mkU32(8) : mkU64(8);
6149
6150 const UChar b11100 = 0x1C;
6151 const UChar b00111 = 0x07;
6152
6153 if (is32bit) {
6154 vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 );
6155 vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 );
6156 } else {
6157 vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 );
6158 vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 );
6159 vassert( mode64 );
6160 }
6161
6162 if ((TO & b11100) == b11100 || (TO & b00111) == b00111) {
6163 /* Unconditional trap. Just do the exit without
6164 testing the arguments. */
6165 stmt( IRStmt_Exit(
6166 binop(opCMPEQ, const0, const0),
6167 Ijk_SigTRAP,
6168 mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia),
6169 OFFB_CIA
6170 ));
6171 return True; /* unconditional trap */
6172 }
6173
6174 if (is32bit) {
6175 argL = newTemp(Ity_I32);
6176 argR = newTemp(Ity_I32);
6177 } else {
6178 argL = newTemp(Ity_I64);
6179 argR = newTemp(Ity_I64);
6180 }
6181
6182 assign( argL, argL0 );
6183 assign( argR, argR0 );
6184
6185 argLe = mkexpr(argL);
6186 argRe = mkexpr(argR);
6187
6188 cond = const0;
6189 if (TO & 16) { // L <s R
6190 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const8);
6191 cond = binop(opOR, tmp, cond);
6192 }
6193 if (TO & 8) { // L >s R
6194 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4);
6195 cond = binop(opOR, tmp, cond);
6196 }
6197 if (TO & 4) { // L == R
6198 tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2);
6199 cond = binop(opOR, tmp, cond);
6200 }
6201 if (TO & 2) { // L <u R
6202 tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const8);
6203 cond = binop(opOR, tmp, cond);
6204 }
6205 if (TO & 1) { // L >u R
6206 tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4);
6207 cond = binop(opOR, tmp, cond);
6208 }
6209 stmt( IRStmt_Exit(
6210 binop(opCMPNE, cond, const0),
6211 Ijk_SigTRAP,
6212 mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia),
6213 OFFB_CIA
6214 ));
6215 return False; /* not an unconditional trap */
6216 }
6217
dis_trapi(UInt theInstr,DisResult * dres)6218 static Bool dis_trapi ( UInt theInstr,
6219 /*OUT*/DisResult* dres )
6220 {
6221 /* D-Form */
6222 UChar opc1 = ifieldOPC(theInstr);
6223 UChar TO = ifieldRegDS(theInstr);
6224 UChar rA_addr = ifieldRegA(theInstr);
6225 UInt uimm16 = ifieldUIMM16(theInstr);
6226 ULong simm16 = extend_s_16to64(uimm16);
6227 Addr64 cia = guest_CIA_curr_instr;
6228 IRType ty = mode64 ? Ity_I64 : Ity_I32;
6229 Bool uncond = False;
6230
6231 switch (opc1) {
6232 case 0x03: // twi (Trap Word Immediate, PPC32 p548)
6233 uncond = do_trap( TO,
6234 mode64 ? unop(Iop_64to32, getIReg(rA_addr))
6235 : getIReg(rA_addr),
6236 mkU32( (UInt)simm16 ),
6237 cia );
6238 if (TO == 4) {
6239 DIP("tweqi r%u,%d\n", rA_addr, (Int)simm16);
6240 } else {
6241 DIP("tw%di r%u,%d\n", TO, rA_addr, (Int)simm16);
6242 }
6243 break;
6244 case 0x02: // tdi
6245 if (!mode64)
6246 return False;
6247 uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia );
6248 if (TO == 4) {
6249 DIP("tdeqi r%u,%d\n", rA_addr, (Int)simm16);
6250 } else {
6251 DIP("td%di r%u,%d\n", TO, rA_addr, (Int)simm16);
6252 }
6253 break;
6254 default:
6255 return False;
6256 }
6257
6258 if (uncond) {
6259 /* If the trap shows signs of being unconditional, don't
6260 continue decoding past it. */
6261 putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
6262 dres->jk_StopHere = Ijk_Boring;
6263 dres->whatNext = Dis_StopHere;
6264 }
6265
6266 return True;
6267 }
6268
dis_trap(UInt theInstr,DisResult * dres)6269 static Bool dis_trap ( UInt theInstr,
6270 /*OUT*/DisResult* dres )
6271 {
6272 /* X-Form */
6273 UInt opc2 = ifieldOPClo10(theInstr);
6274 UChar TO = ifieldRegDS(theInstr);
6275 UChar rA_addr = ifieldRegA(theInstr);
6276 UChar rB_addr = ifieldRegB(theInstr);
6277 Addr64 cia = guest_CIA_curr_instr;
6278 IRType ty = mode64 ? Ity_I64 : Ity_I32;
6279 Bool uncond = False;
6280
6281 if (ifieldBIT0(theInstr) != 0)
6282 return False;
6283
6284 switch (opc2) {
6285 case 0x004: // tw (Trap Word, PPC64 p540)
6286 uncond = do_trap( TO,
6287 mode64 ? unop(Iop_64to32, getIReg(rA_addr))
6288 : getIReg(rA_addr),
6289 mode64 ? unop(Iop_64to32, getIReg(rB_addr))
6290 : getIReg(rB_addr),
6291 cia );
6292 if (TO == 4) {
6293 DIP("tweq r%u,r%u\n", rA_addr, rB_addr);
6294 } else {
6295 DIP("tw%d r%u,r%u\n", TO, rA_addr, rB_addr);
6296 }
6297 break;
6298 case 0x044: // td (Trap Doubleword, PPC64 p534)
6299 if (!mode64)
6300 return False;
6301 uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia );
6302 if (TO == 4) {
6303 DIP("tdeq r%u,r%u\n", rA_addr, rB_addr);
6304 } else {
6305 DIP("td%d r%u,r%u\n", TO, rA_addr, rB_addr);
6306 }
6307 break;
6308 default:
6309 return False;
6310 }
6311
6312 if (uncond) {
6313 /* If the trap shows signs of being unconditional, don't
6314 continue decoding past it. */
6315 putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
6316 dres->jk_StopHere = Ijk_Boring;
6317 dres->whatNext = Dis_StopHere;
6318 }
6319
6320 return True;
6321 }
6322
6323
6324 /*
6325 System Linkage Instructions
6326 */
dis_syslink(UInt theInstr,const VexAbiInfo * abiinfo,DisResult * dres)6327 static Bool dis_syslink ( UInt theInstr,
6328 const VexAbiInfo* abiinfo, DisResult* dres )
6329 {
6330 IRType ty = mode64 ? Ity_I64 : Ity_I32;
6331
6332 if (theInstr != 0x44000002) {
6333 vex_printf("dis_syslink(ppc)(theInstr)\n");
6334 return False;
6335 }
6336
6337 // sc (System Call, PPC32 p504)
6338 DIP("sc\n");
6339
6340 /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on Darwin
6341 Valgrind can back the guest up to this instruction if it needs
6342 to restart the syscall. */
6343 putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) );
6344
6345 /* It's important that all ArchRegs carry their up-to-date value
6346 at this point. So we declare an end-of-block here, which
6347 forces any TempRegs caching ArchRegs to be flushed. */
6348 putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
6349
6350 dres->whatNext = Dis_StopHere;
6351 dres->jk_StopHere = Ijk_Sys_syscall;
6352 return True;
6353 }
6354
6355
6356 /*
6357 Memory Synchronization Instructions
6358
6359 Note on Reservations:
6360 We rely on the assumption that V will in fact only allow one thread at
6361 once to run. In effect, a thread can make a reservation, but we don't
6362 check any stores it does. Instead, the reservation is cancelled when
6363 the scheduler switches to another thread (run_thread_for_a_while()).
6364 */
dis_memsync(UInt theInstr)6365 static Bool dis_memsync ( UInt theInstr )
6366 {
6367 /* X-Form, XL-Form */
6368 UChar opc1 = ifieldOPC(theInstr);
6369 UInt b11to25 = IFIELD(theInstr, 11, 15);
6370 UChar flag_L = ifieldRegDS(theInstr);
6371 UInt b11to20 = IFIELD(theInstr, 11, 10);
6372 UInt M0 = IFIELD(theInstr, 11, 5);
6373 UChar rD_addr = ifieldRegDS(theInstr);
6374 UChar rS_addr = rD_addr;
6375 UChar rA_addr = ifieldRegA(theInstr);
6376 UChar rB_addr = ifieldRegB(theInstr);
6377 UInt opc2 = ifieldOPClo10(theInstr);
6378 UChar b0 = ifieldBIT0(theInstr);
6379
6380 IRType ty = mode64 ? Ity_I64 : Ity_I32;
6381 IRTemp EA = newTemp(ty);
6382
6383 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
6384
6385 switch (opc1) {
6386 /* XL-Form */
6387 case 0x13: // isync (Instruction Synchronize, PPC32 p432)
6388 if (opc2 != 0x096) {
6389 vex_printf("dis_memsync(ppc)(0x13,opc2)\n");
6390 return False;
6391 }
6392 if (b11to25 != 0 || b0 != 0) {
6393 vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n");
6394 return False;
6395 }
6396 DIP("isync\n");
6397 stmt( IRStmt_MBE(Imbe_Fence) );
6398 break;
6399
6400 /* X-Form */
6401 case 0x1F:
6402 switch (opc2) {
6403 case 0x356: // eieio or mbar (Enforce In-Order Exec of I/O, PPC32 p394)
6404 if (M0 == 0) {
6405 if (b11to20 != 0 || b0 != 0) {
6406 vex_printf("dis_memsync(ppc)(eieio,b11to20|b0)\n");
6407 return False;
6408 }
6409 DIP("eieio\n");
6410 } else {
6411 if (b11to20 != 0 || b0 != 0) {
6412 vex_printf("dis_memsync(ppc)(mbar,b11to20|b0)\n");
6413 return False;
6414 }
6415 DIP("mbar %d\n", M0);
6416 }
6417 /* Insert a memory fence, just to be on the safe side. */
6418 stmt( IRStmt_MBE(Imbe_Fence) );
6419 break;
6420
6421 case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458)
6422 IRTemp res;
6423 /* According to the PowerPC ISA version 2.05, b0 (called EH
6424 in the documentation) is merely a hint bit to the
6425 hardware, I think as to whether or not contention is
6426 likely. So we can just ignore it. */
6427 DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
6428
6429 // trap if misaligned
6430 gen_SIGBUS_if_misaligned( EA, 4 );
6431
6432 // and actually do the load
6433 res = newTemp(Ity_I32);
6434 stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) );
6435
6436 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) );
6437 break;
6438 }
6439
6440 case 0x034: { // lbarx (Load Word and Reserve Indexed)
6441 IRTemp res;
6442 /* According to the PowerPC ISA version 2.05, b0 (called EH
6443 in the documentation) is merely a hint bit to the
6444 hardware, I think as to whether or not contention is
6445 likely. So we can just ignore it. */
6446 DIP("lbarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
6447
6448 // and actually do the load
6449 res = newTemp(Ity_I8);
6450 stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) );
6451
6452 putIReg( rD_addr, mkWidenFrom8(ty, mkexpr(res), False) );
6453 break;
6454 }
6455
6456 case 0x074: { // lharx (Load Word and Reserve Indexed)
6457 IRTemp res;
6458 /* According to the PowerPC ISA version 2.05, b0 (called EH
6459 in the documentation) is merely a hint bit to the
6460 hardware, I think as to whether or not contention is
6461 likely. So we can just ignore it. */
6462 DIP("lharx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
6463
6464 // trap if misaligned
6465 gen_SIGBUS_if_misaligned( EA, 2 );
6466
6467 // and actually do the load
6468 res = newTemp(Ity_I16);
6469 stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) );
6470
6471 putIReg( rD_addr, mkWidenFrom16(ty, mkexpr(res), False) );
6472 break;
6473 }
6474
6475 case 0x096: {
6476 // stwcx. (Store Word Conditional Indexed, PPC32 p532)
6477 // Note this has to handle stwcx. in both 32- and 64-bit modes,
6478 // so isn't quite as straightforward as it might otherwise be.
6479 IRTemp rS = newTemp(Ity_I32);
6480 IRTemp resSC;
6481 if (b0 != 1) {
6482 vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
6483 return False;
6484 }
6485 DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6486
6487 // trap if misaligned
6488 gen_SIGBUS_if_misaligned( EA, 4 );
6489
6490 // Get the data to be stored, and narrow to 32 bits if necessary
6491 assign( rS, mkNarrowTo32(ty, getIReg(rS_addr)) );
6492
6493 // Do the store, and get success/failure bit into resSC
6494 resSC = newTemp(Ity_I1);
6495 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
6496
6497 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure
6498 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success
6499 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
6500 putCR0(0, getXER_SO());
6501
6502 /* Note:
6503 If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
6504 whether rS is stored is dependent on that value. */
6505 /* So I guess we can just ignore this case? */
6506 break;
6507 }
6508
6509 case 0x2B6: {
6510 // stbcx. (Store Byte Conditional Indexed)
6511 // Note this has to handle stbcx. in both 32- and 64-bit modes,
6512 // so isn't quite as straightforward as it might otherwise be.
6513 IRTemp rS = newTemp(Ity_I8);
6514 IRTemp resSC;
6515 if (b0 != 1) {
6516 vex_printf("dis_memsync(ppc)(stbcx.,b0)\n");
6517 return False;
6518 }
6519 DIP("stbcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6520
6521 // Get the data to be stored, and narrow to 32 bits if necessary
6522 assign( rS, mkNarrowTo8(ty, getIReg(rS_addr)) );
6523
6524 // Do the store, and get success/failure bit into resSC
6525 resSC = newTemp(Ity_I1);
6526 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
6527
6528 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure
6529 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success
6530 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
6531 putCR0(0, getXER_SO());
6532
6533 /* Note:
6534 If resaddr != lbarx_resaddr, CR0[EQ] is undefined, and
6535 whether rS is stored is dependent on that value. */
6536 /* So I guess we can just ignore this case? */
6537 break;
6538 }
6539
6540 case 0x2D6: {
6541 // sthcx. (Store Word Conditional Indexed, PPC32 p532)
6542 // Note this has to handle sthcx. in both 32- and 64-bit modes,
6543 // so isn't quite as straightforward as it might otherwise be.
6544 IRTemp rS = newTemp(Ity_I16);
6545 IRTemp resSC;
6546 if (b0 != 1) {
6547 vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
6548 return False;
6549 }
6550 DIP("sthcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6551
6552 // trap if misaligned
6553 gen_SIGBUS_if_misaligned( EA, 2 );
6554
6555 // Get the data to be stored, and narrow to 16 bits if necessary
6556 assign( rS, mkNarrowTo16(ty, getIReg(rS_addr)) );
6557
6558 // Do the store, and get success/failure bit into resSC
6559 resSC = newTemp(Ity_I1);
6560 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
6561
6562 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure
6563 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success
6564 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
6565 putCR0(0, getXER_SO());
6566
6567 /* Note:
6568 If resaddr != lharx_resaddr, CR0[EQ] is undefined, and
6569 whether rS is stored is dependent on that value. */
6570 /* So I guess we can just ignore this case? */
6571 break;
6572 }
6573
6574 case 0x256: // sync (Synchronize, PPC32 p543),
6575 // also lwsync (L==1), ptesync (L==2)
6576 /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html
6577
6578 The PowerPC architecture used in IBM chips has expanded
6579 the sync instruction into two variants: lightweight sync
6580 and heavyweight sync. The original sync instruction is
6581 the new heavyweight sync and lightweight sync is a strict
6582 subset of the heavyweight sync functionality. This allows
6583 the programmer to specify a less expensive operation on
6584 high-end systems when the full sync functionality is not
6585 necessary.
6586
6587 The basic "sync" mnemonic now utilizes an operand. "sync"
6588 without an operand now becomes a extended mnemonic for
6589 heavyweight sync. Processors without the lwsync
6590 instruction will not decode the L field and will perform a
6591 heavyweight sync. Everything is backward compatible.
6592
6593 sync = sync 0
6594 lwsync = sync 1
6595 ptesync = sync 2 *** TODO - not implemented ***
6596 */
6597 if (b11to20 != 0 || b0 != 0) {
6598 vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n");
6599 return False;
6600 }
6601 if (flag_L != 0/*sync*/ && flag_L != 1/*lwsync*/) {
6602 vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n");
6603 return False;
6604 }
6605 DIP("%ssync\n", flag_L == 1 ? "lw" : "");
6606 /* Insert a memory fence. It's sometimes important that these
6607 are carried through to the generated code. */
6608 stmt( IRStmt_MBE(Imbe_Fence) );
6609 break;
6610
6611 /* 64bit Memsync */
6612 case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473)
6613 IRTemp res;
6614 /* According to the PowerPC ISA version 2.05, b0 (called EH
6615 in the documentation) is merely a hint bit to the
6616 hardware, I think as to whether or not contention is
6617 likely. So we can just ignore it. */
6618 if (!mode64)
6619 return False;
6620 DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
6621
6622 // trap if misaligned
6623 gen_SIGBUS_if_misaligned( EA, 8 );
6624
6625 // and actually do the load
6626 res = newTemp(Ity_I64);
6627 stmt( stmt_load( res, mkexpr(EA), NULL/*this is a load*/) );
6628
6629 putIReg( rD_addr, mkexpr(res) );
6630 break;
6631 }
6632
6633 case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581)
6634 // A marginally simplified version of the stwcx. case
6635 IRTemp rS = newTemp(Ity_I64);
6636 IRTemp resSC;
6637 if (b0 != 1) {
6638 vex_printf("dis_memsync(ppc)(stdcx.,b0)\n");
6639 return False;
6640 }
6641 if (!mode64)
6642 return False;
6643 DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6644
6645 // trap if misaligned
6646 gen_SIGBUS_if_misaligned( EA, 8 );
6647
6648 // Get the data to be stored
6649 assign( rS, getIReg(rS_addr) );
6650
6651 // Do the store, and get success/failure bit into resSC
6652 resSC = newTemp(Ity_I1);
6653 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
6654
6655 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure
6656 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success
6657 putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
6658 putCR0(0, getXER_SO());
6659
6660 /* Note:
6661 If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
6662 whether rS is stored is dependent on that value. */
6663 /* So I guess we can just ignore this case? */
6664 break;
6665 }
6666
6667 /* 128bit Memsync */
6668 case 0x114: { // lqarx (Load QuadWord and Reserve Indexed)
6669 IRTemp res_hi = newTemp(ty);
6670 IRTemp res_lo = newTemp(ty);
6671
6672 /* According to the PowerPC ISA version 2.07, b0 (called EH
6673 in the documentation) is merely a hint bit to the
6674 hardware, I think as to whether or not contention is
6675 likely. So we can just ignore it. */
6676 DIP("lqarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
6677
6678 // trap if misaligned
6679 gen_SIGBUS_if_misaligned( EA, 16 );
6680
6681 // and actually do the load
6682 if (mode64) {
6683 if (host_endness == VexEndnessBE) {
6684 stmt( stmt_load( res_hi,
6685 mkexpr(EA), NULL/*this is a load*/) );
6686 stmt( stmt_load( res_lo,
6687 binop(Iop_Add64, mkexpr(EA), mkU64(8) ),
6688 NULL/*this is a load*/) );
6689 } else {
6690 stmt( stmt_load( res_lo,
6691 mkexpr(EA), NULL/*this is a load*/) );
6692 stmt( stmt_load( res_hi,
6693 binop(Iop_Add64, mkexpr(EA), mkU64(8) ),
6694 NULL/*this is a load*/) );
6695 }
6696 } else {
6697 stmt( stmt_load( res_hi,
6698 binop( Iop_Add32, mkexpr(EA), mkU32(4) ),
6699 NULL/*this is a load*/) );
6700 stmt( stmt_load( res_lo,
6701 binop( Iop_Add32, mkexpr(EA), mkU32(12) ),
6702 NULL/*this is a load*/) );
6703 }
6704 putIReg( rD_addr, mkexpr(res_hi) );
6705 putIReg( rD_addr+1, mkexpr(res_lo) );
6706 break;
6707 }
6708
6709 case 0x0B6: { // stqcx. (Store QuadWord Condition Indexd, PPC64)
6710 // A marginally simplified version of the stwcx. case
6711 IRTemp rS_hi = newTemp(ty);
6712 IRTemp rS_lo = newTemp(ty);
6713 IRTemp resSC;
6714 if (b0 != 1) {
6715 vex_printf("dis_memsync(ppc)(stqcx.,b0)\n");
6716 return False;
6717 }
6718
6719 DIP("stqcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6720
6721 // trap if misaligned
6722 gen_SIGBUS_if_misaligned( EA, 16 );
6723 // Get the data to be stored
6724 assign( rS_hi, getIReg(rS_addr) );
6725 assign( rS_lo, getIReg(rS_addr+1) );
6726
6727 // Do the store, and get success/failure bit into resSC
6728 resSC = newTemp(Ity_I1);
6729
6730 if (mode64) {
6731 if (host_endness == VexEndnessBE) {
6732 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_hi) ) );
6733 store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ),
6734 mkexpr(rS_lo) );
6735 } else {
6736 stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_lo) ) );
6737 store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ),
6738 mkexpr(rS_hi) );
6739 }
6740 } else {
6741 stmt( stmt_load( resSC, binop( Iop_Add32,
6742 mkexpr(EA),
6743 mkU32(4) ),
6744 mkexpr(rS_hi) ) );
6745 store( binop(Iop_Add32, mkexpr(EA), mkU32(12) ), mkexpr(rS_lo) );
6746 }
6747
6748 // Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure
6749 // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success
6750 putCR321(0, binop( Iop_Shl8,
6751 unop(Iop_1Uto8, mkexpr(resSC) ),
6752 mkU8(1)));
6753 putCR0(0, getXER_SO());
6754 break;
6755 }
6756
6757 default:
6758 vex_printf("dis_memsync(ppc)(opc2)\n");
6759 return False;
6760 }
6761 break;
6762
6763 default:
6764 vex_printf("dis_memsync(ppc)(opc1)\n");
6765 return False;
6766 }
6767 return True;
6768 }
6769
6770
6771
6772 /*
6773 Integer Shift Instructions
6774 */
dis_int_shift(UInt theInstr)6775 static Bool dis_int_shift ( UInt theInstr )
6776 {
6777 /* X-Form, XS-Form */
6778 UChar opc1 = ifieldOPC(theInstr);
6779 UChar rS_addr = ifieldRegDS(theInstr);
6780 UChar rA_addr = ifieldRegA(theInstr);
6781 UChar rB_addr = ifieldRegB(theInstr);
6782 UChar sh_imm = rB_addr;
6783 UInt opc2 = ifieldOPClo10(theInstr);
6784 UChar b1 = ifieldBIT1(theInstr);
6785 UChar flag_rC = ifieldBIT0(theInstr);
6786
6787 IRType ty = mode64 ? Ity_I64 : Ity_I32;
6788 IRTemp rA = newTemp(ty);
6789 IRTemp rS = newTemp(ty);
6790 IRTemp rB = newTemp(ty);
6791 IRTemp outofrange = newTemp(Ity_I1);
6792 IRTemp rS_lo32 = newTemp(Ity_I32);
6793 IRTemp rB_lo32 = newTemp(Ity_I32);
6794 IRExpr* e_tmp;
6795
6796 assign( rS, getIReg(rS_addr) );
6797 assign( rB, getIReg(rB_addr) );
6798 assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) );
6799 assign( rB_lo32, mkNarrowTo32(ty, mkexpr(rB)) );
6800
6801 if (opc1 == 0x1F) {
6802 switch (opc2) {
6803 case 0x018: { // slw (Shift Left Word, PPC32 p505)
6804 DIP("slw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
6805 rA_addr, rS_addr, rB_addr);
6806 /* rA = rS << rB */
6807 /* ppc32 semantics are:
6808 slw(x,y) = (x << (y & 31)) -- primary result
6809 & ~((y << 26) >>s 31) -- make result 0
6810 for y in 32 .. 63
6811 */
6812 e_tmp =
6813 binop( Iop_And32,
6814 binop( Iop_Shl32,
6815 mkexpr(rS_lo32),
6816 unop( Iop_32to8,
6817 binop(Iop_And32,
6818 mkexpr(rB_lo32), mkU32(31)))),
6819 unop( Iop_Not32,
6820 binop( Iop_Sar32,
6821 binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)),
6822 mkU8(31))) );
6823 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
6824 break;
6825 }
6826
6827 case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506)
6828 IRTemp sh_amt = newTemp(Ity_I32);
6829 DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
6830 rA_addr, rS_addr, rB_addr);
6831 /* JRS: my reading of the (poorly worded) PPC32 doc p506 is:
6832 amt = rB & 63
6833 rA = Sar32( rS, amt > 31 ? 31 : amt )
6834 XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi)
6835 */
6836 assign( sh_amt, binop(Iop_And32, mkU32(0x3F),
6837 mkexpr(rB_lo32)) );
6838 assign( outofrange,
6839 binop(Iop_CmpLT32U, mkU32(31), mkexpr(sh_amt)) );
6840 e_tmp = binop( Iop_Sar32,
6841 mkexpr(rS_lo32),
6842 unop( Iop_32to8,
6843 IRExpr_ITE( mkexpr(outofrange),
6844 mkU32(31),
6845 mkexpr(sh_amt)) ) );
6846 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) );
6847
6848 set_XER_CA( ty, PPCG_FLAG_OP_SRAW,
6849 mkexpr(rA),
6850 mkWidenFrom32(ty, mkexpr(rS_lo32), True),
6851 mkWidenFrom32(ty, mkexpr(sh_amt), True ),
6852 mkWidenFrom32(ty, getXER_CA32(), True) );
6853 break;
6854 }
6855
6856 case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507)
6857 DIP("srawi%s r%u,r%u,%d\n", flag_rC ? ".":"",
6858 rA_addr, rS_addr, sh_imm);
6859 vassert(sh_imm < 32);
6860 if (mode64) {
6861 assign( rA, binop(Iop_Sar64,
6862 binop(Iop_Shl64, getIReg(rS_addr),
6863 mkU8(32)),
6864 mkU8(32 + sh_imm)) );
6865 } else {
6866 assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32),
6867 mkU8(sh_imm)) );
6868 }
6869
6870 set_XER_CA( ty, PPCG_FLAG_OP_SRAWI,
6871 mkexpr(rA),
6872 mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True),
6873 mkSzImm(ty, sh_imm),
6874 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
6875 break;
6876
6877 case 0x218: // srw (Shift Right Word, PPC32 p508)
6878 DIP("srw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
6879 rA_addr, rS_addr, rB_addr);
6880 /* rA = rS >>u rB */
6881 /* ppc32 semantics are:
6882 srw(x,y) = (x >>u (y & 31)) -- primary result
6883 & ~((y << 26) >>s 31) -- make result 0
6884 for y in 32 .. 63
6885 */
6886 e_tmp =
6887 binop(
6888 Iop_And32,
6889 binop( Iop_Shr32,
6890 mkexpr(rS_lo32),
6891 unop( Iop_32to8,
6892 binop(Iop_And32, mkexpr(rB_lo32),
6893 mkU32(31)))),
6894 unop( Iop_Not32,
6895 binop( Iop_Sar32,
6896 binop(Iop_Shl32, mkexpr(rB_lo32),
6897 mkU8(26)),
6898 mkU8(31))));
6899 assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
6900 break;
6901
6902
6903 /* 64bit Shifts */
6904 case 0x01B: // sld (Shift Left DWord, PPC64 p568)
6905 DIP("sld%s r%u,r%u,r%u\n",
6906 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6907 /* rA = rS << rB */
6908 /* ppc64 semantics are:
6909 slw(x,y) = (x << (y & 63)) -- primary result
6910 & ~((y << 57) >>s 63) -- make result 0
6911 for y in 64 ..
6912 */
6913 assign( rA,
6914 binop(
6915 Iop_And64,
6916 binop( Iop_Shl64,
6917 mkexpr(rS),
6918 unop( Iop_64to8,
6919 binop(Iop_And64, mkexpr(rB), mkU64(63)))),
6920 unop( Iop_Not64,
6921 binop( Iop_Sar64,
6922 binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
6923 mkU8(63)))) );
6924 break;
6925
6926 case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570)
6927 IRTemp sh_amt = newTemp(Ity_I64);
6928 DIP("srad%s r%u,r%u,r%u\n",
6929 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6930 /* amt = rB & 127
6931 rA = Sar64( rS, amt > 63 ? 63 : amt )
6932 XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi)
6933 */
6934 assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) );
6935 assign( outofrange,
6936 binop(Iop_CmpLT64U, mkU64(63), mkexpr(sh_amt)) );
6937 assign( rA,
6938 binop( Iop_Sar64,
6939 mkexpr(rS),
6940 unop( Iop_64to8,
6941 IRExpr_ITE( mkexpr(outofrange),
6942 mkU64(63),
6943 mkexpr(sh_amt)) ))
6944 );
6945 set_XER_CA( ty, PPCG_FLAG_OP_SRAD,
6946 mkexpr(rA), mkexpr(rS), mkexpr(sh_amt),
6947 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
6948 break;
6949 }
6950
6951 case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571)
6952 sh_imm |= b1<<5;
6953 vassert(sh_imm < 64);
6954 DIP("sradi%s r%u,r%u,%u\n",
6955 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
6956 assign( rA, binop(Iop_Sar64, getIReg(rS_addr), mkU8(sh_imm)) );
6957
6958 set_XER_CA( ty, PPCG_FLAG_OP_SRADI,
6959 mkexpr(rA),
6960 getIReg(rS_addr),
6961 mkU64(sh_imm),
6962 mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
6963 break;
6964
6965 case 0x21B: // srd (Shift Right DWord, PPC64 p574)
6966 DIP("srd%s r%u,r%u,r%u\n",
6967 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6968 /* rA = rS >>u rB */
6969 /* ppc semantics are:
6970 srw(x,y) = (x >>u (y & 63)) -- primary result
6971 & ~((y << 57) >>s 63) -- make result 0
6972 for y in 64 .. 127
6973 */
6974 assign( rA,
6975 binop(
6976 Iop_And64,
6977 binop( Iop_Shr64,
6978 mkexpr(rS),
6979 unop( Iop_64to8,
6980 binop(Iop_And64, mkexpr(rB), mkU64(63)))),
6981 unop( Iop_Not64,
6982 binop( Iop_Sar64,
6983 binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
6984 mkU8(63)))) );
6985 break;
6986
6987 default:
6988 vex_printf("dis_int_shift(ppc)(opc2)\n");
6989 return False;
6990 }
6991 } else {
6992 vex_printf("dis_int_shift(ppc)(opc1)\n");
6993 return False;
6994 }
6995
6996 putIReg( rA_addr, mkexpr(rA) );
6997
6998 if (flag_rC) {
6999 set_CR0( mkexpr(rA) );
7000 }
7001 return True;
7002 }
7003
7004
7005
7006 /*
7007 Integer Load/Store Reverse Instructions
7008 */
7009 /* Generates code to swap the byte order in an Ity_I32. */
gen_byterev32(IRTemp t)7010 static IRExpr* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t )
7011 {
7012 vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
7013 return
7014 binop(Iop_Or32,
7015 binop(Iop_Shl32, mkexpr(t), mkU8(24)),
7016 binop(Iop_Or32,
7017 binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
7018 mkU32(0x00FF0000)),
7019 binop(Iop_Or32,
7020 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
7021 mkU32(0x0000FF00)),
7022 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(24)),
7023 mkU32(0x000000FF) )
7024 )));
7025 }
7026
7027 /* Generates code to swap the byte order in the lower half of an Ity_I32,
7028 and zeroes the upper half. */
gen_byterev16(IRTemp t)7029 static IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t )
7030 {
7031 vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
7032 return
7033 binop(Iop_Or32,
7034 binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
7035 mkU32(0x0000FF00)),
7036 binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
7037 mkU32(0x000000FF))
7038 );
7039 }
7040
dis_int_ldst_rev(UInt theInstr)7041 static Bool dis_int_ldst_rev ( UInt theInstr )
7042 {
7043 /* X-Form */
7044 UChar opc1 = ifieldOPC(theInstr);
7045 UChar rD_addr = ifieldRegDS(theInstr);
7046 UChar rS_addr = rD_addr;
7047 UChar rA_addr = ifieldRegA(theInstr);
7048 UChar rB_addr = ifieldRegB(theInstr);
7049 UInt opc2 = ifieldOPClo10(theInstr);
7050 UChar b0 = ifieldBIT0(theInstr);
7051
7052 IRType ty = mode64 ? Ity_I64 : Ity_I32;
7053 IRTemp EA = newTemp(ty);
7054 IRTemp w1 = newTemp(Ity_I32);
7055 IRTemp w2 = newTemp(Ity_I32);
7056
7057 if (opc1 != 0x1F || b0 != 0) {
7058 vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n");
7059 return False;
7060 }
7061
7062 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
7063
7064 switch (opc2) {
7065
7066 case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449)
7067 DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7068 assign( w1, unop(Iop_16Uto32, load(Ity_I16, mkexpr(EA))) );
7069 assign( w2, gen_byterev16(w1) );
7070 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
7071 /* Signed */False) );
7072 break;
7073
7074 case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459)
7075 DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7076 assign( w1, load(Ity_I32, mkexpr(EA)) );
7077 assign( w2, gen_byterev32(w1) );
7078 putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
7079 /* Signed */False) );
7080 break;
7081
7082 case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed)
7083 {
7084 IRExpr * nextAddr;
7085 IRTemp w3 = newTemp( Ity_I32 );
7086 IRTemp w4 = newTemp( Ity_I32 );
7087 DIP("ldbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7088 assign( w1, load( Ity_I32, mkexpr( EA ) ) );
7089 assign( w2, gen_byterev32( w1 ) );
7090 nextAddr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
7091 ty == Ity_I64 ? mkU64( 4 ) : mkU32( 4 ) );
7092 assign( w3, load( Ity_I32, nextAddr ) );
7093 assign( w4, gen_byterev32( w3 ) );
7094 if (host_endness == VexEndnessLE)
7095 putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w2 ), mkexpr( w4 ) ) );
7096 else
7097 putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) );
7098 break;
7099 }
7100
7101 case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523)
7102 DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7103 assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
7104 store( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) );
7105 break;
7106
7107 case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531)
7108 DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7109 assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
7110 store( mkexpr(EA), gen_byterev32(w1) );
7111 break;
7112
7113 case 0x294: // stdbrx (Store Doubleword Byte-Reverse Indexed)
7114 {
7115 IRTemp lo = newTemp(Ity_I32);
7116 IRTemp hi = newTemp(Ity_I32);
7117 IRTemp rS = newTemp(Ity_I64);
7118 assign( rS, getIReg( rS_addr ) );
7119 DIP("stdbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7120 assign(lo, unop(Iop_64HIto32, mkexpr(rS)));
7121 assign(hi, unop(Iop_64to32, mkexpr(rS)));
7122 store( mkexpr( EA ),
7123 binop( Iop_32HLto64, gen_byterev32( hi ),
7124 gen_byterev32( lo ) ) );
7125 break;
7126 }
7127
7128 default:
7129 vex_printf("dis_int_ldst_rev(ppc)(opc2)\n");
7130 return False;
7131 }
7132 return True;
7133 }
7134
7135
7136
7137 /*
7138 Processor Control Instructions
7139 */
dis_proc_ctl(const VexAbiInfo * vbi,UInt theInstr)7140 static Bool dis_proc_ctl ( const VexAbiInfo* vbi, UInt theInstr )
7141 {
7142 UChar opc1 = ifieldOPC(theInstr);
7143
7144 /* X-Form */
7145 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) );
7146 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) );
7147 UChar rD_addr = ifieldRegDS(theInstr);
7148 UInt b11to20 = IFIELD( theInstr, 11, 10 );
7149
7150 /* XFX-Form */
7151 UChar rS_addr = rD_addr;
7152 UInt SPR = b11to20;
7153 UInt TBR = b11to20;
7154 UChar b20 = toUChar( IFIELD( theInstr, 20, 1 ) );
7155 UInt CRM = IFIELD( theInstr, 12, 8 );
7156 UChar b11 = toUChar( IFIELD( theInstr, 11, 1 ) );
7157
7158 UInt opc2 = ifieldOPClo10(theInstr);
7159 UChar b0 = ifieldBIT0(theInstr);
7160
7161 IRType ty = mode64 ? Ity_I64 : Ity_I32;
7162 IRTemp rS = newTemp(ty);
7163 assign( rS, getIReg(rS_addr) );
7164
7165 /* Reorder SPR field as per PPC32 p470 */
7166 SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F);
7167 /* Reorder TBR field as per PPC32 p475 */
7168 TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31);
7169
7170 /* b0 = 0, inst is treated as floating point inst for reservation purposes
7171 * b0 = 1, inst is treated as vector inst for reservation purposes
7172 */
7173 if (opc1 != 0x1F) {
7174 vex_printf("dis_proc_ctl(ppc)(opc1|b%d)\n", b0);
7175 return False;
7176 }
7177
7178 switch (opc2) {
7179 /* X-Form */
7180 case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466)
7181 if (b21to22 != 0 || b11to20 != 0) {
7182 vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n");
7183 return False;
7184 }
7185 DIP("mcrxr crf%d\n", crfD);
7186 /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */
7187 putGST_field( PPC_GST_CR,
7188 getGST_field( PPC_GST_XER, 7 ),
7189 crfD );
7190
7191 // Clear XER[0-3]
7192 putXER_SO( mkU8(0) );
7193 putXER_OV( mkU8(0) );
7194 putXER_CA( mkU8(0) );
7195 break;
7196 }
7197
7198 case 0x013:
7199 // b11to20==0: mfcr (Move from Cond Register, PPC32 p467)
7200 // b20==1 & b11==0: mfocrf (Move from One CR Field)
7201 // However it seems that the 'mfcr' behaviour is an acceptable
7202 // implementation of mfocr (from the 2.02 arch spec)
7203 if (b11to20 == 0) {
7204 DIP("mfcr r%u\n", rD_addr);
7205 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
7206 /* Signed */False) );
7207 break;
7208 }
7209 if (b20 == 1 && b11 == 0) {
7210 DIP("mfocrf r%u,%u\n", rD_addr, CRM);
7211 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
7212 /* Signed */False) );
7213 break;
7214 }
7215 /* not decodable */
7216 return False;
7217
7218 /* XFX-Form */
7219 case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470)
7220
7221 switch (SPR) { // Choose a register...
7222 case 0x1:
7223 DIP("mfxer r%u\n", rD_addr);
7224 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ),
7225 /* Signed */False) );
7226 break;
7227 case 0x8:
7228 DIP("mflr r%u\n", rD_addr);
7229 putIReg( rD_addr, getGST( PPC_GST_LR ) );
7230 break;
7231 case 0x9:
7232 DIP("mfctr r%u\n", rD_addr);
7233 putIReg( rD_addr, getGST( PPC_GST_CTR ) );
7234 break;
7235 case 0x80: // 128
7236 DIP("mfspr r%u (TFHAR)\n", rD_addr);
7237 putIReg( rD_addr, getGST( PPC_GST_TFHAR) );
7238 break;
7239 case 0x81: // 129
7240 DIP("mfspr r%u (TFIAR)\n", rD_addr);
7241 putIReg( rD_addr, getGST( PPC_GST_TFIAR) );
7242 break;
7243 case 0x82: // 130
7244 DIP("mfspr r%u (TEXASR)\n", rD_addr);
7245 putIReg( rD_addr, getGST( PPC_GST_TEXASR) );
7246 break;
7247 case 0x83: // 131
7248 DIP("mfspr r%u (TEXASRU)\n", rD_addr);
7249 putIReg( rD_addr, getGST( PPC_GST_TEXASRU) );
7250 break;
7251 case 0x9F: // 159
7252 DIP("mfspr r%u (PSPB)\n", rD_addr);
7253 putIReg( rD_addr, getGST( PPC_GST_PSPB) );
7254 break;
7255 case 0x380: // 896
7256 DIP("mfspr r%u (PPR)\n", rD_addr);
7257 putIReg( rD_addr, getGST( PPC_GST_PPR) );
7258 break;
7259 case 0x382: // 898
7260 DIP("mfspr r%u (PPR)32\n", rD_addr);
7261 putIReg( rD_addr, getGST( PPC_GST_PPR32) );
7262 break;
7263 case 0x100:
7264 DIP("mfvrsave r%u\n", rD_addr);
7265 putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ),
7266 /* Signed */False) );
7267 break;
7268
7269 case 0x103:
7270 DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr);
7271 putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) );
7272 break;
7273
7274 /* Even a lowly PPC7400 can run the associated helper, so no
7275 obvious need for feature testing at this point. */
7276 case 268 /* 0x10C */:
7277 case 269 /* 0x10D */: {
7278 UInt arg = SPR==268 ? 0 : 1;
7279 IRTemp val = newTemp(Ity_I32);
7280 IRExpr** args = mkIRExprVec_1( mkU32(arg) );
7281 IRDirty* d = unsafeIRDirty_1_N(
7282 val,
7283 0/*regparms*/,
7284 "ppc32g_dirtyhelper_MFSPR_268_269",
7285 fnptr_to_fnentry
7286 (vbi, &ppc32g_dirtyhelper_MFSPR_268_269),
7287 args
7288 );
7289 /* execute the dirty call, dumping the result in val. */
7290 stmt( IRStmt_Dirty(d) );
7291 putIReg( rD_addr,
7292 mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
7293 DIP("mfspr r%u,%u", rD_addr, SPR);
7294 break;
7295 }
7296
7297 /* Again, runs natively on PPC7400 (7447, really). Not
7298 bothering with a feature test. */
7299 case 287: /* 0x11F */ {
7300 IRTemp val = newTemp(Ity_I32);
7301 IRExpr** args = mkIRExprVec_0();
7302 IRDirty* d = unsafeIRDirty_1_N(
7303 val,
7304 0/*regparms*/,
7305 "ppc32g_dirtyhelper_MFSPR_287",
7306 fnptr_to_fnentry
7307 (vbi, &ppc32g_dirtyhelper_MFSPR_287),
7308 args
7309 );
7310 /* execute the dirty call, dumping the result in val. */
7311 stmt( IRStmt_Dirty(d) );
7312 putIReg( rD_addr,
7313 mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
7314 DIP("mfspr r%u,%u", rD_addr, SPR);
7315 break;
7316 }
7317
7318 default:
7319 vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR);
7320 return False;
7321 }
7322 break;
7323
7324 case 0x173: { // mftb (Move from Time Base, PPC32 p475)
7325 IRTemp val = newTemp(Ity_I64);
7326 IRExpr** args = mkIRExprVec_0();
7327 IRDirty* d = unsafeIRDirty_1_N(
7328 val,
7329 0/*regparms*/,
7330 "ppcg_dirtyhelper_MFTB",
7331 fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB),
7332 args );
7333 /* execute the dirty call, dumping the result in val. */
7334 stmt( IRStmt_Dirty(d) );
7335
7336 switch (TBR) {
7337 case 269:
7338 DIP("mftbu r%u", rD_addr);
7339 putIReg( rD_addr,
7340 mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)),
7341 /* Signed */False) );
7342 break;
7343 case 268:
7344 DIP("mftb r%u", rD_addr);
7345 putIReg( rD_addr, (mode64) ? mkexpr(val) :
7346 unop(Iop_64to32, mkexpr(val)) );
7347 break;
7348 default:
7349 return False; /* illegal instruction */
7350 }
7351 break;
7352 }
7353
7354 case 0x090: {
7355 // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477)
7356 // b20==1: mtocrf (Move to One Cond Reg Field)
7357 Int cr;
7358 UChar shft;
7359 if (b11 != 0)
7360 return False;
7361 if (b20 == 1) {
7362 /* ppc64 v2.02 spec says mtocrf gives undefined outcome if >
7363 1 field is written. It seems more robust to decline to
7364 decode the insn if so. */
7365 switch (CRM) {
7366 case 0x01: case 0x02: case 0x04: case 0x08:
7367 case 0x10: case 0x20: case 0x40: case 0x80:
7368 break;
7369 default:
7370 return False;
7371 }
7372 }
7373 DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf",
7374 CRM, rS_addr);
7375 /* Write to each field specified by CRM */
7376 for (cr = 0; cr < 8; cr++) {
7377 if ((CRM & (1 << (7-cr))) == 0)
7378 continue;
7379 shft = 4*(7-cr);
7380 putGST_field( PPC_GST_CR,
7381 binop(Iop_Shr32,
7382 mkNarrowTo32(ty, mkexpr(rS)),
7383 mkU8(shft)), cr );
7384 }
7385 break;
7386 }
7387
7388 case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483)
7389
7390 switch (SPR) { // Choose a register...
7391 case 0x1:
7392 DIP("mtxer r%u\n", rS_addr);
7393 putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) );
7394 break;
7395 case 0x8:
7396 DIP("mtlr r%u\n", rS_addr);
7397 putGST( PPC_GST_LR, mkexpr(rS) );
7398 break;
7399 case 0x9:
7400 DIP("mtctr r%u\n", rS_addr);
7401 putGST( PPC_GST_CTR, mkexpr(rS) );
7402 break;
7403 case 0x100:
7404 DIP("mtvrsave r%u\n", rS_addr);
7405 putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) );
7406 break;
7407 case 0x80: // 128
7408 DIP("mtspr r%u (TFHAR)\n", rS_addr);
7409 putGST( PPC_GST_TFHAR, mkexpr(rS) );
7410 break;
7411 case 0x81: // 129
7412 DIP("mtspr r%u (TFIAR)\n", rS_addr);
7413 putGST( PPC_GST_TFIAR, mkexpr(rS) );
7414 break;
7415 case 0x82: // 130
7416 DIP("mtspr r%u (TEXASR)\n", rS_addr);
7417 putGST( PPC_GST_TEXASR, mkexpr(rS) );
7418 break;
7419 case 0x9F: // 159
7420 DIP("mtspr r%u (PSPB)\n", rS_addr);
7421 putGST( PPC_GST_PSPB, mkexpr(rS) );
7422 break;
7423 case 0x380: // 896
7424 DIP("mtspr r%u (PPR)\n", rS_addr);
7425 putGST( PPC_GST_PPR, mkexpr(rS) );
7426 break;
7427 case 0x382: // 898
7428 DIP("mtspr r%u (PPR32)\n", rS_addr);
7429 putGST( PPC_GST_PPR32, mkexpr(rS) );
7430 break;
7431 default:
7432 vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR);
7433 return False;
7434 }
7435 break;
7436
7437 case 0x33: // mfvsrd
7438 {
7439 UChar XS = ifieldRegXS( theInstr );
7440 UChar rA_addr = ifieldRegA(theInstr);
7441 IRExpr * high64;
7442 IRTemp vS = newTemp( Ity_V128 );
7443 DIP("mfvsrd r%u,vsr%d\n", rA_addr, XS);
7444
7445 /* XS = SX || S
7446 * For SX=0, mfvsrd is treated as a Floating-Point
7447 * instruction in terms of resource availability.
7448 * For SX=1, mfvsrd is treated as a Vector instruction in
7449 * terms of resource availability.
7450 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
7451 */
7452 assign( vS, getVSReg( XS ) );
7453 high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
7454 putIReg( rA_addr, (mode64) ? high64 :
7455 unop( Iop_64to32, high64 ) );
7456 break;
7457 }
7458
7459 case 0x73: // mfvsrwz
7460 {
7461 UChar XS = ifieldRegXS( theInstr );
7462 UChar rA_addr = ifieldRegA(theInstr);
7463 IRExpr * high64;
7464 IRTemp vS = newTemp( Ity_V128 );
7465 DIP("mfvsrwz r%u,vsr%d\n", rA_addr, XS);
7466 /* XS = SX || S
7467 * For SX=0, mfvsrwz is treated as a Floating-Point
7468 * instruction in terms of resource availability.
7469 * For SX=1, mfvsrwz is treated as a Vector instruction in
7470 * terms of resource availability.
7471 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
7472 */
7473
7474 assign( vS, getVSReg( XS ) );
7475 high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
7476 /* move value to the destination setting the upper 32-bits to zero */
7477 putIReg( rA_addr, (mode64) ?
7478 binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) :
7479 unop( Iop_64to32,
7480 binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) ) );
7481 break;
7482 }
7483
7484 case 0xB3: // mtvsrd
7485 {
7486 UChar XT = ifieldRegXT( theInstr );
7487 UChar rA_addr = ifieldRegA(theInstr);
7488 IRTemp rA = newTemp(ty);
7489 DIP("mtvsrd vsr%d,r%u\n", XT, rA_addr);
7490 /* XS = SX || S
7491 * For SX=0, mfvsrd is treated as a Floating-Point
7492 * instruction in terms of resource availability.
7493 * For SX=1, mfvsrd is treated as a Vector instruction in
7494 * terms of resource availability.
7495 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
7496 */
7497 assign( rA, getIReg(rA_addr) );
7498
7499 if (mode64)
7500 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( rA ), mkU64( 0 ) ) );
7501 else
7502 putVSReg( XT, binop( Iop_64HLtoV128,
7503 binop( Iop_32HLto64,
7504 mkU32( 0 ),
7505 mkexpr( rA ) ),
7506 mkU64( 0 ) ) );
7507 break;
7508 }
7509
7510 case 0xD3: // mtvsrwa
7511 {
7512 UChar XT = ifieldRegXT( theInstr );
7513 UChar rA_addr = ifieldRegA(theInstr);
7514 IRTemp rA = newTemp( Ity_I32 );
7515 DIP("mtvsrwa vsr%d,r%u\n", XT, rA_addr);
7516 /* XS = SX || S
7517 * For SX=0, mtvsrwa is treated as a Floating-Point
7518 * instruction in terms of resource availability.
7519 * For SX=1, mtvsrwa is treated as a Vector instruction in
7520 * terms of resource availability.
7521 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
7522 */
7523 if (mode64)
7524 assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) );
7525 else
7526 assign( rA, getIReg(rA_addr) );
7527
7528 putVSReg( XT, binop( Iop_64HLtoV128,
7529 unop( Iop_32Sto64, mkexpr( rA ) ),
7530 mkU64( 0 ) ) );
7531 break;
7532 }
7533
7534 case 0xF3: // mtvsrwz
7535 {
7536 UChar XT = ifieldRegXT( theInstr );
7537 UChar rA_addr = ifieldRegA(theInstr);
7538 IRTemp rA = newTemp( Ity_I32 );
7539 DIP("mtvsrwz vsr%d,r%u\n", rA_addr, XT);
7540 /* XS = SX || S
7541 * For SX=0, mtvsrwz is treated as a Floating-Point
7542 * instruction in terms of resource availability.
7543 * For SX=1, mtvsrwz is treated as a Vector instruction in
7544 * terms of resource availability.
7545 * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
7546 */
7547 if (mode64)
7548 assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) );
7549 else
7550 assign( rA, getIReg(rA_addr) );
7551
7552 putVSReg( XT, binop( Iop_64HLtoV128,
7553 binop( Iop_32HLto64, mkU32( 0 ), mkexpr ( rA ) ),
7554 mkU64( 0 ) ) );
7555 break;
7556 }
7557
7558 default:
7559 vex_printf("dis_proc_ctl(ppc)(opc2)\n");
7560 return False;
7561 }
7562 return True;
7563 }
7564
7565
7566 /*
7567 Cache Management Instructions
7568 */
dis_cache_manage(UInt theInstr,DisResult * dres,const VexArchInfo * guest_archinfo)7569 static Bool dis_cache_manage ( UInt theInstr,
7570 DisResult* dres,
7571 const VexArchInfo* guest_archinfo )
7572 {
7573 /* X-Form */
7574 UChar opc1 = ifieldOPC(theInstr);
7575 UChar b21to25 = ifieldRegDS(theInstr);
7576 UChar rA_addr = ifieldRegA(theInstr);
7577 UChar rB_addr = ifieldRegB(theInstr);
7578 UInt opc2 = ifieldOPClo10(theInstr);
7579 UChar b0 = ifieldBIT0(theInstr);
7580 UInt lineszB = guest_archinfo->ppc_icache_line_szB;
7581 Bool is_dcbzl = False;
7582
7583 IRType ty = mode64 ? Ity_I64 : Ity_I32;
7584
7585 // Check for valid hint values for dcbt and dcbtst as currently described in
7586 // ISA 2.07. If valid, then we simply set b21to25 to zero since we have no
7587 // means of modeling the hint anyway.
7588 if (opc1 == 0x1F && ((opc2 == 0x116) || (opc2 == 0xF6))) {
7589 if (b21to25 == 0x10 || b21to25 < 0x10)
7590 b21to25 = 0;
7591 }
7592 if (opc1 == 0x1F && opc2 == 0x116 && b21to25 == 0x11)
7593 b21to25 = 0;
7594
7595 if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz
7596 if (b21to25 == 1) {
7597 is_dcbzl = True;
7598 b21to25 = 0;
7599 if (!(guest_archinfo->ppc_dcbzl_szB)) {
7600 vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n");
7601 return False;
7602 }
7603 }
7604 }
7605
7606 if (opc1 != 0x1F || b0 != 0) {
7607 if (0) vex_printf("dis_cache_manage %d %d\n",
7608 opc1, b0);
7609 vex_printf("dis_cache_manage(ppc)(opc1|b0)\n");
7610 return False;
7611 }
7612
7613 /* stay sane .. */
7614 vassert(lineszB == 16 || lineszB == 32 || lineszB == 64 || lineszB == 128);
7615
7616 switch (opc2) {
7617 //zz case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380)
7618 //zz vassert(0); /* AWAITING TEST CASE */
7619 //zz DIP("dcba r%u,r%u\n", rA_addr, rB_addr);
7620 //zz if (0) vex_printf("vex ppc->IR: kludged dcba\n");
7621 //zz break;
7622
7623 case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382)
7624 DIP("dcbf r%u,r%u\n", rA_addr, rB_addr);
7625 /* nop as far as vex is concerned */
7626 break;
7627
7628 case 0x036: // dcbst (Data Cache Block Store, PPC32 p384)
7629 DIP("dcbst r%u,r%u\n", rA_addr, rB_addr);
7630 /* nop as far as vex is concerned */
7631 break;
7632
7633 case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385)
7634 DIP("dcbt r%u,r%u\n", rA_addr, rB_addr);
7635 /* nop as far as vex is concerned */
7636 break;
7637
7638 case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386)
7639 DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr);
7640 /* nop as far as vex is concerned */
7641 break;
7642
7643 case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387)
7644 // dcbzl (Data Cache Block Clear to Zero Long, bug#135264)
7645 /* Clear all bytes in cache block at (rA|0) + rB. */
7646 IRTemp EA = newTemp(ty);
7647 IRTemp addr = newTemp(ty);
7648 IRExpr* irx_addr;
7649 UInt i;
7650 UInt clearszB;
7651 if (is_dcbzl) {
7652 clearszB = guest_archinfo->ppc_dcbzl_szB;
7653 DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr);
7654 }
7655 else {
7656 clearszB = guest_archinfo->ppc_dcbz_szB;
7657 DIP("dcbz r%u,r%u\n", rA_addr, rB_addr);
7658 }
7659
7660 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
7661
7662 if (mode64) {
7663 /* Round EA down to the start of the containing block. */
7664 assign( addr, binop( Iop_And64,
7665 mkexpr(EA),
7666 mkU64( ~((ULong)clearszB-1) )) );
7667
7668 for (i = 0; i < clearszB / 8; i++) {
7669 irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) );
7670 store( irx_addr, mkU64(0) );
7671 }
7672 } else {
7673 /* Round EA down to the start of the containing block. */
7674 assign( addr, binop( Iop_And32,
7675 mkexpr(EA),
7676 mkU32( ~(clearszB-1) )) );
7677
7678 for (i = 0; i < clearszB / 4; i++) {
7679 irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) );
7680 store( irx_addr, mkU32(0) );
7681 }
7682 }
7683 break;
7684 }
7685
7686 case 0x3D6: {
7687 // icbi (Instruction Cache Block Invalidate, PPC32 p431)
7688 /* Invalidate all translations containing code from the cache
7689 block at (rA|0) + rB. */
7690 IRTemp EA = newTemp(ty);
7691 IRTemp addr = newTemp(ty);
7692 DIP("icbi r%u,r%u\n", rA_addr, rB_addr);
7693 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
7694
7695 /* Round EA down to the start of the containing block. */
7696 assign( addr, binop( mkSzOp(ty, Iop_And8),
7697 mkexpr(EA),
7698 mkSzImm(ty, ~(((ULong)lineszB)-1) )) );
7699 putGST( PPC_GST_CMSTART, mkexpr(addr) );
7700 putGST( PPC_GST_CMLEN, mkSzImm(ty, lineszB) );
7701
7702 /* be paranoid ... */
7703 stmt( IRStmt_MBE(Imbe_Fence) );
7704
7705 putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()));
7706 dres->jk_StopHere = Ijk_InvalICache;
7707 dres->whatNext = Dis_StopHere;
7708 break;
7709 }
7710
7711 default:
7712 vex_printf("dis_cache_manage(ppc)(opc2)\n");
7713 return False;
7714 }
7715 return True;
7716 }
7717
7718
7719 /*------------------------------------------------------------*/
7720 /*--- Floating Point Helpers ---*/
7721 /*------------------------------------------------------------*/
7722
7723 /* --------- Synthesise a 2-bit FPU rounding mode. --------- */
7724 /* Produces a value in 0 .. 3, which is encoded as per the type
7725 IRRoundingMode. PPCRoundingMode encoding is different to
7726 IRRoundingMode, so need to map it.
7727 */
get_IR_roundingmode(void)7728 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void )
7729 {
7730 /*
7731 rounding mode | PPC | IR
7732 ------------------------
7733 to nearest | 00 | 00
7734 to zero | 01 | 11
7735 to +infinity | 10 | 10
7736 to -infinity | 11 | 01
7737 */
7738 IRTemp rm_PPC32 = newTemp(Ity_I32);
7739 assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) );
7740
7741 // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
7742 return binop( Iop_Xor32,
7743 mkexpr(rm_PPC32),
7744 binop( Iop_And32,
7745 binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)),
7746 mkU32(2) ));
7747 }
7748
7749 /* The DFP IR rounding modes were chosen such that the existing PPC to IR
7750 * mapping would still work with the extended three bit DFP rounding
7751 * mode designator.
7752
7753 * rounding mode | PPC | IR
7754 * -----------------------------------------------
7755 * to nearest, ties to even | 000 | 000
7756 * to zero | 001 | 011
7757 * to +infinity | 010 | 010
7758 * to -infinity | 011 | 001
7759 * to nearest, ties away from 0 | 100 | 100
7760 * to nearest, ties toward 0 | 101 | 111
7761 * to away from 0 | 110 | 110
7762 * to prepare for shorter precision | 111 | 101
7763 */
get_IR_roundingmode_DFP(void)7764 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode_DFP( void )
7765 {
7766 IRTemp rm_PPC32 = newTemp( Ity_I32 );
7767 assign( rm_PPC32, getGST_masked_upper( PPC_GST_FPSCR, MASK_FPSCR_DRN ) );
7768
7769 // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
7770 return binop( Iop_Xor32,
7771 mkexpr( rm_PPC32 ),
7772 binop( Iop_And32,
7773 binop( Iop_Shl32, mkexpr( rm_PPC32 ), mkU8( 1 ) ),
7774 mkU32( 2 ) ) );
7775 }
7776
7777 #define NANmaskSingle 0x7F800000
7778 #define NANmaskDouble 0x7FF00000
7779
Check_NaN(IRExpr * value,IRExpr * Hi32Mask)7780 static IRExpr * Check_NaN( IRExpr * value, IRExpr * Hi32Mask )
7781 {
7782 IRTemp exp_zero = newTemp(Ity_I8);
7783 IRTemp frac_mask = newTemp(Ity_I32);
7784 IRTemp frac_not_zero = newTemp(Ity_I8);
7785
7786 /* Check if the result is QNAN or SNAN and not +infinity or -infinity.
7787 * The input value is always 64-bits, for single precision values, the
7788 * lower 32 bits must be zero.
7789 *
7790 * Single Pricision
7791 * [62:54] exponent field is equal to 0xFF for NAN and Infinity.
7792 * [53:32] fraction field is zero for Infinity and non-zero for NAN
7793 * [31:0] unused for single precision representation
7794 *
7795 * Double Pricision
7796 * [62:51] exponent field is equal to 0xFF for NAN and Infinity.
7797 * [50:0] fraction field is zero for Infinity and non-zero for NAN
7798 *
7799 * Returned result is a U32 value of 0xFFFFFFFF for NaN and 0 otherwise.
7800 */
7801 assign( frac_mask, unop( Iop_Not32,
7802 binop( Iop_Or32,
7803 mkU32( 0x80000000ULL ), Hi32Mask) ) );
7804
7805 assign( exp_zero,
7806 unop( Iop_1Sto8,
7807 binop( Iop_CmpEQ32,
7808 binop( Iop_And32,
7809 unop( Iop_64HIto32,
7810 unop( Iop_ReinterpF64asI64,
7811 value ) ),
7812 Hi32Mask ),
7813 Hi32Mask ) ) );
7814 assign( frac_not_zero,
7815 binop( Iop_Or8,
7816 unop( Iop_1Sto8,
7817 binop( Iop_CmpNE32,
7818 binop( Iop_And32,
7819 unop( Iop_64HIto32,
7820 unop( Iop_ReinterpF64asI64,
7821 value ) ),
7822 mkexpr( frac_mask ) ),
7823 mkU32( 0x0 ) ) ),
7824 unop( Iop_1Sto8,
7825 binop( Iop_CmpNE32,
7826 binop( Iop_And32,
7827 unop( Iop_64to32,
7828 unop( Iop_ReinterpF64asI64,
7829 value ) ),
7830 mkU32( 0xFFFFFFFF ) ),
7831 mkU32( 0x0 ) ) ) ) );
7832 return unop( Iop_8Sto32,
7833 binop( Iop_And8,
7834 mkexpr( exp_zero ),
7835 mkexpr( frac_not_zero ) ) );
7836 }
7837
Complement_non_NaN(IRExpr * value,IRExpr * nan_mask)7838 static IRExpr * Complement_non_NaN( IRExpr * value, IRExpr * nan_mask )
7839 {
7840 /* This function will only complement the 64-bit floating point value if it
7841 * is not Nan. NaN is not a signed value. Need to do computations using
7842 * 32-bit operands to ensure it will run in 32-bit mode.
7843 */
7844 return binop( Iop_32HLto64,
7845 binop( Iop_Or32,
7846 binop( Iop_And32,
7847 nan_mask,
7848 unop( Iop_64HIto32,
7849 unop( Iop_ReinterpF64asI64,
7850 value ) ) ),
7851 binop( Iop_And32,
7852 unop( Iop_Not32,
7853 nan_mask ),
7854 unop( Iop_64HIto32,
7855 unop( Iop_ReinterpF64asI64,
7856 unop( Iop_NegF64,
7857 value ) ) ) ) ),
7858 unop( Iop_64to32,
7859 unop( Iop_ReinterpF64asI64, value ) ) );
7860 }
7861
7862 /*------------------------------------------------------------*/
7863 /*--- Floating Point Instruction Translation ---*/
7864 /*------------------------------------------------------------*/
7865
7866 /*
7867 Floating Point Load Instructions
7868 */
dis_fp_load(UInt theInstr)7869 static Bool dis_fp_load ( UInt theInstr )
7870 {
7871 /* X-Form, D-Form */
7872 UChar opc1 = ifieldOPC(theInstr);
7873 UChar frD_addr = ifieldRegDS(theInstr);
7874 UChar rA_addr = ifieldRegA(theInstr);
7875 UChar rB_addr = ifieldRegB(theInstr);
7876 UInt opc2 = ifieldOPClo10(theInstr);
7877 UChar b0 = ifieldBIT0(theInstr);
7878 UInt uimm16 = ifieldUIMM16(theInstr);
7879
7880 Int simm16 = extend_s_16to32(uimm16);
7881 IRType ty = mode64 ? Ity_I64 : Ity_I32;
7882 IRTemp EA = newTemp(ty);
7883 IRTemp rA = newTemp(ty);
7884 IRTemp rB = newTemp(ty);
7885 IRTemp iHi = newTemp(Ity_I32);
7886 IRTemp iLo = newTemp(Ity_I32);
7887
7888 assign( rA, getIReg(rA_addr) );
7889 assign( rB, getIReg(rB_addr) );
7890
7891 /* These are completely straightforward from a rounding and status
7892 bits perspective: no rounding involved and no funny status or CR
7893 bits affected. */
7894
7895 switch (opc1) {
7896 case 0x30: // lfs (Load Float Single, PPC32 p441)
7897 DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
7898 assign( EA, ea_rAor0_simm(rA_addr, simm16) );
7899 putFReg( frD_addr,
7900 unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
7901 break;
7902
7903 case 0x31: // lfsu (Load Float Single, Update, PPC32 p442)
7904 if (rA_addr == 0)
7905 return False;
7906 DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
7907 assign( EA, ea_rA_simm(rA_addr, simm16) );
7908 putFReg( frD_addr,
7909 unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
7910 putIReg( rA_addr, mkexpr(EA) );
7911 break;
7912
7913 case 0x32: // lfd (Load Float Double, PPC32 p437)
7914 DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
7915 assign( EA, ea_rAor0_simm(rA_addr, simm16) );
7916 putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
7917 break;
7918
7919 case 0x33: // lfdu (Load Float Double, Update, PPC32 p438)
7920 if (rA_addr == 0)
7921 return False;
7922 DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
7923 assign( EA, ea_rA_simm(rA_addr, simm16) );
7924 putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
7925 putIReg( rA_addr, mkexpr(EA) );
7926 break;
7927
7928 case 0x1F:
7929 if (b0 != 0) {
7930 vex_printf("dis_fp_load(ppc)(instr,b0)\n");
7931 return False;
7932 }
7933
7934 switch(opc2) {
7935 case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444)
7936 DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7937 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
7938 putFReg( frD_addr, unop( Iop_F32toF64,
7939 load(Ity_F32, mkexpr(EA))) );
7940 break;
7941
7942 case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443)
7943 if (rA_addr == 0)
7944 return False;
7945 DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7946 assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
7947 putFReg( frD_addr,
7948 unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
7949 putIReg( rA_addr, mkexpr(EA) );
7950 break;
7951
7952 case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440)
7953 DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7954 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
7955 putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
7956 break;
7957
7958 case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439)
7959 if (rA_addr == 0)
7960 return False;
7961 DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7962 assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
7963 putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
7964 putIReg( rA_addr, mkexpr(EA) );
7965 break;
7966
7967 case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120)
7968 DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7969 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
7970 assign( iLo, load(Ity_I32, mkexpr(EA)) );
7971 assign( iHi, binop(Iop_Sub32,
7972 mkU32(0),
7973 binop(Iop_Shr32, mkexpr(iLo), mkU8(31))) );
7974 putFReg( frD_addr, unop(Iop_ReinterpI64asF64,
7975 binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) );
7976 break;
7977
7978 case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed
7979 {
7980 IRTemp dw = newTemp( Ity_I64 );
7981 DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7982 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
7983 assign( iLo, load(Ity_I32, mkexpr(EA)) );
7984 assign( dw, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( iLo ) ) );
7985 putFReg( frD_addr, unop( Iop_ReinterpI64asF64, mkexpr( dw ) ) );
7986 break;
7987 }
7988
7989 default:
7990 vex_printf("dis_fp_load(ppc)(opc2)\n");
7991 return False;
7992 }
7993 break;
7994
7995 default:
7996 vex_printf("dis_fp_load(ppc)(opc1)\n");
7997 return False;
7998 }
7999 return True;
8000 }
8001
8002
8003
8004 /*
8005 Floating Point Store Instructions
8006 */
dis_fp_store(UInt theInstr)8007 static Bool dis_fp_store ( UInt theInstr )
8008 {
8009 /* X-Form, D-Form */
8010 UChar opc1 = ifieldOPC(theInstr);
8011 UChar frS_addr = ifieldRegDS(theInstr);
8012 UChar rA_addr = ifieldRegA(theInstr);
8013 UChar rB_addr = ifieldRegB(theInstr);
8014 UInt opc2 = ifieldOPClo10(theInstr);
8015 UChar b0 = ifieldBIT0(theInstr);
8016 Int uimm16 = ifieldUIMM16(theInstr);
8017
8018 Int simm16 = extend_s_16to32(uimm16);
8019 IRTemp frS = newTemp(Ity_F64);
8020 IRType ty = mode64 ? Ity_I64 : Ity_I32;
8021 IRTemp EA = newTemp(ty);
8022 IRTemp rA = newTemp(ty);
8023 IRTemp rB = newTemp(ty);
8024
8025 assign( frS, getFReg(frS_addr) );
8026 assign( rA, getIReg(rA_addr) );
8027 assign( rB, getIReg(rB_addr) );
8028
8029 /* These are straightforward from a status bits perspective: no
8030 funny status or CR bits affected. For single precision stores,
8031 the values are truncated and denormalised (not rounded) to turn
8032 them into single precision values. */
8033
8034 switch (opc1) {
8035
8036 case 0x34: // stfs (Store Float Single, PPC32 p518)
8037 DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
8038 assign( EA, ea_rAor0_simm(rA_addr, simm16) );
8039 /* Use Iop_TruncF64asF32 to truncate and possible denormalise
8040 the value to be stored in the correct way, without any
8041 rounding. */
8042 store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
8043 break;
8044
8045 case 0x35: // stfsu (Store Float Single, Update, PPC32 p519)
8046 if (rA_addr == 0)
8047 return False;
8048 DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
8049 assign( EA, ea_rA_simm(rA_addr, simm16) );
8050 /* See comment for stfs */
8051 store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
8052 putIReg( rA_addr, mkexpr(EA) );
8053 break;
8054
8055 case 0x36: // stfd (Store Float Double, PPC32 p513)
8056 DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
8057 assign( EA, ea_rAor0_simm(rA_addr, simm16) );
8058 store( mkexpr(EA), mkexpr(frS) );
8059 break;
8060
8061 case 0x37: // stfdu (Store Float Double, Update, PPC32 p514)
8062 if (rA_addr == 0)
8063 return False;
8064 DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
8065 assign( EA, ea_rA_simm(rA_addr, simm16) );
8066 store( mkexpr(EA), mkexpr(frS) );
8067 putIReg( rA_addr, mkexpr(EA) );
8068 break;
8069
8070 case 0x1F:
8071 if (b0 != 0) {
8072 vex_printf("dis_fp_store(ppc)(instr,b0)\n");
8073 return False;
8074 }
8075 switch(opc2) {
8076 case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521)
8077 DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
8078 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
8079 /* See note for stfs */
8080 store( mkexpr(EA),
8081 unop(Iop_TruncF64asF32, mkexpr(frS)) );
8082 break;
8083
8084 case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520)
8085 if (rA_addr == 0)
8086 return False;
8087 DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
8088 assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
8089 /* See note for stfs */
8090 store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
8091 putIReg( rA_addr, mkexpr(EA) );
8092 break;
8093
8094 case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516)
8095 DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
8096 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
8097 store( mkexpr(EA), mkexpr(frS) );
8098 break;
8099
8100 case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515)
8101 if (rA_addr == 0)
8102 return False;
8103 DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
8104 assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
8105 store( mkexpr(EA), mkexpr(frS) );
8106 putIReg( rA_addr, mkexpr(EA) );
8107 break;
8108
8109 case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517)
8110 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
8111 DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
8112 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
8113 store( mkexpr(EA),
8114 unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) );
8115 break;
8116
8117 default:
8118 vex_printf("dis_fp_store(ppc)(opc2)\n");
8119 return False;
8120 }
8121 break;
8122
8123 default:
8124 vex_printf("dis_fp_store(ppc)(opc1)\n");
8125 return False;
8126 }
8127 return True;
8128 }
8129
8130
8131
8132 /*
8133 Floating Point Arith Instructions
8134 */
dis_fp_arith(UInt theInstr)8135 static Bool dis_fp_arith ( UInt theInstr )
8136 {
8137 /* A-Form */
8138 UChar opc1 = ifieldOPC(theInstr);
8139 UChar frD_addr = ifieldRegDS(theInstr);
8140 UChar frA_addr = ifieldRegA(theInstr);
8141 UChar frB_addr = ifieldRegB(theInstr);
8142 UChar frC_addr = ifieldRegC(theInstr);
8143 UChar opc2 = ifieldOPClo5(theInstr);
8144 UChar flag_rC = ifieldBIT0(theInstr);
8145
8146 IRTemp frD = newTemp(Ity_F64);
8147 IRTemp frA = newTemp(Ity_F64);
8148 IRTemp frB = newTemp(Ity_F64);
8149 IRTemp frC = newTemp(Ity_F64);
8150 IRExpr* rm = get_IR_roundingmode();
8151
8152 /* By default, we will examine the results of the operation and set
8153 fpscr[FPRF] accordingly. */
8154 Bool set_FPRF = True;
8155
8156 /* By default, if flag_RC is set, we will clear cr1 after the
8157 operation. In reality we should set cr1 to indicate the
8158 exception status of the operation, but since we're not
8159 simulating exceptions, the exception status will appear to be
8160 zero. Hence cr1 should be cleared if this is a . form insn. */
8161 Bool clear_CR1 = True;
8162
8163 assign( frA, getFReg(frA_addr));
8164 assign( frB, getFReg(frB_addr));
8165 assign( frC, getFReg(frC_addr));
8166
8167 switch (opc1) {
8168 case 0x3B:
8169 switch (opc2) {
8170 case 0x12: // fdivs (Floating Divide Single, PPC32 p407)
8171 if (frC_addr != 0)
8172 return False;
8173 DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8174 frD_addr, frA_addr, frB_addr);
8175 assign( frD, triop( Iop_DivF64r32,
8176 rm, mkexpr(frA), mkexpr(frB) ));
8177 break;
8178
8179 case 0x14: // fsubs (Floating Subtract Single, PPC32 p430)
8180 if (frC_addr != 0)
8181 return False;
8182 DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8183 frD_addr, frA_addr, frB_addr);
8184 assign( frD, triop( Iop_SubF64r32,
8185 rm, mkexpr(frA), mkexpr(frB) ));
8186 break;
8187
8188 case 0x15: // fadds (Floating Add Single, PPC32 p401)
8189 if (frC_addr != 0)
8190 return False;
8191 DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8192 frD_addr, frA_addr, frB_addr);
8193 assign( frD, triop( Iop_AddF64r32,
8194 rm, mkexpr(frA), mkexpr(frB) ));
8195 break;
8196
8197 case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428)
8198 // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
8199 if (frA_addr != 0 || frC_addr != 0)
8200 return False;
8201 DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? ".":"",
8202 frD_addr, frB_addr);
8203 // however illogically, on ppc970 this insn behaves identically
8204 // to fsqrt (double-precision). So use SqrtF64, not SqrtF64r32.
8205 assign( frD, binop( Iop_SqrtF64, rm, mkexpr(frB) ));
8206 break;
8207
8208 case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421)
8209 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
8210 if (frA_addr != 0 || frC_addr != 0)
8211 return False;
8212 DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"",
8213 frD_addr, frB_addr);
8214 { IRExpr* ieee_one
8215 = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
8216 assign( frD, triop( Iop_DivF64r32,
8217 rm,
8218 ieee_one, mkexpr(frB) ));
8219 }
8220 break;
8221
8222 case 0x19: // fmuls (Floating Multiply Single, PPC32 p414)
8223 if (frB_addr != 0)
8224 return False;
8225 DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8226 frD_addr, frA_addr, frC_addr);
8227 assign( frD, triop( Iop_MulF64r32,
8228 rm, mkexpr(frA), mkexpr(frC) ));
8229 break;
8230
8231 case 0x1A: // frsqrtes (Floating Recip SqRt Est Single)
8232 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
8233 // Undocumented instruction?
8234 if (frA_addr != 0 || frC_addr != 0)
8235 return False;
8236 DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"",
8237 frD_addr, frB_addr);
8238 assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) );
8239 break;
8240
8241 default:
8242 vex_printf("dis_fp_arith(ppc)(3B: opc2)\n");
8243 return False;
8244 }
8245 break;
8246
8247 case 0x3F:
8248 switch (opc2) {
8249 case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406)
8250 if (frC_addr != 0)
8251 return False;
8252 DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8253 frD_addr, frA_addr, frB_addr);
8254 assign( frD, triop(Iop_DivF64, rm, mkexpr(frA), mkexpr(frB)) );
8255 break;
8256
8257 case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429)
8258 if (frC_addr != 0)
8259 return False;
8260 DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8261 frD_addr, frA_addr, frB_addr);
8262 assign( frD, triop(Iop_SubF64, rm, mkexpr(frA), mkexpr(frB)) );
8263 break;
8264
8265 case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400)
8266 if (frC_addr != 0)
8267 return False;
8268 DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8269 frD_addr, frA_addr, frB_addr);
8270 assign( frD, triop(Iop_AddF64, rm, mkexpr(frA), mkexpr(frB)) );
8271 break;
8272
8273 case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427)
8274 // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
8275 if (frA_addr != 0 || frC_addr != 0)
8276 return False;
8277 DIP("fsqrt%s fr%u,fr%u\n", flag_rC ? ".":"",
8278 frD_addr, frB_addr);
8279 assign( frD, binop(Iop_SqrtF64, rm, mkexpr(frB)) );
8280 break;
8281
8282 case 0x17: { // fsel (Floating Select, PPC32 p426)
8283 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
8284 IRTemp cc = newTemp(Ity_I32);
8285 IRTemp cc_b0 = newTemp(Ity_I32);
8286
8287 DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8288 frD_addr, frA_addr, frC_addr, frB_addr);
8289
8290 // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40
8291 // => GT|EQ == (cc & 0x1 == 0)
8292 assign( cc, binop(Iop_CmpF64, mkexpr(frA),
8293 IRExpr_Const(IRConst_F64(0))) );
8294 assign( cc_b0, binop(Iop_And32, mkexpr(cc), mkU32(1)) );
8295
8296 // frD = (frA >= 0.0) ? frC : frB
8297 // = (cc_b0 == 0) ? frC : frB
8298 assign( frD,
8299 IRExpr_ITE(
8300 binop(Iop_CmpEQ32, mkexpr(cc_b0), mkU32(0)),
8301 mkexpr(frC),
8302 mkexpr(frB) ));
8303
8304 /* One of the rare ones which don't mess with FPRF */
8305 set_FPRF = False;
8306 break;
8307 }
8308
8309 case 0x18: // fre (Floating Reciprocal Estimate)
8310 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
8311 // Note: unclear whether this insn really exists or not
8312 // ppc970 doesn't have it, but POWER5 does
8313 if (frA_addr != 0 || frC_addr != 0)
8314 return False;
8315 DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"",
8316 frD_addr, frB_addr);
8317 { IRExpr* ieee_one
8318 = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
8319 assign( frD, triop( Iop_DivF64,
8320 rm,
8321 ieee_one, mkexpr(frB) ));
8322 }
8323 break;
8324
8325 case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413)
8326 if (frB_addr != 0)
8327 vex_printf("dis_fp_arith(ppc)(instr,fmul)\n");
8328 DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8329 frD_addr, frA_addr, frC_addr);
8330 assign( frD, triop(Iop_MulF64, rm, mkexpr(frA), mkexpr(frC)) );
8331 break;
8332
8333 case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424)
8334 // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
8335 if (frA_addr != 0 || frC_addr != 0)
8336 return False;
8337 DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"",
8338 frD_addr, frB_addr);
8339 assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) );
8340 break;
8341
8342 default:
8343 vex_printf("dis_fp_arith(ppc)(3F: opc2)\n");
8344 return False;
8345 }
8346 break;
8347
8348 default:
8349 vex_printf("dis_fp_arith(ppc)(opc1)\n");
8350 return False;
8351 }
8352
8353 putFReg( frD_addr, mkexpr(frD) );
8354
8355 if (set_FPRF) {
8356 // XXX XXX XXX FIXME
8357 // set FPRF from frD
8358 }
8359
8360 if (flag_rC && clear_CR1) {
8361 putCR321( 1, mkU8(0) );
8362 putCR0( 1, mkU8(0) );
8363 }
8364
8365 return True;
8366 }
8367
8368
8369
8370 /*
8371 Floating Point Mult-Add Instructions
8372 */
dis_fp_multadd(UInt theInstr)8373 static Bool dis_fp_multadd ( UInt theInstr )
8374 {
8375 /* A-Form */
8376 UChar opc1 = ifieldOPC(theInstr);
8377 UChar frD_addr = ifieldRegDS(theInstr);
8378 UChar frA_addr = ifieldRegA(theInstr);
8379 UChar frB_addr = ifieldRegB(theInstr);
8380 UChar frC_addr = ifieldRegC(theInstr);
8381 UChar opc2 = ifieldOPClo5(theInstr);
8382 UChar flag_rC = ifieldBIT0(theInstr);
8383
8384 IRTemp frD = newTemp(Ity_F64);
8385 IRTemp frA = newTemp(Ity_F64);
8386 IRTemp frB = newTemp(Ity_F64);
8387 IRTemp frC = newTemp(Ity_F64);
8388 IRTemp rmt = newTemp(Ity_I32);
8389 IRTemp tmp = newTemp(Ity_F64);
8390 IRTemp sign_tmp = newTemp(Ity_I64);
8391 IRTemp nan_mask = newTemp(Ity_I32);
8392 IRExpr* rm;
8393
8394 /* By default, we will examine the results of the operation and set
8395 fpscr[FPRF] accordingly. */
8396 Bool set_FPRF = True;
8397
8398 /* By default, if flag_RC is set, we will clear cr1 after the
8399 operation. In reality we should set cr1 to indicate the
8400 exception status of the operation, but since we're not
8401 simulating exceptions, the exception status will appear to be
8402 zero. Hence cr1 should be cleared if this is a . form insn. */
8403 Bool clear_CR1 = True;
8404
8405 /* Bind the rounding mode expression to a temp; there's no
8406 point in creating gratuitous CSEs, as we know we'll need
8407 to use it twice. */
8408 assign( rmt, get_IR_roundingmode() );
8409 rm = mkexpr(rmt);
8410
8411 assign( frA, getFReg(frA_addr));
8412 assign( frB, getFReg(frB_addr));
8413 assign( frC, getFReg(frC_addr));
8414
8415 /* The rounding in this is all a bit dodgy. The idea is to only do
8416 one rounding. That clearly isn't achieveable without dedicated
8417 four-input IR primops, although in the single precision case we
8418 can sort-of simulate it by doing the inner multiply in double
8419 precision.
8420
8421 In the negated cases, the negation happens after rounding. */
8422
8423 switch (opc1) {
8424 case 0x3B:
8425 switch (opc2) {
8426 case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412)
8427 DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8428 frD_addr, frA_addr, frC_addr, frB_addr);
8429 assign( frD, qop( Iop_MSubF64r32, rm,
8430 mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
8431 break;
8432
8433 case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409)
8434 DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8435 frD_addr, frA_addr, frC_addr, frB_addr);
8436 assign( frD, qop( Iop_MAddF64r32, rm,
8437 mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
8438 break;
8439
8440 case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420)
8441 case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418)
8442
8443 if (opc2 == 0x1E) {
8444 DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8445 frD_addr, frA_addr, frC_addr, frB_addr);
8446 assign( tmp, qop( Iop_MSubF64r32, rm,
8447 mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
8448 } else {
8449 DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8450 frD_addr, frA_addr, frC_addr, frB_addr);
8451 assign( tmp, qop( Iop_MAddF64r32, rm,
8452 mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
8453 }
8454
8455 assign( nan_mask, Check_NaN( mkexpr( tmp ),
8456 mkU32( NANmaskSingle ) ) );
8457 assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ),
8458 mkexpr( nan_mask ) ) );
8459 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) );
8460 break;
8461
8462 default:
8463 vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n");
8464 return False;
8465 }
8466 break;
8467
8468 case 0x3F:
8469 switch (opc2) {
8470 case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411)
8471 DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8472 frD_addr, frA_addr, frC_addr, frB_addr);
8473 assign( frD, qop( Iop_MSubF64, rm,
8474 mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
8475 break;
8476
8477 case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408)
8478 DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8479 frD_addr, frA_addr, frC_addr, frB_addr);
8480 assign( frD, qop( Iop_MAddF64, rm,
8481 mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
8482 break;
8483
8484 case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419)
8485 case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417)
8486
8487 if (opc2 == 0x1E) {
8488 DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8489 frD_addr, frA_addr, frC_addr, frB_addr);
8490 assign( tmp, qop( Iop_MSubF64, rm,
8491 mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
8492 } else {
8493 DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8494 frD_addr, frA_addr, frC_addr, frB_addr);
8495 assign( tmp, qop( Iop_MAddF64, rm,
8496 mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
8497 }
8498
8499 assign( nan_mask, Check_NaN( mkexpr( tmp ),
8500 mkU32( NANmaskDouble ) ) );
8501 assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ),
8502 mkexpr( nan_mask ) ) );
8503 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) );
8504 break;
8505
8506 default:
8507 vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n");
8508 return False;
8509 }
8510 break;
8511
8512 default:
8513 vex_printf("dis_fp_multadd(ppc)(opc1)\n");
8514 return False;
8515 }
8516
8517 putFReg( frD_addr, mkexpr(frD) );
8518
8519 if (set_FPRF) {
8520 // XXX XXX XXX FIXME
8521 // set FPRF from frD
8522 }
8523
8524 if (flag_rC && clear_CR1) {
8525 putCR321( 1, mkU8(0) );
8526 putCR0( 1, mkU8(0) );
8527 }
8528
8529 return True;
8530 }
8531
8532 /*
8533 * fe_flag is set to 1 if any of the following conditions occurs:
8534 * - The floating-point operand in register FRB is a Zero, a
8535 * NaN, an Infinity, or a negative value.
8536 * - e_b is less than or equal to: -970 for double precision; -103 for single precision
8537 * Otherwise fe_flag is set to 0.
8538 *
8539 * fg_flag is set to 1 if either of the following conditions occurs.
8540 * - The floating-point operand in register FRB is a Zero, an
8541 * Infinity, or a denormalized value.
8542 * Otherwise fg_flag is set to 0.
8543 *
8544 */
do_fp_tsqrt(IRTemp frB_Int,Bool sp,IRTemp * fe_flag_tmp,IRTemp * fg_flag_tmp)8545 static void do_fp_tsqrt(IRTemp frB_Int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
8546 {
8547 // The following temps are for holding intermediate results
8548 IRTemp e_b = newTemp(Ity_I32);
8549 IRExpr * fe_flag, * fg_flag;
8550 IRTemp frB_exp_shR = newTemp(Ity_I32);
8551 UInt bias = sp? 127 : 1023;
8552 IRExpr * frbNaN, * frbDenorm, * frBNeg;
8553 IRExpr * eb_LTE;
8554 IRTemp frbZero_tmp = newTemp(Ity_I1);
8555 IRTemp frbInf_tmp = newTemp(Ity_I1);
8556 *fe_flag_tmp = newTemp(Ity_I32);
8557 *fg_flag_tmp = newTemp(Ity_I32);
8558 assign( frB_exp_shR, fp_exp_part( frB_Int, sp ) );
8559 assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
8560
8561 ////////////////// fe_flag tests BEGIN //////////////////////
8562 /* We first do all tests that may result in setting fe_flag to '1'.
8563 * (NOTE: These tests are similar to those used for ftdiv. See do_fp_tdiv()
8564 * for details.)
8565 */
8566 frbNaN = sp ? is_NaN_32(frB_Int) : is_NaN(frB_Int);
8567 assign( frbInf_tmp, is_Inf(frB_Int, sp) );
8568 assign( frbZero_tmp, is_Zero(frB_Int, sp ) );
8569 {
8570 // Test_value = -970 for double precision
8571 UInt test_value = sp ? 0xffffff99 : 0xfffffc36;
8572 eb_LTE = binop( Iop_CmpLE32S, mkexpr( e_b ), mkU32( test_value ) );
8573 }
8574 frBNeg = binop( Iop_CmpEQ32,
8575 binop( Iop_Shr32,
8576 sp ? mkexpr( frB_Int ) : unop( Iop_64HIto32, mkexpr( frB_Int ) ),
8577 mkU8( 31 ) ),
8578 mkU32( 1 ) );
8579 ////////////////// fe_flag tests END //////////////////////
8580
8581 ////////////////// fg_flag tests BEGIN //////////////////////
8582 /*
8583 * The following tests were already performed above in the fe_flag
8584 * tests. So these conditions will result in both fe_ and fg_ flags
8585 * being set.
8586 * - Test if FRB is Zero
8587 * - Test if FRB is an Infinity
8588 */
8589
8590 /*
8591 * Test if FRB holds a denormalized value. A denormalized value is one where
8592 * the exp is 0 and the fraction is non-zero.
8593 */
8594 if (sp) {
8595 IRTemp frac_part = newTemp(Ity_I32);
8596 assign( frac_part, binop( Iop_And32, mkexpr(frB_Int), mkU32(0x007fffff)) );
8597 frbDenorm
8598 = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
8599 binop( Iop_CmpNE32, mkexpr( frac_part ), mkU32( 0 ) ) );
8600 } else {
8601 IRExpr * hi32, * low32, * fraction_is_nonzero;
8602 IRTemp frac_part = newTemp(Ity_I64);
8603
8604 assign( frac_part, FP_FRAC_PART(frB_Int) );
8605 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
8606 low32 = unop( Iop_64to32, mkexpr( frac_part ) );
8607 fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
8608 mkU32( 0 ) );
8609 frbDenorm
8610 = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
8611 fraction_is_nonzero );
8612 }
8613 ////////////////// fg_flag tests END //////////////////////
8614
8615 /////////////////////////
8616 fe_flag = mkOR1( mkexpr( frbZero_tmp ),
8617 mkOR1( frbNaN,
8618 mkOR1( mkexpr( frbInf_tmp ),
8619 mkOR1( frBNeg, eb_LTE ) ) ) );
8620
8621 fe_flag = unop(Iop_1Uto32, fe_flag);
8622
8623 fg_flag = mkOR1( mkexpr( frbZero_tmp ),
8624 mkOR1( mkexpr( frbInf_tmp ), frbDenorm ) );
8625 fg_flag = unop(Iop_1Uto32, fg_flag);
8626 assign (*fg_flag_tmp, fg_flag);
8627 assign (*fe_flag_tmp, fe_flag);
8628 }
8629 /*
8630 * fe_flag is set to 1 if any of the following conditions occurs:
8631 * - The double-precision floating-point operand in register FRA is a NaN or an
8632 * Infinity.
8633 * - The double-precision floating-point operand in register FRB is a Zero, a
8634 * NaN, or an Infinity.
8635 * - e_b is less than or equal to -1022.
8636 * - e_b is greater than or equal to 1021.
8637 * - The double-precision floating-point operand in register FRA is not a zero
8638 * and the difference, e_a - e_b, is greater than or equal to 1023.
8639 * - The double-precision floating-point operand in register FRA is not a zero
8640 * and the difference, e_a - e_b, is less than or equal to -1021.
8641 * - The double-precision floating-point operand in register FRA is not a zero
8642 * and e_a is less than or equal to -970
8643 * Otherwise fe_flag is set to 0.
8644 *
8645 * fg_flag is set to 1 if either of the following conditions occurs.
8646 * - The double-precision floating-point operand in register FRA is an Infinity.
8647 * - The double-precision floating-point operand in register FRB is a Zero, an
8648 * Infinity, or a denormalized value.
8649 * Otherwise fg_flag is set to 0.
8650 *
8651 */
_do_fp_tdiv(IRTemp frA_int,IRTemp frB_int,Bool sp,IRTemp * fe_flag_tmp,IRTemp * fg_flag_tmp)8652 static void _do_fp_tdiv(IRTemp frA_int, IRTemp frB_int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
8653 {
8654 // The following temps are for holding intermediate results
8655 IRTemp e_a = newTemp(Ity_I32);
8656 IRTemp e_b = newTemp(Ity_I32);
8657 IRTemp frA_exp_shR = newTemp(Ity_I32);
8658 IRTemp frB_exp_shR = newTemp(Ity_I32);
8659
8660 UInt bias = sp? 127 : 1023;
8661 *fe_flag_tmp = newTemp(Ity_I32);
8662 *fg_flag_tmp = newTemp(Ity_I32);
8663
8664 /* The following variables hold boolean results from tests
8665 * that are OR'ed together for setting the fe_ and fg_ flags.
8666 * For some cases, the booleans are used more than once, so
8667 * I make those IRTemp's instead of IRExpr's.
8668 */
8669 IRExpr * fraNaN, * frbNaN, * frbDenorm;
8670 IRExpr * eb_LTE, * eb_GTE, * ea_eb_GTE, * ea_eb_LTE, * ea_LTE;
8671 IRTemp fraInf_tmp = newTemp(Ity_I1);
8672 IRTemp frbZero_tmp = newTemp(Ity_I1);
8673 IRTemp frbInf_tmp = newTemp(Ity_I1);
8674 IRTemp fraNotZero_tmp = newTemp(Ity_I1);
8675
8676 /* The following are the flags that are set by OR'ing the results of
8677 * all the tests done for tdiv. These flags are the input to the specified CR.
8678 */
8679 IRExpr * fe_flag, * fg_flag;
8680
8681 // Create temps that will be used throughout the following tests.
8682 assign( frA_exp_shR, fp_exp_part( frA_int, sp ) );
8683 assign( frB_exp_shR, fp_exp_part( frB_int, sp ) );
8684 /* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */
8685 assign(e_a, binop( Iop_Sub32, mkexpr(frA_exp_shR), mkU32( bias ) ));
8686 assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
8687
8688
8689 ////////////////// fe_flag tests BEGIN //////////////////////
8690 /* We first do all tests that may result in setting fe_flag to '1'. */
8691
8692 /*
8693 * Test if the double-precision floating-point operand in register FRA is
8694 * a NaN:
8695 */
8696 fraNaN = sp ? is_NaN_32(frA_int) : is_NaN(frA_int);
8697 /*
8698 * Test if the double-precision floating-point operand in register FRA is
8699 * an Infinity.
8700 */
8701 assign(fraInf_tmp, is_Inf(frA_int, sp));
8702
8703 /*
8704 * Test if the double-precision floating-point operand in register FRB is
8705 * a NaN:
8706 */
8707 frbNaN = sp ? is_NaN_32(frB_int) : is_NaN(frB_int);
8708 /*
8709 * Test if the double-precision floating-point operand in register FRB is
8710 * an Infinity.
8711 */
8712 assign( frbInf_tmp, is_Inf(frB_int, sp) );
8713 /*
8714 * Test if the double-precision floating-point operand in register FRB is
8715 * a Zero.
8716 */
8717 assign( frbZero_tmp, is_Zero(frB_int, sp) );
8718
8719 /*
8720 * Test if e_b <= -1022 for double precision;
8721 * or e_b <= -126 for single precision
8722 */
8723 {
8724 UInt test_value = sp ? 0xffffff82 : 0xfffffc02;
8725 eb_LTE = binop(Iop_CmpLE32S, mkexpr(e_b), mkU32(test_value));
8726 }
8727
8728 /*
8729 * Test if e_b >= 1021 (i.e., 1021 < e_b) for double precision;
8730 * or e_b >= -125 (125 < e_b) for single precision
8731 */
8732 {
8733 Int test_value = sp ? 125 : 1021;
8734 eb_GTE = binop(Iop_CmpLT32S, mkU32(test_value), mkexpr(e_b));
8735 }
8736
8737 /*
8738 * Test if FRA != Zero and (e_a - e_b) >= bias
8739 */
8740 assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( frA_int, sp ) ) );
8741 ea_eb_GTE = mkAND1( mkexpr( fraNotZero_tmp ),
8742 binop( Iop_CmpLT32S, mkU32( bias ),
8743 binop( Iop_Sub32, mkexpr( e_a ),
8744 mkexpr( e_b ) ) ) );
8745
8746 /*
8747 * Test if FRA != Zero and (e_a - e_b) <= [-1021 (double precision) or -125 (single precision)]
8748 */
8749 {
8750 UInt test_value = sp ? 0xffffff83 : 0xfffffc03;
8751
8752 ea_eb_LTE = mkAND1( mkexpr( fraNotZero_tmp ),
8753 binop( Iop_CmpLE32S,
8754 binop( Iop_Sub32,
8755 mkexpr( e_a ),
8756 mkexpr( e_b ) ),
8757 mkU32( test_value ) ) );
8758 }
8759
8760 /*
8761 * Test if FRA != Zero and e_a <= [-970 (double precision) or -103 (single precision)]
8762 */
8763 {
8764 UInt test_value = 0xfffffc36; //Int test_value = -970;
8765
8766 ea_LTE = mkAND1( mkexpr( fraNotZero_tmp ), binop( Iop_CmpLE32S,
8767 mkexpr( e_a ),
8768 mkU32( test_value ) ) );
8769 }
8770 ////////////////// fe_flag tests END //////////////////////
8771
8772 ////////////////// fg_flag tests BEGIN //////////////////////
8773 /*
8774 * The following tests were already performed above in the fe_flag
8775 * tests. So these conditions will result in both fe_ and fg_ flags
8776 * being set.
8777 * - Test if FRA is an Infinity
8778 * - Test if FRB ix Zero
8779 * - Test if FRB is an Infinity
8780 */
8781
8782 /*
8783 * Test if FRB holds a denormalized value. A denormalized value is one where
8784 * the exp is 0 and the fraction is non-zero.
8785 */
8786 {
8787 IRExpr * fraction_is_nonzero;
8788
8789 if (sp) {
8790 fraction_is_nonzero = binop( Iop_CmpNE32, FP_FRAC_PART32(frB_int),
8791 mkU32( 0 ) );
8792 } else {
8793 IRExpr * hi32, * low32;
8794 IRTemp frac_part = newTemp(Ity_I64);
8795 assign( frac_part, FP_FRAC_PART(frB_int) );
8796
8797 hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
8798 low32 = unop( Iop_64to32, mkexpr( frac_part ) );
8799 fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
8800 mkU32( 0 ) );
8801 }
8802 frbDenorm = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ),
8803 mkU32( 0x0 ) ), fraction_is_nonzero );
8804
8805 }
8806 ////////////////// fg_flag tests END //////////////////////
8807
8808 fe_flag
8809 = mkOR1(
8810 fraNaN,
8811 mkOR1(
8812 mkexpr( fraInf_tmp ),
8813 mkOR1(
8814 mkexpr( frbZero_tmp ),
8815 mkOR1(
8816 frbNaN,
8817 mkOR1(
8818 mkexpr( frbInf_tmp ),
8819 mkOR1( eb_LTE,
8820 mkOR1( eb_GTE,
8821 mkOR1( ea_eb_GTE,
8822 mkOR1( ea_eb_LTE,
8823 ea_LTE ) ) ) ) ) ) ) ) );
8824
8825 fe_flag = unop(Iop_1Uto32, fe_flag);
8826
8827 fg_flag = mkOR1( mkexpr( fraInf_tmp ), mkOR1( mkexpr( frbZero_tmp ),
8828 mkOR1( mkexpr( frbInf_tmp ),
8829 frbDenorm ) ) );
8830 fg_flag = unop(Iop_1Uto32, fg_flag);
8831 assign(*fe_flag_tmp, fe_flag);
8832 assign(*fg_flag_tmp, fg_flag);
8833 }
8834
8835 /* See description for _do_fp_tdiv() above. */
do_fp_tdiv(IRTemp frA_int,IRTemp frB_int)8836 static IRExpr * do_fp_tdiv(IRTemp frA_int, IRTemp frB_int)
8837 {
8838 IRTemp fe_flag, fg_flag;
8839 /////////////////////////
8840 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
8841 * where fl_flag == 1 on ppc64.
8842 */
8843 IRExpr * fl_flag = unop(Iop_Not32, mkU32(0xFFFFFE));
8844 fe_flag = fg_flag = IRTemp_INVALID;
8845 _do_fp_tdiv(frA_int, frB_int, False/*not single precision*/, &fe_flag, &fg_flag);
8846 return binop( Iop_Or32,
8847 binop( Iop_Or32,
8848 binop( Iop_Shl32, fl_flag, mkU8( 3 ) ),
8849 binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
8850 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) );
8851 }
8852
dis_fp_tests(UInt theInstr)8853 static Bool dis_fp_tests ( UInt theInstr )
8854 {
8855 UChar opc1 = ifieldOPC(theInstr);
8856 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) );
8857 UChar frB_addr = ifieldRegB(theInstr);
8858 UChar b0 = ifieldBIT0(theInstr);
8859 UInt opc2 = ifieldOPClo10(theInstr);
8860 IRTemp frB_I64 = newTemp(Ity_I64);
8861
8862 if (opc1 != 0x3F || b0 != 0 ){
8863 vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
8864 return False;
8865 }
8866 assign( frB_I64, unop( Iop_ReinterpF64asI64, getFReg( frB_addr ) ) );
8867
8868 switch (opc2) {
8869 case 0x080: // ftdiv
8870 {
8871 UChar frA_addr = ifieldRegA(theInstr);
8872 IRTemp frA_I64 = newTemp(Ity_I64);
8873 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) );
8874 if (b21to22 != 0 ) {
8875 vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
8876 return False;
8877 }
8878
8879 assign( frA_I64, unop( Iop_ReinterpF64asI64, getFReg( frA_addr ) ) );
8880 putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
8881
8882 DIP("ftdiv crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
8883 break;
8884 }
8885 case 0x0A0: // ftsqrt
8886 {
8887 IRTemp flags = newTemp(Ity_I32);
8888 IRTemp fe_flag, fg_flag;
8889 fe_flag = fg_flag = IRTemp_INVALID;
8890 UChar b18to22 = toUChar( IFIELD( theInstr, 18, 5 ) );
8891 if ( b18to22 != 0) {
8892 vex_printf("dis_fp_tests(ppc)(ftsqrt)\n");
8893 return False;
8894 }
8895 DIP("ftsqrt crf%d,fr%u\n", crfD, frB_addr);
8896 do_fp_tsqrt(frB_I64, False /* not single precision*/, &fe_flag, &fg_flag);
8897 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
8898 * where fl_flag == 1 on ppc64.
8899 */
8900 assign( flags,
8901 binop( Iop_Or32,
8902 binop( Iop_Or32, mkU32( 8 ), // fl_flag
8903 binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
8904 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
8905 putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
8906 break;
8907 }
8908
8909 default:
8910 vex_printf("dis_fp_tests(ppc)(opc2)\n");
8911 return False;
8912
8913 }
8914 return True;
8915 }
8916
8917 /*
8918 Floating Point Compare Instructions
8919 */
dis_fp_cmp(UInt theInstr)8920 static Bool dis_fp_cmp ( UInt theInstr )
8921 {
8922 /* X-Form */
8923 UChar opc1 = ifieldOPC(theInstr);
8924 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) );
8925 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) );
8926 UChar frA_addr = ifieldRegA(theInstr);
8927 UChar frB_addr = ifieldRegB(theInstr);
8928 UInt opc2 = ifieldOPClo10(theInstr);
8929 UChar b0 = ifieldBIT0(theInstr);
8930
8931 IRTemp ccIR = newTemp(Ity_I32);
8932 IRTemp ccPPC32 = newTemp(Ity_I32);
8933
8934 IRTemp frA = newTemp(Ity_F64);
8935 IRTemp frB = newTemp(Ity_F64);
8936
8937 if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) {
8938 vex_printf("dis_fp_cmp(ppc)(instr)\n");
8939 return False;
8940 }
8941
8942 assign( frA, getFReg(frA_addr));
8943 assign( frB, getFReg(frB_addr));
8944
8945 assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) );
8946
8947 /* Map compare result from IR to PPC32 */
8948 /*
8949 FP cmp result | PPC | IR
8950 --------------------------
8951 UN | 0x1 | 0x45
8952 EQ | 0x2 | 0x40
8953 GT | 0x4 | 0x00
8954 LT | 0x8 | 0x01
8955 */
8956
8957 // ccPPC32 = Shl(1, (~(ccIR>>5) & 2)
8958 // | ((ccIR ^ (ccIR>>6)) & 1)
8959 assign(
8960 ccPPC32,
8961 binop(
8962 Iop_Shl32,
8963 mkU32(1),
8964 unop(
8965 Iop_32to8,
8966 binop(
8967 Iop_Or32,
8968 binop(
8969 Iop_And32,
8970 unop(
8971 Iop_Not32,
8972 binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))
8973 ),
8974 mkU32(2)
8975 ),
8976 binop(
8977 Iop_And32,
8978 binop(
8979 Iop_Xor32,
8980 mkexpr(ccIR),
8981 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))
8982 ),
8983 mkU32(1)
8984 )
8985 )
8986 )
8987 )
8988 );
8989
8990 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
8991
8992 /* CAB: TODO?: Support writing cc to FPSCR->FPCC ?
8993 putGST_field( PPC_GST_FPSCR, mkexpr(ccPPC32), 4 );
8994 */
8995 // XXX XXX XXX FIXME
8996 // Also write the result into FPRF (it's not entirely clear how)
8997
8998 /* Note: Differences between fcmpu and fcmpo are only in exception
8999 flag settings, which aren't supported anyway. */
9000 switch (opc2) {
9001 case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403)
9002 DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
9003 break;
9004 case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402)
9005 DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
9006 break;
9007 default:
9008 vex_printf("dis_fp_cmp(ppc)(opc2)\n");
9009 return False;
9010 }
9011 return True;
9012 }
9013
9014
9015
9016 /*
9017 Floating Point Rounding/Conversion Instructions
9018 */
dis_fp_round(UInt theInstr)9019 static Bool dis_fp_round ( UInt theInstr )
9020 {
9021 /* X-Form */
9022 UChar opc1 = ifieldOPC(theInstr);
9023 UChar b16to20 = ifieldRegA(theInstr);
9024 UChar frD_addr = ifieldRegDS(theInstr);
9025 UChar frB_addr = ifieldRegB(theInstr);
9026 UInt opc2 = ifieldOPClo10(theInstr);
9027 UChar flag_rC = ifieldBIT0(theInstr);
9028
9029 IRTemp frD = newTemp(Ity_F64);
9030 IRTemp frB = newTemp(Ity_F64);
9031 IRTemp r_tmp32 = newTemp(Ity_I32);
9032 IRTemp r_tmp64 = newTemp(Ity_I64);
9033 IRExpr* rm = get_IR_roundingmode();
9034
9035 /* By default, we will examine the results of the operation and set
9036 fpscr[FPRF] accordingly. */
9037 Bool set_FPRF = True;
9038
9039 /* By default, if flag_RC is set, we will clear cr1 after the
9040 operation. In reality we should set cr1 to indicate the
9041 exception status of the operation, but since we're not
9042 simulating exceptions, the exception status will appear to be
9043 zero. Hence cr1 should be cleared if this is a . form insn. */
9044 Bool clear_CR1 = True;
9045 if ((!(opc1 == 0x3F || opc1 == 0x3B)) || b16to20 != 0) {
9046 vex_printf("dis_fp_round(ppc)(instr)\n");
9047 return False;
9048 }
9049
9050 assign( frB, getFReg(frB_addr));
9051 if (opc1 == 0x3B) {
9052 /* The fcfid[u]s instructions (from ISA 2.06) are a bit odd because
9053 * they're very similar to the other instructions handled here, but have
9054 * a different primary opcode.
9055 */
9056 switch (opc2) {
9057 case 0x34E: // fcfids (Float convert from signed DWord to single precision)
9058 DIP("fcfids%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9059 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
9060 assign( frD, binop( Iop_RoundF64toF32, rm, binop( Iop_I64StoF64, rm,
9061 mkexpr( r_tmp64 ) ) ) );
9062 goto putFR;
9063
9064 case 0x3Ce: // fcfidus (Float convert from unsigned DWord to single precision)
9065 DIP("fcfidus%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9066 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
9067 assign( frD, unop( Iop_F32toF64, binop( Iop_I64UtoF32, rm, mkexpr( r_tmp64 ) ) ) );
9068 goto putFR;
9069 }
9070 }
9071
9072
9073 switch (opc2) {
9074 case 0x00C: // frsp (Float Round to Single, PPC32 p423)
9075 DIP("frsp%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9076 assign( frD, binop( Iop_RoundF64toF32, rm, mkexpr(frB) ));
9077 break;
9078
9079 case 0x00E: // fctiw (Float Conv to Int, PPC32 p404)
9080 DIP("fctiw%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9081 assign( r_tmp32,
9082 binop(Iop_F64toI32S, rm, mkexpr(frB)) );
9083 assign( frD, unop( Iop_ReinterpI64asF64,
9084 unop( Iop_32Uto64, mkexpr(r_tmp32))));
9085 /* FPRF is undefined after fctiw. Leave unchanged. */
9086 set_FPRF = False;
9087 break;
9088
9089 case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405)
9090 DIP("fctiwz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9091 assign( r_tmp32,
9092 binop(Iop_F64toI32S, mkU32(Irrm_ZERO), mkexpr(frB) ));
9093 assign( frD, unop( Iop_ReinterpI64asF64,
9094 unop( Iop_32Uto64, mkexpr(r_tmp32))));
9095 /* FPRF is undefined after fctiwz. Leave unchanged. */
9096 set_FPRF = False;
9097 break;
9098
9099 case 0x08F: case 0x08E: // fctiwu[z]
9100 DIP("fctiwu%s%s fr%u,fr%u\n", opc2 == 0x08F ? "z" : "",
9101 flag_rC ? ".":"", frD_addr, frB_addr);
9102 assign( r_tmp32,
9103 binop( Iop_F64toI32U,
9104 opc2 == 0x08F ? mkU32( Irrm_ZERO ) : rm,
9105 mkexpr( frB ) ) );
9106 assign( frD, unop( Iop_ReinterpI64asF64,
9107 unop( Iop_32Uto64, mkexpr(r_tmp32))));
9108 /* FPRF is undefined after fctiwz. Leave unchanged. */
9109 set_FPRF = False;
9110 break;
9111
9112
9113 case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437)
9114 DIP("fctid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9115 assign( r_tmp64,
9116 binop(Iop_F64toI64S, rm, mkexpr(frB)) );
9117 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
9118 /* FPRF is undefined after fctid. Leave unchanged. */
9119 set_FPRF = False;
9120 break;
9121
9122 case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437)
9123 DIP("fctidz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9124 assign( r_tmp64,
9125 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
9126 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
9127 /* FPRF is undefined after fctidz. Leave unchanged. */
9128 set_FPRF = False;
9129 break;
9130
9131 case 0x3AE: case 0x3AF: // fctidu[z] (Float Conv to Int DWord Unsigned [Round to Zero])
9132 {
9133 DIP("fctidu%s%s fr%u,fr%u\n", opc2 == 0x3AE ? "" : "z",
9134 flag_rC ? ".":"", frD_addr, frB_addr);
9135 assign( r_tmp64,
9136 binop(Iop_F64toI64U, opc2 == 0x3AE ? rm : mkU32(Irrm_ZERO), mkexpr(frB)) );
9137 assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
9138 /* FPRF is undefined after fctidz. Leave unchanged. */
9139 set_FPRF = False;
9140 break;
9141 }
9142 case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434)
9143 DIP("fcfid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9144 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
9145 assign( frD,
9146 binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) );
9147 break;
9148
9149 case 0x3CE: // fcfidu (Float convert from unsigned DWord)
9150 DIP("fcfidu%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9151 assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
9152 assign( frD, binop( Iop_I64UtoF64, rm, mkexpr( r_tmp64 ) ) );
9153 break;
9154
9155 case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim
9156 switch(opc2) {
9157 case 0x188: // frin (Floating Round to Integer Nearest)
9158 DIP("frin%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9159 assign( r_tmp64,
9160 binop(Iop_F64toI64S, mkU32(Irrm_NEAREST), mkexpr(frB)) );
9161 break;
9162 case 0x1A8: // friz (Floating Round to Integer Toward Zero)
9163 DIP("friz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9164 assign( r_tmp64,
9165 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
9166 break;
9167 case 0x1C8: // frip (Floating Round to Integer Plus)
9168 DIP("frip%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9169 assign( r_tmp64,
9170 binop(Iop_F64toI64S, mkU32(Irrm_PosINF), mkexpr(frB)) );
9171 break;
9172 case 0x1E8: // frim (Floating Round to Integer Minus)
9173 DIP("frim%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9174 assign( r_tmp64,
9175 binop(Iop_F64toI64S, mkU32(Irrm_NegINF), mkexpr(frB)) );
9176 break;
9177 }
9178
9179 /* don't use the rounded integer if frB is outside -9e18..9e18 */
9180 /* F64 has only log10(2**52) significant digits anyway */
9181 /* need to preserve sign of zero */
9182 /* frD = (fabs(frB) > 9e18) ? frB :
9183 (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64 */
9184 assign(frD, IRExpr_ITE(
9185 binop(Iop_CmpNE8,
9186 unop(Iop_32to8,
9187 binop(Iop_CmpF64,
9188 IRExpr_Const(IRConst_F64(9e18)),
9189 unop(Iop_AbsF64, mkexpr(frB)))),
9190 mkU8(0)),
9191 mkexpr(frB),
9192 IRExpr_ITE(
9193 binop(Iop_CmpNE32,
9194 binop(Iop_Shr32,
9195 unop(Iop_64HIto32,
9196 unop(Iop_ReinterpF64asI64,
9197 mkexpr(frB))),
9198 mkU8(31)),
9199 mkU32(0)),
9200 unop(Iop_NegF64,
9201 unop( Iop_AbsF64,
9202 binop(Iop_I64StoF64, mkU32(0),
9203 mkexpr(r_tmp64)) )),
9204 binop(Iop_I64StoF64, mkU32(0), mkexpr(r_tmp64) )
9205 )
9206 ));
9207 break;
9208
9209 default:
9210 vex_printf("dis_fp_round(ppc)(opc2)\n");
9211 return False;
9212 }
9213 putFR:
9214 putFReg( frD_addr, mkexpr(frD) );
9215
9216 if (set_FPRF) {
9217 // XXX XXX XXX FIXME
9218 // set FPRF from frD
9219 }
9220
9221 if (flag_rC && clear_CR1) {
9222 putCR321( 1, mkU8(0) );
9223 putCR0( 1, mkU8(0) );
9224 }
9225
9226 return True;
9227 }
9228
9229 /*
9230 Floating Point Pair Instructions
9231 */
dis_fp_pair(UInt theInstr)9232 static Bool dis_fp_pair ( UInt theInstr )
9233 {
9234 /* X-Form/DS-Form */
9235 UChar opc1 = ifieldOPC(theInstr);
9236 UChar frT_hi_addr = ifieldRegDS(theInstr);
9237 UChar frT_lo_addr = frT_hi_addr + 1;
9238 UChar rA_addr = ifieldRegA(theInstr);
9239 UChar rB_addr = ifieldRegB(theInstr);
9240 UInt uimm16 = ifieldUIMM16(theInstr);
9241 Int simm16 = extend_s_16to32(uimm16);
9242 UInt opc2 = ifieldOPClo10(theInstr);
9243 IRType ty = mode64 ? Ity_I64 : Ity_I32;
9244 IRTemp EA_hi = newTemp(ty);
9245 IRTemp EA_lo = newTemp(ty);
9246 IRTemp frT_hi = newTemp(Ity_F64);
9247 IRTemp frT_lo = newTemp(Ity_F64);
9248 UChar b0 = ifieldBIT0(theInstr);
9249 Bool is_load = 0;
9250
9251 if ((frT_hi_addr %2) != 0) {
9252 vex_printf("dis_fp_pair(ppc) : odd frT register\n");
9253 return False;
9254 }
9255
9256 switch (opc1) {
9257 case 0x1F: // register offset
9258 switch(opc2) {
9259 case 0x317: // lfdpx (FP Load Double Pair X-form, ISA 2.05 p125)
9260 DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
9261 is_load = 1;
9262 break;
9263 case 0x397: // stfdpx (FP STORE Double Pair X-form, ISA 2.05 p125)
9264 DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
9265 break;
9266 default:
9267 vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n");
9268 return False;
9269 }
9270
9271 if (b0 != 0) {
9272 vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n");
9273 return False;
9274 }
9275 assign( EA_hi, ea_rAor0_idxd( rA_addr, rB_addr ) );
9276 break;
9277 case 0x39: // lfdp (FP Load Double Pair DS-form, ISA 2.05 p125)
9278 DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
9279 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) );
9280 is_load = 1;
9281 break;
9282 case 0x3d: // stfdp (FP Store Double Pair DS-form, ISA 2.05 p125)
9283 DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
9284 assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) );
9285 break;
9286 default: // immediate offset
9287 vex_printf("dis_fp_pair(ppc)(instr)\n");
9288 return False;
9289 }
9290
9291 if (mode64)
9292 assign( EA_lo, binop(Iop_Add64, mkexpr(EA_hi), mkU64(8)) );
9293 else
9294 assign( EA_lo, binop(Iop_Add32, mkexpr(EA_hi), mkU32(8)) );
9295
9296 assign( frT_hi, getFReg(frT_hi_addr) );
9297 assign( frT_lo, getFReg(frT_lo_addr) );
9298
9299 if (is_load) {
9300 putFReg( frT_hi_addr, load(Ity_F64, mkexpr(EA_hi)) );
9301 putFReg( frT_lo_addr, load(Ity_F64, mkexpr(EA_lo)) );
9302 } else {
9303 store( mkexpr(EA_hi), mkexpr(frT_hi) );
9304 store( mkexpr(EA_lo), mkexpr(frT_lo) );
9305 }
9306
9307 return True;
9308 }
9309
9310
9311 /*
9312 Floating Point Merge Instructions
9313 */
dis_fp_merge(UInt theInstr)9314 static Bool dis_fp_merge ( UInt theInstr )
9315 {
9316 /* X-Form */
9317 UInt opc2 = ifieldOPClo10(theInstr);
9318 UChar frD_addr = ifieldRegDS(theInstr);
9319 UChar frA_addr = ifieldRegA(theInstr);
9320 UChar frB_addr = ifieldRegB(theInstr);
9321
9322 IRTemp frD = newTemp(Ity_F64);
9323 IRTemp frA = newTemp(Ity_F64);
9324 IRTemp frB = newTemp(Ity_F64);
9325
9326 assign( frA, getFReg(frA_addr));
9327 assign( frB, getFReg(frB_addr));
9328
9329 switch (opc2) {
9330 case 0x3c6: // fmrgew floating merge even word
9331 DIP("fmrgew fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr);
9332
9333 assign( frD, unop( Iop_ReinterpI64asF64,
9334 binop( Iop_32HLto64,
9335 unop( Iop_64HIto32,
9336 unop( Iop_ReinterpF64asI64,
9337 mkexpr(frA) ) ),
9338 unop( Iop_64HIto32,
9339 unop( Iop_ReinterpF64asI64,
9340 mkexpr(frB) ) ) ) ) );
9341 break;
9342
9343 case 0x346: // fmrgow floating merge odd word
9344 DIP("fmrgow fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr);
9345
9346 assign( frD, unop( Iop_ReinterpI64asF64,
9347 binop( Iop_32HLto64,
9348 unop( Iop_64to32,
9349 unop( Iop_ReinterpF64asI64,
9350 mkexpr(frA) ) ),
9351 unop( Iop_64to32,
9352 unop( Iop_ReinterpF64asI64,
9353 mkexpr(frB) ) ) ) ) );
9354 break;
9355
9356 default:
9357 vex_printf("dis_fp_merge(ppc)(opc2)\n");
9358 return False;
9359 }
9360
9361 putFReg( frD_addr, mkexpr(frD) );
9362 return True;
9363 }
9364
9365 /*
9366 Floating Point Move Instructions
9367 */
dis_fp_move(UInt theInstr)9368 static Bool dis_fp_move ( UInt theInstr )
9369 {
9370 /* X-Form */
9371 UChar opc1 = ifieldOPC(theInstr);
9372 UChar frD_addr = ifieldRegDS(theInstr);
9373 UChar frA_addr = ifieldRegA(theInstr);
9374 UChar frB_addr = ifieldRegB(theInstr);
9375 UInt opc2 = ifieldOPClo10(theInstr);
9376 UChar flag_rC = ifieldBIT0(theInstr);
9377
9378 IRTemp frD = newTemp(Ity_F64);
9379 IRTemp frB = newTemp(Ity_F64);
9380 IRTemp itmpB = newTemp(Ity_F64);
9381 IRTemp frA;
9382 IRTemp signA;
9383 IRTemp hiD;
9384
9385 if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) {
9386 vex_printf("dis_fp_move(ppc)(instr)\n");
9387 return False;
9388 }
9389
9390 assign( frB, getFReg(frB_addr));
9391
9392 switch (opc2) {
9393 case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126)
9394 DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frA_addr,
9395 frB_addr);
9396 signA = newTemp(Ity_I32);
9397 hiD = newTemp(Ity_I32);
9398 itmpB = newTemp(Ity_I64);
9399 frA = newTemp(Ity_F64);
9400 assign( frA, getFReg(frA_addr) );
9401
9402 /* get A's sign bit */
9403 assign(signA, binop(Iop_And32,
9404 unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64,
9405 mkexpr(frA))),
9406 mkU32(0x80000000)) );
9407
9408 assign( itmpB, unop(Iop_ReinterpF64asI64, mkexpr(frB)) );
9409
9410 /* mask off B's sign bit and or in A's sign bit */
9411 assign(hiD, binop(Iop_Or32,
9412 binop(Iop_And32,
9413 unop(Iop_64HIto32,
9414 mkexpr(itmpB)), /* frB's high 32 bits */
9415 mkU32(0x7fffffff)),
9416 mkexpr(signA)) );
9417
9418 /* combine hiD/loB into frD */
9419 assign( frD, unop(Iop_ReinterpI64asF64,
9420 binop(Iop_32HLto64,
9421 mkexpr(hiD),
9422 unop(Iop_64to32,
9423 mkexpr(itmpB)))) ); /* frB's low 32 bits */
9424 break;
9425
9426 case 0x028: // fneg (Floating Negate, PPC32 p416)
9427 DIP("fneg%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9428 assign( frD, unop( Iop_NegF64, mkexpr(frB) ));
9429 break;
9430
9431 case 0x048: // fmr (Floating Move Register, PPC32 p410)
9432 DIP("fmr%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9433 assign( frD, mkexpr(frB) );
9434 break;
9435
9436 case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415)
9437 DIP("fnabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9438 assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) )));
9439 break;
9440
9441 case 0x108: // fabs (Floating Absolute Value, PPC32 p399)
9442 DIP("fabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9443 assign( frD, unop( Iop_AbsF64, mkexpr(frB) ));
9444 break;
9445
9446 default:
9447 vex_printf("dis_fp_move(ppc)(opc2)\n");
9448 return False;
9449 }
9450
9451 putFReg( frD_addr, mkexpr(frD) );
9452
9453 /* None of these change FPRF. cr1 is set in the usual way though,
9454 if flag_rC is set. */
9455
9456 if (flag_rC) {
9457 putCR321( 1, mkU8(0) );
9458 putCR0( 1, mkU8(0) );
9459 }
9460
9461 return True;
9462 }
9463
9464
9465
9466 /*
9467 Floating Point Status/Control Register Instructions
9468 */
dis_fp_scr(UInt theInstr,Bool GX_level)9469 static Bool dis_fp_scr ( UInt theInstr, Bool GX_level )
9470 {
9471 /* Many forms - see each switch case */
9472 UChar opc1 = ifieldOPC(theInstr);
9473 UInt opc2 = ifieldOPClo10(theInstr);
9474 UChar flag_rC = ifieldBIT0(theInstr);
9475
9476 if (opc1 != 0x3F) {
9477 vex_printf("dis_fp_scr(ppc)(instr)\n");
9478 return False;
9479 }
9480
9481 switch (opc2) {
9482 case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479)
9483 // Bit crbD of the FPSCR is set.
9484 UChar crbD = ifieldRegDS(theInstr);
9485 UInt b11to20 = IFIELD(theInstr, 11, 10);
9486
9487 if (b11to20 != 0) {
9488 vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n");
9489 return False;
9490 }
9491 DIP("mtfsb1%s crb%d \n", flag_rC ? ".":"", crbD);
9492 putGST_masked( PPC_GST_FPSCR, mkU64( 1 <<( 31 - crbD ) ),
9493 1ULL << ( 31 - crbD ) );
9494 break;
9495 }
9496
9497 case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465)
9498 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) );
9499 UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) );
9500 UChar crfS = toUChar( IFIELD( theInstr, 18, 3 ) );
9501 UChar b11to17 = toUChar( IFIELD( theInstr, 11, 7 ) );
9502 IRTemp tmp = newTemp(Ity_I32);
9503 IRExpr* fpscr_all;
9504 if (b21to22 != 0 || b11to17 != 0 || flag_rC != 0) {
9505 vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n");
9506 return False;
9507 }
9508 DIP("mcrfs crf%d,crf%d\n", crfD, crfS);
9509 vassert(crfD < 8);
9510 vassert(crfS < 8);
9511 fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
9512 assign( tmp, binop(Iop_And32,
9513 binop(Iop_Shr32,fpscr_all,mkU8(4 * (7-crfS))),
9514 mkU32(0xF)) );
9515 putGST_field( PPC_GST_CR, mkexpr(tmp), crfD );
9516 break;
9517 }
9518
9519 case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478)
9520 // Bit crbD of the FPSCR is cleared.
9521 UChar crbD = ifieldRegDS(theInstr);
9522 UInt b11to20 = IFIELD(theInstr, 11, 10);
9523
9524 if (b11to20 != 0) {
9525 vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n");
9526 return False;
9527 }
9528 DIP("mtfsb0%s crb%d\n", flag_rC ? ".":"", crbD);
9529 putGST_masked( PPC_GST_FPSCR, mkU64( 0 ), 1ULL << ( 31 - crbD ) );
9530 break;
9531 }
9532
9533 case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481)
9534 UInt crfD = IFIELD( theInstr, 23, 3 );
9535 UChar b16to22 = toUChar( IFIELD( theInstr, 16, 7 ) );
9536 UChar IMM = toUChar( IFIELD( theInstr, 12, 4 ) );
9537 UChar b11 = toUChar( IFIELD( theInstr, 11, 1 ) );
9538 UChar Wbit;
9539
9540 if (b16to22 != 0 || b11 != 0) {
9541 vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n");
9542 return False;
9543 }
9544 DIP("mtfsfi%s crf%u,%d\n", flag_rC ? ".":"", crfD, IMM);
9545 if (GX_level) {
9546 /* This implies that Decimal Floating Point is supported, and the
9547 * FPSCR must be managed as a 64-bit register.
9548 */
9549 Wbit = toUChar( IFIELD(theInstr, 16, 1) );
9550 } else {
9551 Wbit = 0;
9552 }
9553 crfD = crfD + (8 * (1 - Wbit) );
9554 putGST_field( PPC_GST_FPSCR, mkU32( IMM ), crfD );
9555 break;
9556 }
9557
9558 case 0x247: { // mffs (Move from FPSCR, PPC32 p468)
9559 UChar frD_addr = ifieldRegDS(theInstr);
9560 UInt b11to20 = IFIELD(theInstr, 11, 10);
9561 IRExpr* fpscr_lower = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
9562 IRExpr* fpscr_upper = getGST_masked_upper( PPC_GST_FPSCR,
9563 MASK_FPSCR_DRN );
9564
9565 if (b11to20 != 0) {
9566 vex_printf("dis_fp_scr(ppc)(instr,mffs)\n");
9567 return False;
9568 }
9569 DIP("mffs%s fr%u\n", flag_rC ? ".":"", frD_addr);
9570 putFReg( frD_addr,
9571 unop( Iop_ReinterpI64asF64,
9572 binop( Iop_32HLto64, fpscr_upper, fpscr_lower ) ) );
9573 break;
9574 }
9575
9576 case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480)
9577 UChar b25 = toUChar( IFIELD(theInstr, 25, 1) );
9578 UChar FM = toUChar( IFIELD(theInstr, 17, 8) );
9579 UChar frB_addr = ifieldRegB(theInstr);
9580 IRTemp frB = newTemp(Ity_F64);
9581 IRTemp rB_64 = newTemp( Ity_I64 );
9582 Int i;
9583 ULong mask;
9584 UChar Wbit;
9585 #define BFP_MASK_SEED 0x3000000000000000ULL
9586 #define DFP_MASK_SEED 0x7000000000000000ULL
9587
9588 if (GX_level) {
9589 /* This implies that Decimal Floating Point is supported, and the
9590 * FPSCR must be managed as a 64-bit register.
9591 */
9592 Wbit = toUChar( IFIELD(theInstr, 16, 1) );
9593 } else {
9594 Wbit = 0;
9595 }
9596
9597 if (b25 == 1) {
9598 /* new 64 bit move variant for power 6. If L field (bit 25) is
9599 * a one do a full 64 bit move. Note, the FPSCR is not really
9600 * properly modeled. This instruciton only changes the value of
9601 * the rounding mode. The HW exception bits do not get set in
9602 * the simulator. 1/12/09
9603 */
9604 DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC ? ".":"", FM, frB_addr);
9605 mask = 0xFF;
9606
9607 } else {
9608 DIP("mtfsf%s %d,fr%u\n", flag_rC ? ".":"", FM, frB_addr);
9609 // Build 32bit mask from FM:
9610 mask = 0;
9611 for (i=0; i<8; i++) {
9612 if ((FM & (1<<(7-i))) == 1) {
9613 /* FPSCR field k is set to the contents of the corresponding
9614 * field of register FRB, where k = i+8x(1-W). In the Power
9615 * ISA, register field numbering is from left to right, so field
9616 * 15 is the least significant field in a 64-bit register. To
9617 * generate the mask, we set all the appropriate rounding mode
9618 * bits in the highest order nibble (field 0) and shift right
9619 * 'k x nibble length'.
9620 */
9621 if (Wbit)
9622 mask |= DFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) );
9623 else
9624 mask |= BFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) );
9625 }
9626 }
9627 }
9628 assign( frB, getFReg(frB_addr));
9629 assign( rB_64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
9630 putGST_masked( PPC_GST_FPSCR, mkexpr( rB_64 ), mask );
9631 break;
9632 }
9633
9634 default:
9635 vex_printf("dis_fp_scr(ppc)(opc2)\n");
9636 return False;
9637 }
9638 return True;
9639 }
9640
9641 /*------------------------------------------------------------*/
9642 /*--- Decimal Floating Point (DFP) Helper functions ---*/
9643 /*------------------------------------------------------------*/
9644 #define DFP_LONG 1
9645 #define DFP_EXTND 2
9646 #define DFP_LONG_BIAS 398
9647 #define DFP_LONG_ENCODED_FIELD_MASK 0x1F00
9648 #define DFP_EXTND_BIAS 6176
9649 #define DFP_EXTND_ENCODED_FIELD_MASK 0x1F000
9650 #define DFP_LONG_EXP_MSK 0XFF
9651 #define DFP_EXTND_EXP_MSK 0XFFF
9652
9653 #define DFP_G_FIELD_LONG_MASK 0x7FFC0000 // upper 32-bits only
9654 #define DFP_LONG_GFIELD_RT_SHIFT (63 - 13 - 32) // adj for upper 32-bits
9655 #define DFP_G_FIELD_EXTND_MASK 0x7FFFC000 // upper 32-bits only
9656 #define DFP_EXTND_GFIELD_RT_SHIFT (63 - 17 - 32) //adj for upper 32 bits
9657 #define DFP_T_FIELD_LONG_MASK 0x3FFFF // mask for upper 32-bits
9658 #define DFP_T_FIELD_EXTND_MASK 0x03FFFF // mask for upper 32-bits
9659 #define DFP_LONG_EXP_MAX 369 // biased max
9660 #define DFP_LONG_EXP_MIN 0 // biased min
9661 #define DFP_EXTND_EXP_MAX 6111 // biased max
9662 #define DFP_EXTND_EXP_MIN 0 // biased min
9663 #define DFP_LONG_MAX_SIG_DIGITS 16
9664 #define DFP_EXTND_MAX_SIG_DIGITS 34
9665 #define MAX_DIGITS_IN_STRING 8
9666
9667
9668 #define AND(x, y) binop( Iop_And32, x, y )
9669 #define AND4(w, x, y, z) AND( AND( w, x ), AND( y, z ) )
9670 #define OR(x, y) binop( Iop_Or32, x, y )
9671 #define OR3(x, y, z) OR( x, OR( y, z ) )
9672 #define OR4(w, x, y, z) OR( OR( w, x ), OR( y, z ) )
9673 #define NOT(x) unop( Iop_1Uto32, unop( Iop_Not1, unop( Iop_32to1, mkexpr( x ) ) ) )
9674
9675 #define SHL(value, by) binop( Iop_Shl32, value, mkU8( by ) )
9676 #define SHR(value, by) binop( Iop_Shr32, value, mkU8( by ) )
9677
9678 #define BITS5(_b4,_b3,_b2,_b1,_b0) \
9679 (((_b4) << 4) | ((_b3) << 3) | ((_b2) << 2) | \
9680 ((_b1) << 1) | ((_b0) << 0))
9681
Gfield_encoding(IRExpr * lmexp,IRExpr * lmd32)9682 static IRExpr * Gfield_encoding( IRExpr * lmexp, IRExpr * lmd32 )
9683 {
9684 IRTemp lmd_07_mask = newTemp( Ity_I32 );
9685 IRTemp lmd_8_mask = newTemp( Ity_I32 );
9686 IRTemp lmd_9_mask = newTemp( Ity_I32 );
9687 IRTemp lmexp_00_mask = newTemp( Ity_I32 );
9688 IRTemp lmexp_01_mask = newTemp( Ity_I32 );
9689 IRTemp lmexp_10_mask = newTemp( Ity_I32 );
9690 IRTemp lmd_07_val = newTemp( Ity_I32 );
9691 IRTemp lmd_8_val = newTemp( Ity_I32 );
9692 IRTemp lmd_9_val = newTemp( Ity_I32 );
9693
9694 /* The encodig is as follows:
9695 * lmd - left most digit
9696 * lme - left most 2-bits of the exponent
9697 *
9698 * lmd
9699 * 0 - 7 (lmexp << 3) | lmd
9700 * 8 0b11000 (24 decimal) if lme=0b00;
9701 * 0b11010 (26 decimal) if lme=0b01;
9702 * 0b11100 (28 decimal) if lme=0b10;
9703 * 9 0b11001 (25 decimal) if lme=0b00;
9704 * 0b11011 (27 decimal) if lme=0b01;
9705 * 0b11101 (29 decimal) if lme=0b10;
9706 */
9707
9708 /* Generate the masks for each condition */
9709 assign( lmd_07_mask,
9710 unop( Iop_1Sto32, binop( Iop_CmpLE32U, lmd32, mkU32( 7 ) ) ) );
9711 assign( lmd_8_mask,
9712 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 8 ) ) ) );
9713 assign( lmd_9_mask,
9714 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 9 ) ) ) );
9715 assign( lmexp_00_mask,
9716 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 0 ) ) ) );
9717 assign( lmexp_01_mask,
9718 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 1 ) ) ) );
9719 assign( lmexp_10_mask,
9720 unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 2 ) ) ) );
9721
9722 /* Generate the values for each LMD condition, assuming the condition
9723 * is TRUE.
9724 */
9725 assign( lmd_07_val,
9726 binop( Iop_Or32, binop( Iop_Shl32, lmexp, mkU8( 3 ) ), lmd32 ) );
9727 assign( lmd_8_val,
9728 binop( Iop_Or32,
9729 binop( Iop_Or32,
9730 binop( Iop_And32,
9731 mkexpr( lmexp_00_mask ),
9732 mkU32( 24 ) ),
9733 binop( Iop_And32,
9734 mkexpr( lmexp_01_mask ),
9735 mkU32( 26 ) ) ),
9736 binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 28 ) ) ) );
9737 assign( lmd_9_val,
9738 binop( Iop_Or32,
9739 binop( Iop_Or32,
9740 binop( Iop_And32,
9741 mkexpr( lmexp_00_mask ),
9742 mkU32( 25 ) ),
9743 binop( Iop_And32,
9744 mkexpr( lmexp_01_mask ),
9745 mkU32( 27 ) ) ),
9746 binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 29 ) ) ) );
9747
9748 /* generate the result from the possible LMD values */
9749 return binop( Iop_Or32,
9750 binop( Iop_Or32,
9751 binop( Iop_And32,
9752 mkexpr( lmd_07_mask ),
9753 mkexpr( lmd_07_val ) ),
9754 binop( Iop_And32,
9755 mkexpr( lmd_8_mask ),
9756 mkexpr( lmd_8_val ) ) ),
9757 binop( Iop_And32, mkexpr( lmd_9_mask ), mkexpr( lmd_9_val ) ) );
9758 }
9759
Get_lmd(IRTemp * lmd,IRExpr * gfield_0_4)9760 static void Get_lmd( IRTemp * lmd, IRExpr * gfield_0_4 )
9761 {
9762 /* Extract the exponent and the left most digit of the mantissa
9763 * from the G field bits [0:4].
9764 */
9765 IRTemp lmd_07_mask = newTemp( Ity_I32 );
9766 IRTemp lmd_8_00_mask = newTemp( Ity_I32 );
9767 IRTemp lmd_8_01_mask = newTemp( Ity_I32 );
9768 IRTemp lmd_8_10_mask = newTemp( Ity_I32 );
9769 IRTemp lmd_9_00_mask = newTemp( Ity_I32 );
9770 IRTemp lmd_9_01_mask = newTemp( Ity_I32 );
9771 IRTemp lmd_9_10_mask = newTemp( Ity_I32 );
9772
9773 IRTemp lmd_07_val = newTemp( Ity_I32 );
9774 IRTemp lmd_8_val = newTemp( Ity_I32 );
9775 IRTemp lmd_9_val = newTemp( Ity_I32 );
9776
9777 /* The left most digit (LMD) encoding is as follows:
9778 * lmd
9779 * 0 - 7 (lmexp << 3) | lmd
9780 * 8 0b11000 (24 decimal) if lme=0b00;
9781 * 0b11010 (26 decimal) if lme=0b01;
9782 * 0b11100 (28 decimal) if lme=0b10
9783 * 9 0b11001 (25 decimal) if lme=0b00;
9784 * 0b11011 (27 decimal) if lme=0b01;
9785 * 0b11101 (29 decimal) if lme=0b10;
9786 */
9787
9788 /* Generate the masks for each condition of LMD and exponent bits */
9789 assign( lmd_07_mask,
9790 unop( Iop_1Sto32, binop( Iop_CmpLE32U,
9791 gfield_0_4,
9792 mkU32( BITS5(1,0,1,1,1) ) ) ) );
9793 assign( lmd_8_00_mask,
9794 unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9795 gfield_0_4,
9796 mkU32( BITS5(1,1,0,0,0) ) ) ) );
9797 assign( lmd_8_01_mask,
9798 unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9799 gfield_0_4,
9800 mkU32( BITS5(1,1,0,1,0) ) ) ) );
9801 assign( lmd_8_10_mask,
9802 unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9803 gfield_0_4,
9804 mkU32( BITS5(1,1,1,0,0) ) ) ) );
9805 assign( lmd_9_00_mask,
9806 unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9807 gfield_0_4,
9808 mkU32( BITS5(1,1,0,0,1) ) ) ) );
9809 assign( lmd_9_01_mask,
9810 unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9811 gfield_0_4,
9812 mkU32( BITS5(1,1,0,1,1) ) ) ) );
9813 assign( lmd_9_10_mask,
9814 unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9815 gfield_0_4,
9816 mkU32( BITS5(1,1,1,0,1) ) ) ) );
9817
9818 /* Generate the values for each LMD condition, assuming the condition
9819 * is TRUE.
9820 */
9821 assign( lmd_07_val, binop( Iop_And32, gfield_0_4, mkU32( 0x7 ) ) );
9822 assign( lmd_8_val, mkU32( 0x8 ) );
9823 assign( lmd_9_val, mkU32( 0x9 ) );
9824
9825 assign( *lmd,
9826 OR( OR3 ( AND( mkexpr( lmd_07_mask ), mkexpr( lmd_07_val ) ),
9827 AND( mkexpr( lmd_8_00_mask ), mkexpr( lmd_8_val ) ),
9828 AND( mkexpr( lmd_8_01_mask ), mkexpr( lmd_8_val ) )),
9829 OR4( AND( mkexpr( lmd_8_10_mask ), mkexpr( lmd_8_val ) ),
9830 AND( mkexpr( lmd_9_00_mask ), mkexpr( lmd_9_val ) ),
9831 AND( mkexpr( lmd_9_01_mask ), mkexpr( lmd_9_val ) ),
9832 AND( mkexpr( lmd_9_10_mask ), mkexpr( lmd_9_val ) )
9833 ) ) );
9834 }
9835
9836 #define DIGIT1_SHR 4 // shift digit 1 to bottom 4 bits
9837 #define DIGIT2_SHR 8 // shift digit 2 to bottom 4 bits
9838 #define DIGIT3_SHR 12
9839 #define DIGIT4_SHR 16
9840 #define DIGIT5_SHR 20
9841 #define DIGIT6_SHR 24
9842 #define DIGIT7_SHR 28
9843
bcd_digit_inval(IRExpr * bcd_u,IRExpr * bcd_l)9844 static IRExpr * bcd_digit_inval( IRExpr * bcd_u, IRExpr * bcd_l )
9845 {
9846 /* 60-bit BCD string stored in two 32-bit values. Check that each,
9847 * digit is a valid BCD number, i.e. less then 9.
9848 */
9849 IRTemp valid = newTemp( Ity_I32 );
9850
9851 assign( valid,
9852 AND4( AND4 ( unop( Iop_1Sto32,
9853 binop( Iop_CmpLE32U,
9854 binop( Iop_And32,
9855 bcd_l,
9856 mkU32 ( 0xF ) ),
9857 mkU32( 0x9 ) ) ),
9858 unop( Iop_1Sto32,
9859 binop( Iop_CmpLE32U,
9860 binop( Iop_And32,
9861 binop( Iop_Shr32,
9862 bcd_l,
9863 mkU8 ( DIGIT1_SHR ) ),
9864 mkU32 ( 0xF ) ),
9865 mkU32( 0x9 ) ) ),
9866 unop( Iop_1Sto32,
9867 binop( Iop_CmpLE32U,
9868 binop( Iop_And32,
9869 binop( Iop_Shr32,
9870 bcd_l,
9871 mkU8 ( DIGIT2_SHR ) ),
9872 mkU32 ( 0xF ) ),
9873 mkU32( 0x9 ) ) ),
9874 unop( Iop_1Sto32,
9875 binop( Iop_CmpLE32U,
9876 binop( Iop_And32,
9877 binop( Iop_Shr32,
9878 bcd_l,
9879 mkU8 ( DIGIT3_SHR ) ),
9880 mkU32 ( 0xF ) ),
9881 mkU32( 0x9 ) ) ) ),
9882 AND4 ( unop( Iop_1Sto32,
9883 binop( Iop_CmpLE32U,
9884 binop( Iop_And32,
9885 binop( Iop_Shr32,
9886 bcd_l,
9887 mkU8 ( DIGIT4_SHR ) ),
9888 mkU32 ( 0xF ) ),
9889 mkU32( 0x9 ) ) ),
9890 unop( Iop_1Sto32,
9891 binop( Iop_CmpLE32U,
9892 binop( Iop_And32,
9893 binop( Iop_Shr32,
9894 bcd_l,
9895 mkU8 ( DIGIT5_SHR ) ),
9896 mkU32 ( 0xF ) ),
9897 mkU32( 0x9 ) ) ),
9898 unop( Iop_1Sto32,
9899 binop( Iop_CmpLE32U,
9900 binop( Iop_And32,
9901 binop( Iop_Shr32,
9902 bcd_l,
9903 mkU8 ( DIGIT6_SHR ) ),
9904 mkU32 ( 0xF ) ),
9905 mkU32( 0x9 ) ) ),
9906 unop( Iop_1Sto32,
9907 binop( Iop_CmpLE32U,
9908 binop( Iop_And32,
9909 binop( Iop_Shr32,
9910 bcd_l,
9911 mkU8 ( DIGIT7_SHR ) ),
9912 mkU32 ( 0xF ) ),
9913 mkU32( 0x9 ) ) ) ),
9914 AND4( unop( Iop_1Sto32,
9915 binop( Iop_CmpLE32U,
9916 binop( Iop_And32,
9917 bcd_u,
9918 mkU32 ( 0xF ) ),
9919 mkU32( 0x9 ) ) ),
9920 unop( Iop_1Sto32,
9921 binop( Iop_CmpLE32U,
9922 binop( Iop_And32,
9923 binop( Iop_Shr32,
9924 bcd_u,
9925 mkU8 ( DIGIT1_SHR ) ),
9926 mkU32 ( 0xF ) ),
9927 mkU32( 0x9 ) ) ),
9928 unop( Iop_1Sto32,
9929 binop( Iop_CmpLE32U,
9930 binop( Iop_And32,
9931 binop( Iop_Shr32,
9932 bcd_u,
9933 mkU8 ( DIGIT2_SHR ) ),
9934 mkU32 ( 0xF ) ),
9935 mkU32( 0x9 ) ) ),
9936 unop( Iop_1Sto32,
9937 binop( Iop_CmpLE32U,
9938 binop( Iop_And32,
9939 binop( Iop_Shr32,
9940 bcd_u,
9941 mkU8 ( DIGIT3_SHR ) ),
9942 mkU32 ( 0xF ) ),
9943 mkU32( 0x9 ) ) ) ),
9944 AND4( unop( Iop_1Sto32,
9945 binop( Iop_CmpLE32U,
9946 binop( Iop_And32,
9947 binop( Iop_Shr32,
9948 bcd_u,
9949 mkU8 ( DIGIT4_SHR ) ),
9950 mkU32 ( 0xF ) ),
9951 mkU32( 0x9 ) ) ),
9952 unop( Iop_1Sto32,
9953 binop( Iop_CmpLE32U,
9954 binop( Iop_And32,
9955 binop( Iop_Shr32,
9956 bcd_u,
9957 mkU8 ( DIGIT5_SHR ) ),
9958 mkU32 ( 0xF ) ),
9959 mkU32( 0x9 ) ) ),
9960 unop( Iop_1Sto32,
9961 binop( Iop_CmpLE32U,
9962 binop( Iop_And32,
9963 binop( Iop_Shr32,
9964 bcd_u,
9965 mkU8 ( DIGIT6_SHR ) ),
9966 mkU32 ( 0xF ) ),
9967 mkU32( 0x9 ) ) ),
9968 unop( Iop_1Sto32,
9969 binop( Iop_CmpLE32U,
9970 binop( Iop_And32,
9971 binop( Iop_Shr32,
9972 bcd_u,
9973 mkU8 ( DIGIT7_SHR ) ),
9974 mkU32 ( 0xF ) ),
9975 mkU32( 0x9 ) ) ) ) ) );
9976
9977 return unop( Iop_Not32, mkexpr( valid ) );
9978 }
9979 #undef DIGIT1_SHR
9980 #undef DIGIT2_SHR
9981 #undef DIGIT3_SHR
9982 #undef DIGIT4_SHR
9983 #undef DIGIT5_SHR
9984 #undef DIGIT6_SHR
9985 #undef DIGIT7_SHR
9986
Generate_neg_sign_mask(IRExpr * sign)9987 static IRExpr * Generate_neg_sign_mask( IRExpr * sign )
9988 {
9989 return binop( Iop_Or32,
9990 unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xB ) ) ),
9991 unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xD ) ) )
9992 );
9993 }
9994
Generate_pos_sign_mask(IRExpr * sign)9995 static IRExpr * Generate_pos_sign_mask( IRExpr * sign )
9996 {
9997 return binop( Iop_Or32,
9998 binop( Iop_Or32,
9999 unop( Iop_1Sto32,
10000 binop( Iop_CmpEQ32, sign, mkU32( 0xA ) ) ),
10001 unop( Iop_1Sto32,
10002 binop( Iop_CmpEQ32, sign, mkU32( 0xC ) ) ) ),
10003 binop( Iop_Or32,
10004 unop( Iop_1Sto32,
10005 binop( Iop_CmpEQ32, sign, mkU32( 0xE ) ) ),
10006 unop( Iop_1Sto32,
10007 binop( Iop_CmpEQ32, sign, mkU32( 0xF ) ) ) ) );
10008 }
10009
Generate_sign_bit(IRExpr * pos_sign_mask,IRExpr * neg_sign_mask)10010 static IRExpr * Generate_sign_bit( IRExpr * pos_sign_mask,
10011 IRExpr * neg_sign_mask )
10012 {
10013 return binop( Iop_Or32,
10014 binop( Iop_And32, neg_sign_mask, mkU32( 0x80000000 ) ),
10015 binop( Iop_And32, pos_sign_mask, mkU32( 0x00000000 ) ) );
10016 }
10017
Generate_inv_mask(IRExpr * invalid_bcd_mask,IRExpr * pos_sign_mask,IRExpr * neg_sign_mask)10018 static IRExpr * Generate_inv_mask( IRExpr * invalid_bcd_mask,
10019 IRExpr * pos_sign_mask,
10020 IRExpr * neg_sign_mask )
10021 /* first argument is all 1's if the BCD string had an invalid digit in it. */
10022 {
10023 return binop( Iop_Or32,
10024 invalid_bcd_mask,
10025 unop( Iop_1Sto32,
10026 binop( Iop_CmpEQ32,
10027 binop( Iop_Or32, pos_sign_mask, neg_sign_mask ),
10028 mkU32( 0x0 ) ) ) );
10029 }
10030
Generate_132_bit_bcd_string(IRExpr * frBI64_hi,IRExpr * frBI64_lo,IRTemp * top_12_l,IRTemp * mid_60_u,IRTemp * mid_60_l,IRTemp * low_60_u,IRTemp * low_60_l)10031 static void Generate_132_bit_bcd_string( IRExpr * frBI64_hi, IRExpr * frBI64_lo,
10032 IRTemp * top_12_l, IRTemp * mid_60_u,
10033 IRTemp * mid_60_l, IRTemp * low_60_u,
10034 IRTemp * low_60_l)
10035 {
10036 IRTemp tmplow60 = newTemp( Ity_I64 );
10037 IRTemp tmpmid60 = newTemp( Ity_I64 );
10038 IRTemp tmptop12 = newTemp( Ity_I64 );
10039 IRTemp low_50 = newTemp( Ity_I64 );
10040 IRTemp mid_50 = newTemp( Ity_I64 );
10041 IRTemp top_10 = newTemp( Ity_I64 );
10042 IRTemp top_12_u = newTemp( Ity_I32 ); // only needed for a dummy arg
10043
10044 /* Convert the 110-bit densely packed BCD string to a 128-bit BCD string */
10045
10046 /* low_50[49:0] = ((frBI64_lo[49:32] << 14) | frBI64_lo[31:0]) */
10047 assign( low_50,
10048 binop( Iop_32HLto64,
10049 binop( Iop_And32,
10050 unop( Iop_64HIto32, frBI64_lo ),
10051 mkU32( 0x3FFFF ) ),
10052 unop( Iop_64to32, frBI64_lo ) ) );
10053
10054 /* Convert the 50 bit densely packed BCD string to a 60 bit
10055 * BCD string.
10056 */
10057 assign( tmplow60, unop( Iop_DPBtoBCD, mkexpr( low_50 ) ) );
10058 assign( *low_60_u, unop( Iop_64HIto32, mkexpr( tmplow60 ) ) );
10059 assign( *low_60_l, unop( Iop_64to32, mkexpr( tmplow60 ) ) );
10060
10061 /* mid_50[49:0] = ((frBI64_hi[35:32] << 14) | frBI64_hi[31:18]) |
10062 * ((frBI64_hi[17:0] << 14) | frBI64_lo[63:50])
10063 */
10064 assign( mid_50,
10065 binop( Iop_32HLto64,
10066 binop( Iop_Or32,
10067 binop( Iop_Shl32,
10068 binop( Iop_And32,
10069 unop( Iop_64HIto32, frBI64_hi ),
10070 mkU32( 0xF ) ),
10071 mkU8( 14 ) ),
10072 binop( Iop_Shr32,
10073 unop( Iop_64to32, frBI64_hi ),
10074 mkU8( 18 ) ) ),
10075 binop( Iop_Or32,
10076 binop( Iop_Shl32,
10077 unop( Iop_64to32, frBI64_hi ),
10078 mkU8( 14 ) ),
10079 binop( Iop_Shr32,
10080 unop( Iop_64HIto32, frBI64_lo ),
10081 mkU8( 18 ) ) ) ) );
10082
10083 /* Convert the 50 bit densely packed BCD string to a 60 bit
10084 * BCD string.
10085 */
10086 assign( tmpmid60, unop( Iop_DPBtoBCD, mkexpr( mid_50 ) ) );
10087 assign( *mid_60_u, unop( Iop_64HIto32, mkexpr( tmpmid60 ) ) );
10088 assign( *mid_60_l, unop( Iop_64to32, mkexpr( tmpmid60 ) ) );
10089
10090 /* top_10[49:0] = frBI64_hi[45:36]) | */
10091 assign( top_10,
10092 binop( Iop_32HLto64,
10093 mkU32( 0 ),
10094 binop( Iop_And32,
10095 binop( Iop_Shr32,
10096 unop( Iop_64HIto32, frBI64_hi ),
10097 mkU8( 4 ) ),
10098 mkU32( 0x3FF ) ) ) );
10099
10100 /* Convert the 10 bit densely packed BCD string to a 12 bit
10101 * BCD string.
10102 */
10103 assign( tmptop12, unop( Iop_DPBtoBCD, mkexpr( top_10 ) ) );
10104 assign( top_12_u, unop( Iop_64HIto32, mkexpr( tmptop12 ) ) );
10105 assign( *top_12_l, unop( Iop_64to32, mkexpr( tmptop12 ) ) );
10106 }
10107
Count_zeros(int start,IRExpr * init_cnt,IRExpr * init_flag,IRTemp * final_cnt,IRTemp * final_flag,IRExpr * string)10108 static void Count_zeros( int start, IRExpr * init_cnt, IRExpr * init_flag,
10109 IRTemp * final_cnt, IRTemp * final_flag,
10110 IRExpr * string )
10111 {
10112 IRTemp cnt[MAX_DIGITS_IN_STRING + 1];IRTemp flag[MAX_DIGITS_IN_STRING+1];
10113 int digits = MAX_DIGITS_IN_STRING;
10114 int i;
10115
10116 cnt[start-1] = newTemp( Ity_I8 );
10117 flag[start-1] = newTemp( Ity_I8 );
10118 assign( cnt[start-1], init_cnt);
10119 assign( flag[start-1], init_flag);
10120
10121 for ( i = start; i <= digits; i++) {
10122 cnt[i] = newTemp( Ity_I8 );
10123 flag[i] = newTemp( Ity_I8 );
10124 assign( cnt[i],
10125 binop( Iop_Add8,
10126 mkexpr( cnt[i-1] ),
10127 binop(Iop_And8,
10128 unop( Iop_1Uto8,
10129 binop(Iop_CmpEQ32,
10130 binop(Iop_And32,
10131 string,
10132 mkU32( 0xF <<
10133 ( ( digits - i ) * 4) ) ),
10134 mkU32( 0 ) ) ),
10135 binop( Iop_Xor8, /* complement flag */
10136 mkexpr( flag[i - 1] ),
10137 mkU8( 0xFF ) ) ) ) );
10138
10139 /* set flag to 1 if digit was not a zero */
10140 assign( flag[i],
10141 binop(Iop_Or8,
10142 unop( Iop_1Sto8,
10143 binop(Iop_CmpNE32,
10144 binop(Iop_And32,
10145 string,
10146 mkU32( 0xF <<
10147 ( (digits - i) * 4) ) ),
10148 mkU32( 0 ) ) ),
10149 mkexpr( flag[i - 1] ) ) );
10150 }
10151
10152 *final_cnt = cnt[digits];
10153 *final_flag = flag[digits];
10154 }
10155
Count_leading_zeros_60(IRExpr * lmd,IRExpr * upper_28,IRExpr * low_32)10156 static IRExpr * Count_leading_zeros_60( IRExpr * lmd, IRExpr * upper_28,
10157 IRExpr * low_32 )
10158 {
10159 IRTemp num_lmd = newTemp( Ity_I8 );
10160 IRTemp num_upper = newTemp( Ity_I8 );
10161 IRTemp num_low = newTemp( Ity_I8 );
10162 IRTemp lmd_flag = newTemp( Ity_I8 );
10163 IRTemp upper_flag = newTemp( Ity_I8 );
10164 IRTemp low_flag = newTemp( Ity_I8 );
10165
10166 assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) );
10167 assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) );
10168
10169 Count_zeros( 2,
10170 mkexpr( num_lmd ),
10171 mkexpr( lmd_flag ),
10172 &num_upper,
10173 &upper_flag,
10174 upper_28 );
10175
10176 Count_zeros( 1,
10177 mkexpr( num_upper ),
10178 mkexpr( upper_flag ),
10179 &num_low,
10180 &low_flag,
10181 low_32 );
10182
10183 return mkexpr( num_low );
10184 }
10185
Count_leading_zeros_128(IRExpr * lmd,IRExpr * top_12_l,IRExpr * mid_60_u,IRExpr * mid_60_l,IRExpr * low_60_u,IRExpr * low_60_l)10186 static IRExpr * Count_leading_zeros_128( IRExpr * lmd, IRExpr * top_12_l,
10187 IRExpr * mid_60_u, IRExpr * mid_60_l,
10188 IRExpr * low_60_u, IRExpr * low_60_l)
10189 {
10190 IRTemp num_lmd = newTemp( Ity_I8 );
10191 IRTemp num_top = newTemp( Ity_I8 );
10192 IRTemp num_mid_u = newTemp( Ity_I8 );
10193 IRTemp num_mid_l = newTemp( Ity_I8 );
10194 IRTemp num_low_u = newTemp( Ity_I8 );
10195 IRTemp num_low_l = newTemp( Ity_I8 );
10196
10197 IRTemp lmd_flag = newTemp( Ity_I8 );
10198 IRTemp top_flag = newTemp( Ity_I8 );
10199 IRTemp mid_u_flag = newTemp( Ity_I8 );
10200 IRTemp mid_l_flag = newTemp( Ity_I8 );
10201 IRTemp low_u_flag = newTemp( Ity_I8 );
10202 IRTemp low_l_flag = newTemp( Ity_I8 );
10203
10204 /* Check the LMD, digit 16, to see if it is zero. */
10205 assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) );
10206
10207 assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) );
10208
10209 Count_zeros( 6,
10210 mkexpr( num_lmd ),
10211 mkexpr( lmd_flag ),
10212 &num_top,
10213 &top_flag,
10214 top_12_l );
10215
10216 Count_zeros( 1,
10217 mkexpr( num_top ),
10218 mkexpr( top_flag ),
10219 &num_mid_u,
10220 &mid_u_flag,
10221 binop( Iop_Or32,
10222 binop( Iop_Shl32, mid_60_u, mkU8( 2 ) ),
10223 binop( Iop_Shr32, mid_60_l, mkU8( 30 ) ) ) );
10224
10225 Count_zeros( 2,
10226 mkexpr( num_mid_u ),
10227 mkexpr( mid_u_flag ),
10228 &num_mid_l,
10229 &mid_l_flag,
10230 mid_60_l );
10231
10232 Count_zeros( 1,
10233 mkexpr( num_mid_l ),
10234 mkexpr( mid_l_flag ),
10235 &num_low_u,
10236 &low_u_flag,
10237 binop( Iop_Or32,
10238 binop( Iop_Shl32, low_60_u, mkU8( 2 ) ),
10239 binop( Iop_Shr32, low_60_l, mkU8( 30 ) ) ) );
10240
10241 Count_zeros( 2,
10242 mkexpr( num_low_u ),
10243 mkexpr( low_u_flag ),
10244 &num_low_l,
10245 &low_l_flag,
10246 low_60_l );
10247
10248 return mkexpr( num_low_l );
10249 }
10250
Check_unordered(IRExpr * val)10251 static IRExpr * Check_unordered(IRExpr * val)
10252 {
10253 IRTemp gfield0to5 = newTemp( Ity_I32 );
10254
10255 /* Extract G[0:4] */
10256 assign( gfield0to5,
10257 binop( Iop_And32,
10258 binop( Iop_Shr32, unop( Iop_64HIto32, val ), mkU8( 26 ) ),
10259 mkU32( 0x1F ) ) );
10260
10261 /* Check for unordered, return all 1'x if true */
10262 return binop( Iop_Or32, /* QNaN check */
10263 unop( Iop_1Sto32,
10264 binop( Iop_CmpEQ32,
10265 mkexpr( gfield0to5 ),
10266 mkU32( 0x1E ) ) ),
10267 unop( Iop_1Sto32, /* SNaN check */
10268 binop( Iop_CmpEQ32,
10269 mkexpr( gfield0to5 ),
10270 mkU32( 0x1F ) ) ) );
10271 }
10272
10273 #undef AND
10274 #undef AND4
10275 #undef OR
10276 #undef OR3
10277 #undef OR4
10278 #undef NOT
10279 #undef SHR
10280 #undef SHL
10281 #undef BITS5
10282
10283 /*------------------------------------------------------------*/
10284 /*--- Decimal Floating Point (DFP) instruction translation ---*/
10285 /*------------------------------------------------------------*/
10286
10287 /* DFP Arithmetic instructions */
dis_dfp_arith(UInt theInstr)10288 static Bool dis_dfp_arith(UInt theInstr)
10289 {
10290 UInt opc2 = ifieldOPClo10( theInstr );
10291 UChar frS_addr = ifieldRegDS( theInstr );
10292 UChar frA_addr = ifieldRegA( theInstr );
10293 UChar frB_addr = ifieldRegB( theInstr );
10294 UChar flag_rC = ifieldBIT0( theInstr );
10295
10296 IRTemp frA = newTemp( Ity_D64 );
10297 IRTemp frB = newTemp( Ity_D64 );
10298 IRTemp frS = newTemp( Ity_D64 );
10299 IRExpr* round = get_IR_roundingmode_DFP();
10300
10301 /* By default, if flag_RC is set, we will clear cr1 after the
10302 * operation. In reality we should set cr1 to indicate the
10303 * exception status of the operation, but since we're not
10304 * simulating exceptions, the exception status will appear to be
10305 * zero. Hence cr1 should be cleared if this is a . form insn.
10306 */
10307 Bool clear_CR1 = True;
10308
10309 assign( frA, getDReg( frA_addr ) );
10310 assign( frB, getDReg( frB_addr ) );
10311
10312 switch (opc2) {
10313 case 0x2: // dadd
10314 DIP( "dadd%s fr%u,fr%u,fr%u\n",
10315 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10316 assign( frS, triop( Iop_AddD64, round, mkexpr( frA ), mkexpr( frB ) ) );
10317 break;
10318 case 0x202: // dsub
10319 DIP( "dsub%s fr%u,fr%u,fr%u\n",
10320 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10321 assign( frS, triop( Iop_SubD64, round, mkexpr( frA ), mkexpr( frB ) ) );
10322 break;
10323 case 0x22: // dmul
10324 DIP( "dmul%s fr%u,fr%u,fr%u\n",
10325 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10326 assign( frS, triop( Iop_MulD64, round, mkexpr( frA ), mkexpr( frB ) ) );
10327 break;
10328 case 0x222: // ddiv
10329 DIP( "ddiv%s fr%u,fr%u,fr%u\n",
10330 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10331 assign( frS, triop( Iop_DivD64, round, mkexpr( frA ), mkexpr( frB ) ) );
10332 break;
10333 }
10334
10335 putDReg( frS_addr, mkexpr( frS ) );
10336
10337 if (flag_rC && clear_CR1) {
10338 putCR321( 1, mkU8( 0 ) );
10339 putCR0( 1, mkU8( 0 ) );
10340 }
10341
10342 return True;
10343 }
10344
10345 /* Quad DFP Arithmetic instructions */
dis_dfp_arithq(UInt theInstr)10346 static Bool dis_dfp_arithq(UInt theInstr)
10347 {
10348 UInt opc2 = ifieldOPClo10( theInstr );
10349 UChar frS_addr = ifieldRegDS( theInstr );
10350 UChar frA_addr = ifieldRegA( theInstr );
10351 UChar frB_addr = ifieldRegB( theInstr );
10352 UChar flag_rC = ifieldBIT0( theInstr );
10353
10354 IRTemp frA = newTemp( Ity_D128 );
10355 IRTemp frB = newTemp( Ity_D128 );
10356 IRTemp frS = newTemp( Ity_D128 );
10357 IRExpr* round = get_IR_roundingmode_DFP();
10358
10359 /* By default, if flag_RC is set, we will clear cr1 after the
10360 * operation. In reality we should set cr1 to indicate the
10361 * exception status of the operation, but since we're not
10362 * simulating exceptions, the exception status will appear to be
10363 * zero. Hence cr1 should be cleared if this is a . form insn.
10364 */
10365 Bool clear_CR1 = True;
10366
10367 assign( frA, getDReg_pair( frA_addr ) );
10368 assign( frB, getDReg_pair( frB_addr ) );
10369
10370 switch (opc2) {
10371 case 0x2: // daddq
10372 DIP( "daddq%s fr%u,fr%u,fr%u\n",
10373 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10374 assign( frS, triop( Iop_AddD128, round, mkexpr( frA ), mkexpr( frB ) ) );
10375 break;
10376 case 0x202: // dsubq
10377 DIP( "dsubq%s fr%u,fr%u,fr%u\n",
10378 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10379 assign( frS, triop( Iop_SubD128, round, mkexpr( frA ), mkexpr( frB ) ) );
10380 break;
10381 case 0x22: // dmulq
10382 DIP( "dmulq%s fr%u,fr%u,fr%u\n",
10383 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10384 assign( frS, triop( Iop_MulD128, round, mkexpr( frA ), mkexpr( frB ) ) );
10385 break;
10386 case 0x222: // ddivq
10387 DIP( "ddivq%s fr%u,fr%u,fr%u\n",
10388 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10389 assign( frS, triop( Iop_DivD128, round, mkexpr( frA ), mkexpr( frB ) ) );
10390 break;
10391 }
10392
10393 putDReg_pair( frS_addr, mkexpr( frS ) );
10394
10395 if (flag_rC && clear_CR1) {
10396 putCR321( 1, mkU8( 0 ) );
10397 putCR0( 1, mkU8( 0 ) );
10398 }
10399
10400 return True;
10401 }
10402
10403 /* DFP 64-bit logical shift instructions */
dis_dfp_shift(UInt theInstr)10404 static Bool dis_dfp_shift(UInt theInstr) {
10405 UInt opc2 = ifieldOPClo9( theInstr );
10406 UChar frS_addr = ifieldRegDS( theInstr );
10407 UChar frA_addr = ifieldRegA( theInstr );
10408 UChar shift_val = IFIELD(theInstr, 10, 6);
10409 UChar flag_rC = ifieldBIT0( theInstr );
10410
10411 IRTemp frA = newTemp( Ity_D64 );
10412 IRTemp frS = newTemp( Ity_D64 );
10413 Bool clear_CR1 = True;
10414
10415 assign( frA, getDReg( frA_addr ) );
10416
10417 switch (opc2) {
10418 case 0x42: // dscli
10419 DIP( "dscli%s fr%u,fr%u,%u\n",
10420 flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
10421 assign( frS, binop( Iop_ShlD64, mkexpr( frA ), mkU8( shift_val ) ) );
10422 break;
10423 case 0x62: // dscri
10424 DIP( "dscri%s fr%u,fr%u,%u\n",
10425 flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
10426 assign( frS, binop( Iop_ShrD64, mkexpr( frA ), mkU8( shift_val ) ) );
10427 break;
10428 }
10429
10430 putDReg( frS_addr, mkexpr( frS ) );
10431
10432 if (flag_rC && clear_CR1) {
10433 putCR321( 1, mkU8( 0 ) );
10434 putCR0( 1, mkU8( 0 ) );
10435 }
10436
10437 return True;
10438 }
10439
10440 /* Quad DFP logical shift instructions */
dis_dfp_shiftq(UInt theInstr)10441 static Bool dis_dfp_shiftq(UInt theInstr) {
10442 UInt opc2 = ifieldOPClo9( theInstr );
10443 UChar frS_addr = ifieldRegDS( theInstr );
10444 UChar frA_addr = ifieldRegA( theInstr );
10445 UChar shift_val = IFIELD(theInstr, 10, 6);
10446 UChar flag_rC = ifieldBIT0( theInstr );
10447
10448 IRTemp frA = newTemp( Ity_D128 );
10449 IRTemp frS = newTemp( Ity_D128 );
10450 Bool clear_CR1 = True;
10451
10452 assign( frA, getDReg_pair( frA_addr ) );
10453
10454 switch (opc2) {
10455 case 0x42: // dscliq
10456 DIP( "dscliq%s fr%u,fr%u,%u\n",
10457 flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
10458 assign( frS, binop( Iop_ShlD128, mkexpr( frA ), mkU8( shift_val ) ) );
10459 break;
10460 case 0x62: // dscriq
10461 DIP( "dscriq%s fr%u,fr%u,%u\n",
10462 flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
10463 assign( frS, binop( Iop_ShrD128, mkexpr( frA ), mkU8( shift_val ) ) );
10464 break;
10465 }
10466
10467 putDReg_pair( frS_addr, mkexpr( frS ) );
10468
10469 if (flag_rC && clear_CR1) {
10470 putCR321( 1, mkU8( 0 ) );
10471 putCR0( 1, mkU8( 0 ) );
10472 }
10473
10474 return True;
10475 }
10476
10477 /* DFP 64-bit format conversion instructions */
dis_dfp_fmt_conv(UInt theInstr)10478 static Bool dis_dfp_fmt_conv(UInt theInstr) {
10479 UInt opc2 = ifieldOPClo10( theInstr );
10480 UChar frS_addr = ifieldRegDS( theInstr );
10481 UChar frB_addr = ifieldRegB( theInstr );
10482 IRExpr* round = get_IR_roundingmode_DFP();
10483 UChar flag_rC = ifieldBIT0( theInstr );
10484 IRTemp frB;
10485 IRTemp frS;
10486 Bool clear_CR1 = True;
10487
10488 switch (opc2) {
10489 case 0x102: //dctdp
10490 DIP( "dctdp%s fr%u,fr%u\n",
10491 flag_rC ? ".":"", frS_addr, frB_addr );
10492
10493 frB = newTemp( Ity_D32 );
10494 frS = newTemp( Ity_D64 );
10495 assign( frB, getDReg32( frB_addr ) );
10496 assign( frS, unop( Iop_D32toD64, mkexpr( frB ) ) );
10497 putDReg( frS_addr, mkexpr( frS ) );
10498 break;
10499 case 0x302: // drsp
10500 DIP( "drsp%s fr%u,fr%u\n",
10501 flag_rC ? ".":"", frS_addr, frB_addr );
10502 frB = newTemp( Ity_D64 );
10503 frS = newTemp( Ity_D32 );
10504 assign( frB, getDReg( frB_addr ) );
10505 assign( frS, binop( Iop_D64toD32, round, mkexpr( frB ) ) );
10506 putDReg32( frS_addr, mkexpr( frS ) );
10507 break;
10508 case 0x122: // dctfix
10509 {
10510 IRTemp tmp = newTemp( Ity_I64 );
10511
10512 DIP( "dctfix%s fr%u,fr%u\n",
10513 flag_rC ? ".":"", frS_addr, frB_addr );
10514 frB = newTemp( Ity_D64 );
10515 frS = newTemp( Ity_D64 );
10516 assign( frB, getDReg( frB_addr ) );
10517 assign( tmp, binop( Iop_D64toI64S, round, mkexpr( frB ) ) );
10518 assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
10519 putDReg( frS_addr, mkexpr( frS ) );
10520 }
10521 break;
10522 case 0x322: // dcffix
10523 DIP( "dcffix%s fr%u,fr%u\n",
10524 flag_rC ? ".":"", frS_addr, frB_addr );
10525 frB = newTemp( Ity_D64 );
10526 frS = newTemp( Ity_D64 );
10527 assign( frB, getDReg( frB_addr ) );
10528 assign( frS, binop( Iop_I64StoD64,
10529 round,
10530 unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ) );
10531 putDReg( frS_addr, mkexpr( frS ) );
10532 break;
10533 }
10534
10535 if (flag_rC && clear_CR1) {
10536 putCR321( 1, mkU8( 0 ) );
10537 putCR0( 1, mkU8( 0 ) );
10538 }
10539
10540 return True;
10541 }
10542
10543 /* Quad DFP format conversion instructions */
dis_dfp_fmt_convq(UInt theInstr)10544 static Bool dis_dfp_fmt_convq(UInt theInstr) {
10545 UInt opc2 = ifieldOPClo10( theInstr );
10546 UChar frS_addr = ifieldRegDS( theInstr );
10547 UChar frB_addr = ifieldRegB( theInstr );
10548 IRExpr* round = get_IR_roundingmode_DFP();
10549 IRTemp frB64 = newTemp( Ity_D64 );
10550 IRTemp frB128 = newTemp( Ity_D128 );
10551 IRTemp frS64 = newTemp( Ity_D64 );
10552 IRTemp frS128 = newTemp( Ity_D128 );
10553 UChar flag_rC = ifieldBIT0( theInstr );
10554 Bool clear_CR1 = True;
10555
10556 switch (opc2) {
10557 case 0x102: // dctqpq
10558 DIP( "dctqpq%s fr%u,fr%u\n",
10559 flag_rC ? ".":"", frS_addr, frB_addr );
10560 assign( frB64, getDReg( frB_addr ) );
10561 assign( frS128, unop( Iop_D64toD128, mkexpr( frB64 ) ) );
10562 putDReg_pair( frS_addr, mkexpr( frS128 ) );
10563 break;
10564 case 0x122: // dctfixq
10565 {
10566 IRTemp tmp = newTemp( Ity_I64 );
10567
10568 DIP( "dctfixq%s fr%u,fr%u\n",
10569 flag_rC ? ".":"", frS_addr, frB_addr );
10570 assign( frB128, getDReg_pair( frB_addr ) );
10571 assign( tmp, binop( Iop_D128toI64S, round, mkexpr( frB128 ) ) );
10572 assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
10573 putDReg( frS_addr, mkexpr( frS64 ) );
10574 }
10575 break;
10576 case 0x302: //drdpq
10577 DIP( "drdpq%s fr%u,fr%u\n",
10578 flag_rC ? ".":"", frS_addr, frB_addr );
10579 assign( frB128, getDReg_pair( frB_addr ) );
10580 assign( frS64, binop( Iop_D128toD64, round, mkexpr( frB128 ) ) );
10581 putDReg( frS_addr, mkexpr( frS64 ) );
10582 break;
10583 case 0x322: // dcffixq
10584 {
10585 /* Have to introduce an IOP for this instruction so it will work
10586 * on POWER 6 because emulating the instruction requires a POWER 7
10587 * DFP instruction in the emulation code.
10588 */
10589 DIP( "dcffixq%s fr%u,fr%u\n",
10590 flag_rC ? ".":"", frS_addr, frB_addr );
10591 assign( frB64, getDReg( frB_addr ) );
10592 assign( frS128, unop( Iop_I64StoD128,
10593 unop( Iop_ReinterpD64asI64,
10594 mkexpr( frB64 ) ) ) );
10595 putDReg_pair( frS_addr, mkexpr( frS128 ) );
10596 break;
10597 }
10598 }
10599
10600 if (flag_rC && clear_CR1) {
10601 putCR321( 1, mkU8( 0 ) );
10602 putCR0( 1, mkU8( 0 ) );
10603 }
10604
10605 return True;
10606 }
10607
dis_dfp_round(UInt theInstr)10608 static Bool dis_dfp_round( UInt theInstr ) {
10609 UChar frS_addr = ifieldRegDS(theInstr);
10610 UChar R = IFIELD(theInstr, 16, 1);
10611 UChar RMC = IFIELD(theInstr, 9, 2);
10612 UChar frB_addr = ifieldRegB( theInstr );
10613 UChar flag_rC = ifieldBIT0( theInstr );
10614 IRTemp frB = newTemp( Ity_D64 );
10615 IRTemp frS = newTemp( Ity_D64 );
10616 UInt opc2 = ifieldOPClo8( theInstr );
10617 Bool clear_CR1 = True;
10618
10619 switch (opc2) {
10620 /* drintn, is the same as drintx. The only difference is this
10621 * instruction does not generate an exception for an inexact operation.
10622 * Currently not supporting inexact exceptions.
10623 */
10624 case 0x63: // drintx
10625 case 0xE3: // drintn
10626 DIP( "drintx/drintn%s fr%u,fr%u\n",
10627 flag_rC ? ".":"", frS_addr, frB_addr );
10628
10629 /* NOTE, this instruction takes a DFP value and rounds to the
10630 * neares floating point integer value, i.e. fractional part
10631 * is zero. The result is a floating point number.
10632 */
10633 /* pass the value of R and RMC in the same field */
10634 assign( frB, getDReg( frB_addr ) );
10635 assign( frS, binop( Iop_RoundD64toInt,
10636 mkU32( ( R << 3 ) | RMC ),
10637 mkexpr( frB ) ) );
10638 putDReg( frS_addr, mkexpr( frS ) );
10639 break;
10640 default:
10641 vex_printf("dis_dfp_round(ppc)(opc2)\n");
10642 return False;
10643 }
10644
10645 if (flag_rC && clear_CR1) {
10646 putCR321( 1, mkU8( 0 ) );
10647 putCR0( 1, mkU8( 0 ) );
10648 }
10649
10650 return True;
10651 }
10652
dis_dfp_roundq(UInt theInstr)10653 static Bool dis_dfp_roundq(UInt theInstr) {
10654 UChar frS_addr = ifieldRegDS( theInstr );
10655 UChar frB_addr = ifieldRegB( theInstr );
10656 UChar R = IFIELD(theInstr, 16, 1);
10657 UChar RMC = IFIELD(theInstr, 9, 2);
10658 UChar flag_rC = ifieldBIT0( theInstr );
10659 IRTemp frB = newTemp( Ity_D128 );
10660 IRTemp frS = newTemp( Ity_D128 );
10661 Bool clear_CR1 = True;
10662 UInt opc2 = ifieldOPClo8( theInstr );
10663
10664 switch (opc2) {
10665 /* drintnq, is the same as drintxq. The only difference is this
10666 * instruction does not generate an exception for an inexact operation.
10667 * Currently not supporting inexact exceptions.
10668 */
10669 case 0x63: // drintxq
10670 case 0xE3: // drintnq
10671 DIP( "drintxq/drintnq%s fr%u,fr%u\n",
10672 flag_rC ? ".":"", frS_addr, frB_addr );
10673
10674 /* pass the value of R and RMC in the same field */
10675 assign( frB, getDReg_pair( frB_addr ) );
10676 assign( frS, binop( Iop_RoundD128toInt,
10677 mkU32( ( R << 3 ) | RMC ),
10678 mkexpr( frB ) ) );
10679 putDReg_pair( frS_addr, mkexpr( frS ) );
10680 break;
10681 default:
10682 vex_printf("dis_dfp_roundq(ppc)(opc2)\n");
10683 return False;
10684 }
10685
10686 if (flag_rC && clear_CR1) {
10687 putCR321( 1, mkU8( 0 ) );
10688 putCR0( 1, mkU8( 0 ) );
10689 }
10690
10691 return True;
10692 }
10693
dis_dfp_quantize_sig_rrnd(UInt theInstr)10694 static Bool dis_dfp_quantize_sig_rrnd(UInt theInstr) {
10695 UInt opc2 = ifieldOPClo8( theInstr );
10696 UChar frS_addr = ifieldRegDS( theInstr );
10697 UChar frA_addr = ifieldRegA( theInstr );
10698 UChar frB_addr = ifieldRegB( theInstr );
10699 UChar flag_rC = ifieldBIT0( theInstr );
10700 UInt TE_value = IFIELD(theInstr, 16, 4);
10701 UInt TE_sign = IFIELD(theInstr, 20, 1);
10702 UInt RMC = IFIELD(theInstr, 9, 2);
10703 IRTemp frA = newTemp( Ity_D64 );
10704 IRTemp frB = newTemp( Ity_D64 );
10705 IRTemp frS = newTemp( Ity_D64 );
10706 Bool clear_CR1 = True;
10707
10708 assign( frB, getDReg( frB_addr ) );
10709
10710 switch (opc2) {
10711 case 0x43: // dquai
10712 DIP( "dquai%s fr%u,fr%u,fr%u\n",
10713 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10714 IRTemp TE_I64 = newTemp( Ity_I64 );
10715
10716 /* Generate a reference DFP value frA with the desired exponent
10717 * given by TE using significand from frB. Need to add the bias
10718 * 398 to TE. TE is stored as a 2's complement number.
10719 */
10720 if (TE_sign == 1) {
10721 /* Take 2's complement of the 5-bit value and subtract from bias.
10722 * Bias is adjusted for the +1 required when taking 2's complement.
10723 */
10724 assign( TE_I64,
10725 unop( Iop_32Uto64,
10726 binop( Iop_Sub32, mkU32( 397 ),
10727 binop( Iop_And32, mkU32( 0xF ),
10728 unop( Iop_Not32, mkU32( TE_value ) )
10729 ) ) ) );
10730
10731 } else {
10732 assign( TE_I64,
10733 unop( Iop_32Uto64,
10734 binop( Iop_Add32, mkU32( 398 ), mkU32( TE_value ) )
10735 ) );
10736 }
10737
10738 assign( frA, binop( Iop_InsertExpD64, mkexpr( TE_I64 ),
10739 unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) );
10740
10741 assign( frS, triop( Iop_QuantizeD64,
10742 mkU32( RMC ),
10743 mkexpr( frA ),
10744 mkexpr( frB ) ) );
10745 break;
10746
10747 case 0x3: // dqua
10748 DIP( "dqua%s fr%u,fr%u,fr%u\n",
10749 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10750 assign( frA, getDReg( frA_addr ) );
10751 assign( frS, triop( Iop_QuantizeD64,
10752 mkU32( RMC ),
10753 mkexpr( frA ),
10754 mkexpr( frB ) ) );
10755 break;
10756 case 0x23: // drrnd
10757 {
10758 IRTemp tmp = newTemp( Ity_I8 );
10759
10760 DIP( "drrnd%s fr%u,fr%u,fr%u\n",
10761 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10762 assign( frA, getDReg( frA_addr ) );
10763 /* Iop_64to8 not supported in 32 bit mode, do it in two steps. */
10764 assign( tmp, unop( Iop_32to8,
10765 unop( Iop_64to32,
10766 unop( Iop_ReinterpD64asI64,
10767 mkexpr( frA ) ) ) ) );
10768 assign( frS, triop( Iop_SignificanceRoundD64,
10769 mkU32( RMC ),
10770 mkexpr( tmp ),
10771 mkexpr( frB ) ) );
10772 }
10773 break;
10774 default:
10775 vex_printf("dis_dfp_quantize_sig_rrnd(ppc)(opc2)\n");
10776 return False;
10777 }
10778 putDReg( frS_addr, mkexpr( frS ) );
10779
10780 if (flag_rC && clear_CR1) {
10781 putCR321( 1, mkU8( 0 ) );
10782 putCR0( 1, mkU8( 0 ) );
10783 }
10784
10785 return True;
10786 }
10787
dis_dfp_quantize_sig_rrndq(UInt theInstr)10788 static Bool dis_dfp_quantize_sig_rrndq(UInt theInstr) {
10789 UInt opc2 = ifieldOPClo8( theInstr );
10790 UChar frS_addr = ifieldRegDS( theInstr );
10791 UChar frA_addr = ifieldRegA( theInstr );
10792 UChar frB_addr = ifieldRegB( theInstr );
10793 UChar flag_rC = ifieldBIT0( theInstr );
10794 UInt TE_value = IFIELD(theInstr, 16, 4);
10795 UInt TE_sign = IFIELD(theInstr, 20, 1);
10796 UInt RMC = IFIELD(theInstr, 9, 2);
10797 IRTemp frA = newTemp( Ity_D128 );
10798 IRTemp frB = newTemp( Ity_D128 );
10799 IRTemp frS = newTemp( Ity_D128 );
10800 Bool clear_CR1 = True;
10801
10802 assign( frB, getDReg_pair( frB_addr ) );
10803
10804 switch (opc2) {
10805 case 0x43: // dquaiq
10806 DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
10807 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10808 IRTemp TE_I64 = newTemp( Ity_I64 );
10809
10810 /* Generate a reference DFP value frA with the desired exponent
10811 * given by TE using significand of 1. Need to add the bias
10812 * 6176 to TE.
10813 */
10814 if (TE_sign == 1) {
10815 /* Take 2's complement of the 5-bit value and subtract from bias.
10816 * Bias adjusted for the +1 required when taking 2's complement.
10817 */
10818 assign( TE_I64,
10819 unop( Iop_32Uto64,
10820 binop( Iop_Sub32, mkU32( 6175 ),
10821 binop( Iop_And32, mkU32( 0xF ),
10822 unop( Iop_Not32, mkU32( TE_value ) )
10823 ) ) ) );
10824
10825 } else {
10826 assign( TE_I64,
10827 unop( Iop_32Uto64,
10828 binop( Iop_Add32,
10829 mkU32( 6176 ),
10830 mkU32( TE_value ) ) ) );
10831 }
10832
10833 assign( frA,
10834 binop( Iop_InsertExpD128, mkexpr( TE_I64 ),
10835 unop( Iop_D64toD128,
10836 unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) ) );
10837 assign( frS, triop( Iop_QuantizeD128,
10838 mkU32( RMC ),
10839 mkexpr( frA ),
10840 mkexpr( frB ) ) );
10841 break;
10842 case 0x3: // dquaq
10843 DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
10844 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10845 assign( frA, getDReg_pair( frA_addr ) );
10846 assign( frS, triop( Iop_QuantizeD128,
10847 mkU32( RMC ),
10848 mkexpr( frA ),
10849 mkexpr( frB ) ) );
10850 break;
10851 case 0x23: // drrndq
10852 {
10853 IRTemp tmp = newTemp( Ity_I8 );
10854
10855 DIP( "drrndq%s fr%u,fr%u,fr%u\n",
10856 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10857 assign( frA, getDReg_pair( frA_addr ) );
10858 assign( tmp, unop( Iop_32to8,
10859 unop( Iop_64to32,
10860 unop( Iop_ReinterpD64asI64,
10861 unop( Iop_D128HItoD64,
10862 mkexpr( frA ) ) ) ) ) );
10863 assign( frS, triop( Iop_SignificanceRoundD128,
10864 mkU32( RMC ),
10865 mkexpr( tmp ),
10866 mkexpr( frB ) ) );
10867 }
10868 break;
10869 default:
10870 vex_printf("dis_dfp_quantize_sig_rrndq(ppc)(opc2)\n");
10871 return False;
10872 }
10873 putDReg_pair( frS_addr, mkexpr( frS ) );
10874
10875 if (flag_rC && clear_CR1) {
10876 putCR321( 1, mkU8( 0 ) );
10877 putCR0( 1, mkU8( 0 ) );
10878 }
10879
10880 return True;
10881 }
10882
dis_dfp_extract_insert(UInt theInstr)10883 static Bool dis_dfp_extract_insert(UInt theInstr) {
10884 UInt opc2 = ifieldOPClo10( theInstr );
10885 UChar frS_addr = ifieldRegDS( theInstr );
10886 UChar frA_addr = ifieldRegA( theInstr );
10887 UChar frB_addr = ifieldRegB( theInstr );
10888 UChar flag_rC = ifieldBIT0( theInstr );
10889 Bool clear_CR1 = True;
10890
10891 IRTemp frA = newTemp( Ity_D64 );
10892 IRTemp frB = newTemp( Ity_D64 );
10893 IRTemp frS = newTemp( Ity_D64 );
10894 IRTemp tmp = newTemp( Ity_I64 );
10895
10896 assign( frA, getDReg( frA_addr ) );
10897 assign( frB, getDReg( frB_addr ) );
10898
10899 switch (opc2) {
10900 case 0x162: // dxex
10901 DIP( "dxex%s fr%u,fr%u,fr%u\n",
10902 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10903 assign( tmp, unop( Iop_ExtractExpD64, mkexpr( frB ) ) );
10904 assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
10905 break;
10906 case 0x362: // diex
10907 DIP( "diex%s fr%u,fr%u,fr%u\n",
10908 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10909 assign( frS, binop( Iop_InsertExpD64,
10910 unop( Iop_ReinterpD64asI64,
10911 mkexpr( frA ) ),
10912 mkexpr( frB ) ) );
10913 break;
10914 default:
10915 vex_printf("dis_dfp_extract_insert(ppc)(opc2)\n");
10916 return False;
10917 }
10918
10919 putDReg( frS_addr, mkexpr( frS ) );
10920
10921 if (flag_rC && clear_CR1) {
10922 putCR321( 1, mkU8( 0 ) );
10923 putCR0( 1, mkU8( 0 ) );
10924 }
10925
10926 return True;
10927 }
10928
dis_dfp_extract_insertq(UInt theInstr)10929 static Bool dis_dfp_extract_insertq(UInt theInstr) {
10930 UInt opc2 = ifieldOPClo10( theInstr );
10931 UChar frS_addr = ifieldRegDS( theInstr );
10932 UChar frA_addr = ifieldRegA( theInstr );
10933 UChar frB_addr = ifieldRegB( theInstr );
10934 UChar flag_rC = ifieldBIT0( theInstr );
10935
10936 IRTemp frA = newTemp( Ity_D64 );
10937 IRTemp frB = newTemp( Ity_D128 );
10938 IRTemp frS64 = newTemp( Ity_D64 );
10939 IRTemp frS = newTemp( Ity_D128 );
10940 IRTemp tmp = newTemp( Ity_I64 );
10941 Bool clear_CR1 = True;
10942
10943 assign( frB, getDReg_pair( frB_addr ) );
10944
10945 switch (opc2) {
10946 case 0x162: // dxexq
10947 DIP( "dxexq%s fr%u,fr%u\n",
10948 flag_rC ? ".":"", frS_addr, frB_addr );
10949 /* Instruction actually returns a 64-bit result. So as to be
10950 * consistent and not have to add a new struct, the emulation returns
10951 * the 64-bit result in the upper and lower register.
10952 */
10953 assign( tmp, unop( Iop_ExtractExpD128, mkexpr( frB ) ) );
10954 assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
10955 putDReg( frS_addr, mkexpr( frS64 ) );
10956 break;
10957 case 0x362: // diexq
10958 DIP( "diexq%s fr%u,fr%u,fr%u\n",
10959 flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10960 assign( frA, getDReg( frA_addr ) );
10961 assign( frS, binop( Iop_InsertExpD128,
10962 unop( Iop_ReinterpD64asI64, mkexpr( frA ) ),
10963 mkexpr( frB ) ) );
10964 putDReg_pair( frS_addr, mkexpr( frS ) );
10965 break;
10966 default:
10967 vex_printf("dis_dfp_extract_insertq(ppc)(opc2)\n");
10968 return False;
10969 }
10970
10971 if (flag_rC && clear_CR1) {
10972 putCR321( 1, mkU8( 0 ) );
10973 putCR0( 1, mkU8( 0 ) );
10974 }
10975
10976 return True;
10977 }
10978
10979 /* DFP 64-bit comparison instructions */
dis_dfp_compare(UInt theInstr)10980 static Bool dis_dfp_compare(UInt theInstr) {
10981 /* X-Form */
10982 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF
10983 UChar frA_addr = ifieldRegA( theInstr );
10984 UChar frB_addr = ifieldRegB( theInstr );
10985 UInt opc1 = ifieldOPC( theInstr );
10986 IRTemp frA;
10987 IRTemp frB;
10988
10989 IRTemp ccIR = newTemp( Ity_I32 );
10990 IRTemp ccPPC32 = newTemp( Ity_I32 );
10991
10992
10993 /* Note: Differences between dcmpu and dcmpo are only in exception
10994 flag settings, which aren't supported anyway. */
10995 switch (opc1) {
10996 case 0x3B: /* dcmpo and dcmpu, DFP 64-bit */
10997 DIP( "dcmpo %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr );
10998 frA = newTemp( Ity_D64 );
10999 frB = newTemp( Ity_D64 );
11000
11001 assign( frA, getDReg( frA_addr ) );
11002 assign( frB, getDReg( frB_addr ) );
11003
11004 assign( ccIR, binop( Iop_CmpD64, mkexpr( frA ), mkexpr( frB ) ) );
11005 break;
11006 case 0x3F: /* dcmpoq and dcmpuq,DFP 128-bit */
11007 DIP( "dcmpoq %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr );
11008 frA = newTemp( Ity_D128 );
11009 frB = newTemp( Ity_D128 );
11010
11011 assign( frA, getDReg_pair( frA_addr ) );
11012 assign( frB, getDReg_pair( frB_addr ) );
11013 assign( ccIR, binop( Iop_CmpD128, mkexpr( frA ), mkexpr( frB ) ) );
11014 break;
11015 default:
11016 vex_printf("dis_dfp_compare(ppc)(opc2)\n");
11017 return False;
11018 }
11019
11020 /* Map compare result from IR to PPC32 */
11021 /*
11022 FP cmp result | PPC | IR
11023 --------------------------
11024 UN | 0x1 | 0x45
11025 EQ | 0x2 | 0x40
11026 GT | 0x4 | 0x00
11027 LT | 0x8 | 0x01
11028 */
11029
11030 assign( ccPPC32,
11031 binop( Iop_Shl32,
11032 mkU32( 1 ),
11033 unop( Iop_32to8,
11034 binop( Iop_Or32,
11035 binop( Iop_And32,
11036 unop( Iop_Not32,
11037 binop( Iop_Shr32,
11038 mkexpr( ccIR ),
11039 mkU8( 5 ) ) ),
11040 mkU32( 2 ) ),
11041 binop( Iop_And32,
11042 binop( Iop_Xor32,
11043 mkexpr( ccIR ),
11044 binop( Iop_Shr32,
11045 mkexpr( ccIR ),
11046 mkU8( 6 ) ) ),
11047 mkU32( 1 ) ) ) ) ) );
11048
11049 putGST_field( PPC_GST_CR, mkexpr( ccPPC32 ), crfD );
11050 return True;
11051 }
11052
11053 /* Test class/group/exponent/significance instructions. */
dis_dfp_exponent_test(UInt theInstr)11054 static Bool dis_dfp_exponent_test ( UInt theInstr )
11055 {
11056 UChar frA_addr = ifieldRegA( theInstr );
11057 UChar frB_addr = ifieldRegB( theInstr );
11058 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) );
11059 IRTemp frA = newTemp( Ity_D64 );
11060 IRTemp frB = newTemp( Ity_D64 );
11061 IRTemp frA128 = newTemp( Ity_D128 );
11062 IRTemp frB128 = newTemp( Ity_D128 );
11063 UInt opc1 = ifieldOPC( theInstr );
11064 IRTemp gfield_A = newTemp( Ity_I32 );
11065 IRTemp gfield_B = newTemp( Ity_I32 );
11066 IRTemp gfield_mask = newTemp( Ity_I32 );
11067 IRTemp exponent_A = newTemp( Ity_I32 );
11068 IRTemp exponent_B = newTemp( Ity_I32 );
11069 IRTemp A_NaN_true = newTemp( Ity_I32 );
11070 IRTemp B_NaN_true = newTemp( Ity_I32 );
11071 IRTemp A_inf_true = newTemp( Ity_I32 );
11072 IRTemp B_inf_true = newTemp( Ity_I32 );
11073 IRTemp A_equals_B = newTemp( Ity_I32 );
11074 IRTemp finite_number = newTemp( Ity_I32 );
11075 IRTemp cc0 = newTemp( Ity_I32 );
11076 IRTemp cc1 = newTemp( Ity_I32 );
11077 IRTemp cc2 = newTemp( Ity_I32 );
11078 IRTemp cc3 = newTemp( Ity_I32 );
11079
11080 /* The dtstex and dtstexg instructions only differ in the size of the
11081 * exponent field. The following switch statement takes care of the size
11082 * specific setup. Once the value of the exponents, the G-field shift
11083 * and mask is setup the remaining code is identical.
11084 */
11085 switch (opc1) {
11086 case 0x3b: // dtstex Extended instruction setup
11087 DIP("dtstex %u,r%u,r%d\n", crfD, frA_addr, frB_addr);
11088 assign( frA, getDReg( frA_addr ) );
11089 assign( frB, getDReg( frB_addr ) );
11090 assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) );
11091 assign(exponent_A, unop( Iop_64to32,
11092 unop( Iop_ExtractExpD64,
11093 mkexpr( frA ) ) ) );
11094 assign(exponent_B, unop( Iop_64to32,
11095 unop( Iop_ExtractExpD64,
11096 mkexpr( frB ) ) ) );
11097 break;
11098
11099 case 0x3F: // dtstexq Quad instruction setup
11100 DIP("dtstexq %u,r%u,r%d\n", crfD, frA_addr, frB_addr);
11101 assign( frA128, getDReg_pair( frA_addr ) );
11102 assign( frB128, getDReg_pair( frB_addr ) );
11103 assign( frA, unop( Iop_D128HItoD64, mkexpr( frA128 ) ) );
11104 assign( frB, unop( Iop_D128HItoD64, mkexpr( frB128 ) ) );
11105 assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) );
11106 assign( exponent_A, unop( Iop_64to32,
11107 unop( Iop_ExtractExpD128,
11108 mkexpr( frA128 ) ) ) );
11109 assign( exponent_B, unop( Iop_64to32,
11110 unop( Iop_ExtractExpD128,
11111 mkexpr( frB128 ) ) ) );
11112 break;
11113 default:
11114 vex_printf("dis_dfp_exponent_test(ppc)(opc2)\n");
11115 return False;
11116 }
11117
11118 /* Extract the Gfield */
11119 assign( gfield_A, binop( Iop_And32,
11120 mkexpr( gfield_mask ),
11121 unop( Iop_64HIto32,
11122 unop( Iop_ReinterpD64asI64,
11123 mkexpr(frA) ) ) ) );
11124
11125 assign( gfield_B, binop( Iop_And32,
11126 mkexpr( gfield_mask ),
11127 unop( Iop_64HIto32,
11128 unop( Iop_ReinterpD64asI64,
11129 mkexpr(frB) ) ) ) );
11130
11131 /* check for NAN */
11132 assign( A_NaN_true, binop(Iop_Or32,
11133 unop( Iop_1Sto32,
11134 binop( Iop_CmpEQ32,
11135 mkexpr( gfield_A ),
11136 mkU32( 0x7C000000 ) ) ),
11137 unop( Iop_1Sto32,
11138 binop( Iop_CmpEQ32,
11139 mkexpr( gfield_A ),
11140 mkU32( 0x7E000000 ) )
11141 ) ) );
11142 assign( B_NaN_true, binop(Iop_Or32,
11143 unop( Iop_1Sto32,
11144 binop( Iop_CmpEQ32,
11145 mkexpr( gfield_B ),
11146 mkU32( 0x7C000000 ) ) ),
11147 unop( Iop_1Sto32,
11148 binop( Iop_CmpEQ32,
11149 mkexpr( gfield_B ),
11150 mkU32( 0x7E000000 ) )
11151 ) ) );
11152
11153 /* check for infinity */
11154 assign( A_inf_true,
11155 unop( Iop_1Sto32,
11156 binop( Iop_CmpEQ32,
11157 mkexpr( gfield_A ),
11158 mkU32( 0x78000000 ) ) ) );
11159
11160 assign( B_inf_true,
11161 unop( Iop_1Sto32,
11162 binop( Iop_CmpEQ32,
11163 mkexpr( gfield_B ),
11164 mkU32( 0x78000000 ) ) ) );
11165
11166 assign( finite_number,
11167 unop( Iop_Not32,
11168 binop( Iop_Or32,
11169 binop( Iop_Or32,
11170 mkexpr( A_NaN_true ),
11171 mkexpr( B_NaN_true ) ),
11172 binop( Iop_Or32,
11173 mkexpr( A_inf_true ),
11174 mkexpr( B_inf_true ) ) ) ) );
11175
11176 /* Calculate the condition code bits
11177 * If QNaN,SNaN, +infinity, -infinity then cc0, cc1 and cc2 are zero
11178 * regardless of the value of the comparisons and cc3 is 1. Otherwise,
11179 * cc0, cc1 and cc0 reflect the results of the comparisons.
11180 */
11181 assign( A_equals_B,
11182 binop( Iop_Or32,
11183 unop( Iop_1Uto32,
11184 binop( Iop_CmpEQ32,
11185 mkexpr( exponent_A ),
11186 mkexpr( exponent_B ) ) ),
11187 binop( Iop_Or32,
11188 binop( Iop_And32,
11189 mkexpr( A_inf_true ),
11190 mkexpr( B_inf_true ) ),
11191 binop( Iop_And32,
11192 mkexpr( A_NaN_true ),
11193 mkexpr( B_NaN_true ) ) ) ) );
11194
11195 assign( cc0, binop( Iop_And32,
11196 mkexpr( finite_number ),
11197 binop( Iop_Shl32,
11198 unop( Iop_1Uto32,
11199 binop( Iop_CmpLT32U,
11200 mkexpr( exponent_A ),
11201 mkexpr( exponent_B ) ) ),
11202 mkU8( 3 ) ) ) );
11203
11204 assign( cc1, binop( Iop_And32,
11205 mkexpr( finite_number ),
11206 binop( Iop_Shl32,
11207 unop( Iop_1Uto32,
11208 binop( Iop_CmpLT32U,
11209 mkexpr( exponent_B ),
11210 mkexpr( exponent_A ) ) ),
11211 mkU8( 2 ) ) ) );
11212
11213 assign( cc2, binop( Iop_Shl32,
11214 binop( Iop_And32,
11215 mkexpr( A_equals_B ),
11216 mkU32( 1 ) ),
11217 mkU8( 1 ) ) );
11218
11219 assign( cc3, binop( Iop_And32,
11220 unop( Iop_Not32, mkexpr( A_equals_B ) ),
11221 binop( Iop_And32,
11222 mkU32( 0x1 ),
11223 binop( Iop_Or32,
11224 binop( Iop_Or32,
11225 mkexpr ( A_inf_true ),
11226 mkexpr ( B_inf_true ) ),
11227 binop( Iop_Or32,
11228 mkexpr ( A_NaN_true ),
11229 mkexpr ( B_NaN_true ) ) )
11230 ) ) );
11231
11232 /* store the condition code */
11233 putGST_field( PPC_GST_CR,
11234 binop( Iop_Or32,
11235 mkexpr( cc0 ),
11236 binop( Iop_Or32,
11237 mkexpr( cc1 ),
11238 binop( Iop_Or32,
11239 mkexpr( cc2 ),
11240 mkexpr( cc3 ) ) ) ),
11241 crfD );
11242 return True;
11243 }
11244
11245 /* Test class/group/exponent/significance instructions. */
dis_dfp_class_test(UInt theInstr)11246 static Bool dis_dfp_class_test ( UInt theInstr )
11247 {
11248 UChar frA_addr = ifieldRegA( theInstr );
11249 IRTemp frA = newTemp( Ity_D64 );
11250 IRTemp abs_frA = newTemp( Ity_D64 );
11251 IRTemp frAI64_hi = newTemp( Ity_I64 );
11252 IRTemp frAI64_lo = newTemp( Ity_I64 );
11253 UInt opc1 = ifieldOPC( theInstr );
11254 UInt opc2 = ifieldOPClo9( theInstr );
11255 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF
11256 UInt DCM = IFIELD( theInstr, 10, 6 );
11257 IRTemp DCM_calc = newTemp( Ity_I32 );
11258 UInt max_exp = 0;
11259 UInt min_exp = 0;
11260 IRTemp min_subnormalD64 = newTemp( Ity_D64 );
11261 IRTemp min_subnormalD128 = newTemp( Ity_D128 );
11262 IRTemp significand64 = newTemp( Ity_D64 );
11263 IRTemp significand128 = newTemp( Ity_D128 );
11264 IRTemp exp_min_normal = newTemp( Ity_I64 );
11265 IRTemp exponent = newTemp( Ity_I32 );
11266
11267 IRTemp infinity_true = newTemp( Ity_I32 );
11268 IRTemp SNaN_true = newTemp( Ity_I32 );
11269 IRTemp QNaN_true = newTemp( Ity_I32 );
11270 IRTemp subnormal_true = newTemp( Ity_I32 );
11271 IRTemp normal_true = newTemp( Ity_I32 );
11272 IRTemp extreme_true = newTemp( Ity_I32 );
11273 IRTemp lmd = newTemp( Ity_I32 );
11274 IRTemp lmd_zero_true = newTemp( Ity_I32 );
11275 IRTemp zero_true = newTemp( Ity_I32 );
11276 IRTemp sign = newTemp( Ity_I32 );
11277 IRTemp field = newTemp( Ity_I32 );
11278 IRTemp ccIR_zero = newTemp( Ity_I32 );
11279 IRTemp ccIR_subnormal = newTemp( Ity_I32 );
11280
11281 /* UInt size = DFP_LONG; JRS:unused */
11282 IRTemp gfield = newTemp( Ity_I32 );
11283 IRTemp gfield_0_4_shift = newTemp( Ity_I8 );
11284 IRTemp gfield_mask = newTemp( Ity_I32 );
11285 IRTemp dcm0 = newTemp( Ity_I32 );
11286 IRTemp dcm1 = newTemp( Ity_I32 );
11287 IRTemp dcm2 = newTemp( Ity_I32 );
11288 IRTemp dcm3 = newTemp( Ity_I32 );
11289 IRTemp dcm4 = newTemp( Ity_I32 );
11290 IRTemp dcm5 = newTemp( Ity_I32 );
11291
11292 /* The only difference between the dtstdc and dtstdcq instructions is
11293 * size of the T and G fields. The calculation of the 4 bit field
11294 * is the same. Setup the parameters and values that are DFP size
11295 * specific. The rest of the code is independent of the DFP size.
11296 *
11297 * The Io_CmpD64 is used below. The instruction sets the ccIR values.
11298 * The interpretation of the ccIR values is as follows:
11299 *
11300 * DFP cmp result | IR
11301 * --------------------------
11302 * UN | 0x45
11303 * EQ | 0x40
11304 * GT | 0x00
11305 * LT | 0x01
11306 */
11307
11308 assign( frA, getDReg( frA_addr ) );
11309 assign( frAI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frA ) ) );
11310
11311 assign( abs_frA, unop( Iop_ReinterpI64asD64,
11312 binop( Iop_And64,
11313 unop( Iop_ReinterpD64asI64,
11314 mkexpr( frA ) ),
11315 mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ) );
11316 assign( gfield_0_4_shift, mkU8( 31 - 5 ) ); // G-field[0:4]
11317 switch (opc1) {
11318 case 0x3b: // dtstdc, dtstdg
11319 DIP("dtstd%s %u,r%u,%u\n", opc2 == 0xc2 ? "c" : "g",
11320 crfD, frA_addr, DCM);
11321 /* setup the parameters for the long format of the two instructions */
11322 assign( frAI64_lo, mkU64( 0 ) );
11323 assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) );
11324 max_exp = DFP_LONG_EXP_MAX;
11325 min_exp = DFP_LONG_EXP_MIN;
11326
11327 assign( exponent, unop( Iop_64to32,
11328 unop( Iop_ExtractExpD64,
11329 mkexpr( frA ) ) ) );
11330 assign( significand64,
11331 unop( Iop_ReinterpI64asD64,
11332 mkU64( 0x2234000000000001ULL ) ) ); // dfp 1.0
11333 assign( exp_min_normal,mkU64( 398 - 383 ) );
11334 assign( min_subnormalD64,
11335 binop( Iop_InsertExpD64,
11336 mkexpr( exp_min_normal ),
11337 mkexpr( significand64 ) ) );
11338
11339 assign( ccIR_subnormal,
11340 binop( Iop_CmpD64,
11341 mkexpr( abs_frA ),
11342 mkexpr( min_subnormalD64 ) ) );
11343
11344 /* compare absolute value of frA with zero */
11345 assign( ccIR_zero,
11346 binop( Iop_CmpD64,
11347 mkexpr( abs_frA ),
11348 unop( Iop_ReinterpI64asD64,
11349 mkU64( 0x2238000000000000ULL ) ) ) );
11350
11351 /* size = DFP_LONG; JRS: unused */
11352 break;
11353
11354 case 0x3F: // dtstdcq, dtstdgq
11355 DIP("dtstd%sq %u,r%u,%u\n", opc2 == 0xc2 ? "c" : "g",
11356 crfD, frA_addr, DCM);
11357 /* setup the parameters for the extended format of the
11358 * two instructions
11359 */
11360 assign( frAI64_lo, unop( Iop_ReinterpD64asI64,
11361 getDReg( frA_addr+1 ) ) );
11362
11363 assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) );
11364 max_exp = DFP_EXTND_EXP_MAX;
11365 min_exp = DFP_EXTND_EXP_MIN;
11366 assign( exponent, unop( Iop_64to32,
11367 unop( Iop_ExtractExpD128,
11368 getDReg_pair( frA_addr) ) ) );
11369
11370 /* create quand exponent for minimum normal number */
11371 assign( exp_min_normal, mkU64( 6176 - 6143 ) );
11372 assign( significand128,
11373 unop( Iop_D64toD128,
11374 unop( Iop_ReinterpI64asD64,
11375 mkU64( 0x2234000000000001ULL ) ) ) ); // dfp 1.0
11376
11377 assign( min_subnormalD128,
11378 binop( Iop_InsertExpD128,
11379 mkexpr( exp_min_normal ),
11380 mkexpr( significand128 ) ) );
11381
11382 assign( ccIR_subnormal,
11383 binop( Iop_CmpD128,
11384 binop( Iop_D64HLtoD128,
11385 unop( Iop_ReinterpI64asD64,
11386 binop( Iop_And64,
11387 unop( Iop_ReinterpD64asI64,
11388 mkexpr( frA ) ),
11389 mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ),
11390 getDReg( frA_addr+1 ) ),
11391 mkexpr( min_subnormalD128 ) ) );
11392 assign( ccIR_zero,
11393 binop( Iop_CmpD128,
11394 binop( Iop_D64HLtoD128,
11395 mkexpr( abs_frA ),
11396 getDReg( frA_addr+1 ) ),
11397 unop( Iop_D64toD128,
11398 unop( Iop_ReinterpI64asD64,
11399 mkU64( 0x0ULL ) ) ) ) );
11400
11401 /* size = DFP_EXTND; JRS:unused */
11402 break;
11403 default:
11404 vex_printf("dis_dfp_class_test(ppc)(opc2)\n");
11405 return False;
11406 }
11407
11408 /* The G-field is in the upper 32-bits. The I64 logical operations
11409 * do not seem to be supported in 32-bit mode so keep things as 32-bit
11410 * operations.
11411 */
11412 assign( gfield, binop( Iop_And32,
11413 mkexpr( gfield_mask ),
11414 unop( Iop_64HIto32,
11415 mkexpr(frAI64_hi) ) ) );
11416
11417 /* There is a lot of code that is the same to do the class and group
11418 * instructions. Later there is an if statement to handle the specific
11419 * instruction.
11420 *
11421 * Will be using I32 values, compares, shifts and logical operations for
11422 * this code as the 64-bit compare, shifts, logical operations are not
11423 * supported in 32-bit mode.
11424 */
11425
11426 /* Check the bits for Infinity, QNaN or Signaling NaN */
11427 assign( infinity_true,
11428 unop( Iop_1Sto32,
11429 binop( Iop_CmpEQ32,
11430 binop( Iop_And32,
11431 mkU32( 0x7C000000 ),
11432 mkexpr( gfield ) ),
11433 mkU32( 0x78000000 ) ) ) );
11434
11435 assign( SNaN_true,
11436 unop( Iop_1Sto32,
11437 binop( Iop_CmpEQ32,
11438 binop( Iop_And32,
11439 mkU32( 0x7E000000 ),
11440 mkexpr( gfield ) ),
11441 mkU32( 0x7E000000 ) ) ) );
11442
11443 assign( QNaN_true,
11444 binop( Iop_And32,
11445 unop( Iop_1Sto32,
11446 binop( Iop_CmpEQ32,
11447 binop( Iop_And32,
11448 mkU32( 0x7E000000 ),
11449 mkexpr( gfield ) ),
11450 mkU32( 0x7C000000 ) ) ),
11451 unop( Iop_Not32,
11452 mkexpr( SNaN_true ) ) ) );
11453
11454 assign( zero_true,
11455 binop( Iop_And32,
11456 unop(Iop_1Sto32,
11457 binop( Iop_CmpEQ32,
11458 mkexpr( ccIR_zero ),
11459 mkU32( 0x40 ) ) ), // ccIR code for Equal
11460 unop( Iop_Not32,
11461 binop( Iop_Or32,
11462 mkexpr( infinity_true ),
11463 binop( Iop_Or32,
11464 mkexpr( QNaN_true ),
11465 mkexpr( SNaN_true ) ) ) ) ) );
11466
11467 /* Do compare of frA the minimum normal value. Comparison is size
11468 * depenent and was done above to get the ccIR value.
11469 */
11470 assign( subnormal_true,
11471 binop( Iop_And32,
11472 binop( Iop_Or32,
11473 unop( Iop_1Sto32,
11474 binop( Iop_CmpEQ32,
11475 mkexpr( ccIR_subnormal ),
11476 mkU32( 0x40 ) ) ), // ccIR code for Equal
11477 unop( Iop_1Sto32,
11478 binop( Iop_CmpEQ32,
11479 mkexpr( ccIR_subnormal ),
11480 mkU32( 0x1 ) ) ) ), // ccIR code for LT
11481 unop( Iop_Not32,
11482 binop( Iop_Or32,
11483 binop( Iop_Or32,
11484 mkexpr( infinity_true ),
11485 mkexpr( zero_true) ),
11486 binop( Iop_Or32,
11487 mkexpr( QNaN_true ),
11488 mkexpr( SNaN_true ) ) ) ) ) );
11489
11490 /* Normal number is not subnormal, infinity, NaN or Zero */
11491 assign( normal_true,
11492 unop( Iop_Not32,
11493 binop( Iop_Or32,
11494 binop( Iop_Or32,
11495 mkexpr( infinity_true ),
11496 mkexpr( zero_true ) ),
11497 binop( Iop_Or32,
11498 mkexpr( subnormal_true ),
11499 binop( Iop_Or32,
11500 mkexpr( QNaN_true ),
11501 mkexpr( SNaN_true ) ) ) ) ) );
11502
11503 /* Calculate the DCM bit field based on the tests for the specific
11504 * instruction
11505 */
11506 if (opc2 == 0xC2) { // dtstdc, dtstdcq
11507 /* DCM[0:5] Bit Data Class definition
11508 * 0 Zero
11509 * 1 Subnormal
11510 * 2 Normal
11511 * 3 Infinity
11512 * 4 Quiet NaN
11513 * 5 Signaling NaN
11514 */
11515
11516 assign( dcm0, binop( Iop_Shl32,
11517 mkexpr( zero_true ),
11518 mkU8( 5 ) ) );
11519 assign( dcm1, binop( Iop_Shl32,
11520 binop( Iop_And32,
11521 mkexpr( subnormal_true ),
11522 mkU32( 1 ) ),
11523 mkU8( 4 ) ) );
11524 assign( dcm2, binop( Iop_Shl32,
11525 binop( Iop_And32,
11526 mkexpr( normal_true ),
11527 mkU32( 1 ) ),
11528 mkU8( 3 ) ) );
11529 assign( dcm3, binop( Iop_Shl32,
11530 binop( Iop_And32,
11531 mkexpr( infinity_true),
11532 mkU32( 1 ) ),
11533 mkU8( 2 ) ) );
11534 assign( dcm4, binop( Iop_Shl32,
11535 binop( Iop_And32,
11536 mkexpr( QNaN_true ),
11537 mkU32( 1 ) ),
11538 mkU8( 1 ) ) );
11539 assign( dcm5, binop( Iop_And32, mkexpr( SNaN_true), mkU32( 1 ) ) );
11540
11541 } else if (opc2 == 0xE2) { // dtstdg, dtstdgq
11542 /* check if the exponent is extreme */
11543 assign( extreme_true, binop( Iop_Or32,
11544 unop( Iop_1Sto32,
11545 binop( Iop_CmpEQ32,
11546 mkexpr( exponent ),
11547 mkU32( max_exp ) ) ),
11548 unop( Iop_1Sto32,
11549 binop( Iop_CmpEQ32,
11550 mkexpr( exponent ),
11551 mkU32( min_exp ) ) ) ) );
11552
11553 /* Check if LMD is zero */
11554 Get_lmd( &lmd, binop( Iop_Shr32,
11555 mkexpr( gfield ), mkU8( 31 - 5 ) ) );
11556
11557 assign( lmd_zero_true, unop( Iop_1Sto32,
11558 binop( Iop_CmpEQ32,
11559 mkexpr( lmd ),
11560 mkU32( 0 ) ) ) );
11561
11562 /* DCM[0:5] Bit Data Class definition
11563 * 0 Zero with non-extreme exponent
11564 * 1 Zero with extreme exponent
11565 * 2 Subnormal or (Normal with extreme exponent)
11566 * 3 Normal with non-extreme exponent and
11567 * leftmost zero digit in significand
11568 * 4 Normal with non-extreme exponent and
11569 * leftmost nonzero digit in significand
11570 * 5 Special symbol (Infinity, QNaN, or SNaN)
11571 */
11572 assign( dcm0, binop( Iop_Shl32,
11573 binop( Iop_And32,
11574 binop( Iop_And32,
11575 unop( Iop_Not32,
11576 mkexpr( extreme_true ) ),
11577 mkexpr( zero_true ) ),
11578 mkU32( 0x1 ) ),
11579 mkU8( 5 ) ) );
11580
11581 assign( dcm1, binop( Iop_Shl32,
11582 binop( Iop_And32,
11583 binop( Iop_And32,
11584 mkexpr( extreme_true ),
11585 mkexpr( zero_true ) ),
11586 mkU32( 0x1 ) ),
11587 mkU8( 4 ) ) );
11588
11589 assign( dcm2, binop( Iop_Shl32,
11590 binop( Iop_And32,
11591 binop( Iop_Or32,
11592 binop( Iop_And32,
11593 mkexpr( extreme_true ),
11594 mkexpr( normal_true ) ),
11595 mkexpr( subnormal_true ) ),
11596 mkU32( 0x1 ) ),
11597 mkU8( 3 ) ) );
11598
11599 assign( dcm3, binop( Iop_Shl32,
11600 binop( Iop_And32,
11601 binop( Iop_And32,
11602 binop( Iop_And32,
11603 unop( Iop_Not32,
11604 mkexpr( extreme_true ) ),
11605 mkexpr( normal_true ) ),
11606 unop( Iop_1Sto32,
11607 binop( Iop_CmpEQ32,
11608 mkexpr( lmd ),
11609 mkU32( 0 ) ) ) ),
11610 mkU32( 0x1 ) ),
11611 mkU8( 2 ) ) );
11612
11613 assign( dcm4, binop( Iop_Shl32,
11614 binop( Iop_And32,
11615 binop( Iop_And32,
11616 binop( Iop_And32,
11617 unop( Iop_Not32,
11618 mkexpr( extreme_true ) ),
11619 mkexpr( normal_true ) ),
11620 unop( Iop_1Sto32,
11621 binop( Iop_CmpNE32,
11622 mkexpr( lmd ),
11623 mkU32( 0 ) ) ) ),
11624 mkU32( 0x1 ) ),
11625 mkU8( 1 ) ) );
11626
11627 assign( dcm5, binop( Iop_And32,
11628 binop( Iop_Or32,
11629 mkexpr( SNaN_true),
11630 binop( Iop_Or32,
11631 mkexpr( QNaN_true),
11632 mkexpr( infinity_true) ) ),
11633 mkU32( 0x1 ) ) );
11634 }
11635
11636 /* create DCM field */
11637 assign( DCM_calc,
11638 binop( Iop_Or32,
11639 mkexpr( dcm0 ),
11640 binop( Iop_Or32,
11641 mkexpr( dcm1 ),
11642 binop( Iop_Or32,
11643 mkexpr( dcm2 ),
11644 binop( Iop_Or32,
11645 mkexpr( dcm3 ),
11646 binop( Iop_Or32,
11647 mkexpr( dcm4 ),
11648 mkexpr( dcm5 ) ) ) ) ) ) );
11649
11650 /* Get the sign of the DFP number, ignore sign for QNaN */
11651 assign( sign,
11652 unop( Iop_1Uto32,
11653 binop( Iop_CmpEQ32,
11654 binop( Iop_Shr32,
11655 unop( Iop_64HIto32, mkexpr( frAI64_hi ) ),
11656 mkU8( 63 - 32 ) ),
11657 mkU32( 1 ) ) ) );
11658
11659 /* This instruction generates a four bit field to be stored in the
11660 * condition code register. The condition code register consists of 7
11661 * fields. The field to be written to is specified by the BF (AKA crfD)
11662 * field.
11663 *
11664 * The field layout is as follows:
11665 *
11666 * Field Meaning
11667 * 0000 Operand positive with no match
11668 * 0100 Operand positive with at least one match
11669 * 0001 Operand negative with no match
11670 * 0101 Operand negative with at least one match
11671 */
11672 assign( field, binop( Iop_Or32,
11673 binop( Iop_Shl32,
11674 mkexpr( sign ),
11675 mkU8( 3 ) ),
11676 binop( Iop_Shl32,
11677 unop( Iop_1Uto32,
11678 binop( Iop_CmpNE32,
11679 binop( Iop_And32,
11680 mkU32( DCM ),
11681 mkexpr( DCM_calc ) ),
11682 mkU32( 0 ) ) ),
11683 mkU8( 1 ) ) ) );
11684
11685 putGST_field( PPC_GST_CR, mkexpr( field ), crfD );
11686 return True;
11687 }
11688
dis_dfp_bcd(UInt theInstr)11689 static Bool dis_dfp_bcd(UInt theInstr) {
11690 UInt opc2 = ifieldOPClo10( theInstr );
11691 ULong sp = IFIELD(theInstr, 19, 2);
11692 ULong s = IFIELD(theInstr, 20, 1);
11693 UChar frT_addr = ifieldRegDS( theInstr );
11694 UChar frB_addr = ifieldRegB( theInstr );
11695 IRTemp frB = newTemp( Ity_D64 );
11696 IRTemp frBI64 = newTemp( Ity_I64 );
11697 IRTemp result = newTemp( Ity_I64 );
11698 IRTemp resultD64 = newTemp( Ity_D64 );
11699 IRTemp bcd64 = newTemp( Ity_I64 );
11700 IRTemp bcd_u = newTemp( Ity_I32 );
11701 IRTemp bcd_l = newTemp( Ity_I32 );
11702 IRTemp dbcd_u = newTemp( Ity_I32 );
11703 IRTemp dbcd_l = newTemp( Ity_I32 );
11704 IRTemp lmd = newTemp( Ity_I32 );
11705
11706 assign( frB, getDReg( frB_addr ) );
11707 assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) );
11708
11709 switch ( opc2 ) {
11710 case 0x142: // ddedpd DFP Decode DPD to BCD
11711 DIP( "ddedpd %llu,r%u,r%u\n", sp, frT_addr, frB_addr );
11712
11713 assign( bcd64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) );
11714 assign( bcd_u, unop( Iop_64HIto32, mkexpr( bcd64 ) ) );
11715 assign( bcd_l, unop( Iop_64to32, mkexpr( bcd64 ) ) );
11716
11717 if ( ( sp == 0 ) || ( sp == 1 ) ) {
11718 /* Unsigned BCD string */
11719 Get_lmd( &lmd,
11720 binop( Iop_Shr32,
11721 unop( Iop_64HIto32, mkexpr( frBI64 ) ),
11722 mkU8( 31 - 5 ) ) ); // G-field[0:4]
11723
11724 assign( result,
11725 binop( Iop_32HLto64,
11726 binop( Iop_Or32,
11727 binop( Iop_Shl32, mkexpr( lmd ), mkU8( 28 ) ),
11728 mkexpr( bcd_u ) ),
11729 mkexpr( bcd_l ) ) );
11730
11731 } else {
11732 /* Signed BCD string, the cases for sp 2 and 3 only differ in how
11733 * the positive and negative values are encoded in the least
11734 * significant bits.
11735 */
11736 IRTemp sign = newTemp( Ity_I32 );
11737
11738 if (sp == 2) {
11739 /* Positive sign = 0xC, negative sign = 0xD */
11740
11741 assign( sign,
11742 binop( Iop_Or32,
11743 binop( Iop_Shr32,
11744 unop( Iop_64HIto32, mkexpr( frBI64 ) ),
11745 mkU8( 31 ) ),
11746 mkU32( 0xC ) ) );
11747
11748 } else if ( sp == 3 ) {
11749 /* Positive sign = 0xF, negative sign = 0xD */
11750 IRTemp tmp32 = newTemp( Ity_I32 );
11751
11752 /* Complement sign bit then OR into bit position 1 */
11753 assign( tmp32,
11754 binop( Iop_Xor32,
11755 binop( Iop_Shr32,
11756 unop( Iop_64HIto32, mkexpr( frBI64 ) ),
11757 mkU8( 30 ) ),
11758 mkU32( 0x2 ) ) );
11759
11760 assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) );
11761
11762 } else {
11763 vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
11764 }
11765
11766 /* Put sign in bottom 4 bits, move most significant 4-bits from
11767 * bcd_l to bcd_u.
11768 */
11769 assign( result,
11770 binop( Iop_32HLto64,
11771 binop( Iop_Or32,
11772 binop( Iop_Shr32,
11773 mkexpr( bcd_l ),
11774 mkU8( 28 ) ),
11775 binop( Iop_Shl32,
11776 mkexpr( bcd_u ),
11777 mkU8( 4 ) ) ),
11778 binop( Iop_Or32,
11779 mkexpr( sign ),
11780 binop( Iop_Shl32,
11781 mkexpr( bcd_l ),
11782 mkU8( 4 ) ) ) ) );
11783 }
11784
11785 putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result ) ) );
11786 break;
11787
11788 case 0x342: // denbcd DFP Encode BCD to DPD
11789 {
11790 IRTemp valid_mask = newTemp( Ity_I32 );
11791 IRTemp invalid_mask = newTemp( Ity_I32 );
11792 IRTemp without_lmd = newTemp( Ity_I64 );
11793 IRTemp tmp64 = newTemp( Ity_I64 );
11794 IRTemp dbcd64 = newTemp( Ity_I64 );
11795 IRTemp left_exp = newTemp( Ity_I32 );
11796 IRTemp g0_4 = newTemp( Ity_I32 );
11797
11798 DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr );
11799
11800 if ( s == 0 ) {
11801 /* Unsigned BCD string */
11802 assign( dbcd64, unop( Iop_BCDtoDPB, mkexpr(frBI64 ) ) );
11803 assign( dbcd_u, unop( Iop_64HIto32, mkexpr( dbcd64 ) ) );
11804 assign( dbcd_l, unop( Iop_64to32, mkexpr( dbcd64 ) ) );
11805
11806 assign( lmd,
11807 binop( Iop_Shr32,
11808 binop( Iop_And32,
11809 unop( Iop_64HIto32, mkexpr( frBI64 ) ),
11810 mkU32( 0xF0000000 ) ),
11811 mkU8( 28 ) ) );
11812
11813 assign( invalid_mask,
11814 bcd_digit_inval( unop( Iop_64HIto32, mkexpr( frBI64 ) ),
11815 unop( Iop_64to32, mkexpr( frBI64 ) ) ) );
11816 assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
11817
11818 assign( without_lmd,
11819 unop( Iop_ReinterpD64asI64,
11820 binop( Iop_InsertExpD64,
11821 mkU64( DFP_LONG_BIAS ),
11822 unop( Iop_ReinterpI64asD64,
11823 binop( Iop_32HLto64,
11824 mkexpr( dbcd_u ),
11825 mkexpr( dbcd_l ) ) ) ) ) );
11826 assign( left_exp,
11827 binop( Iop_Shr32,
11828 binop( Iop_And32,
11829 unop( Iop_64HIto32, mkexpr( without_lmd ) ),
11830 mkU32( 0x60000000 ) ),
11831 mkU8( 29 ) ) );
11832
11833 assign( g0_4,
11834 binop( Iop_Shl32,
11835 Gfield_encoding( mkexpr( left_exp ), mkexpr( lmd ) ),
11836 mkU8( 26 ) ) );
11837
11838 assign( tmp64,
11839 binop( Iop_32HLto64,
11840 binop( Iop_Or32,
11841 binop( Iop_And32,
11842 unop( Iop_64HIto32,
11843 mkexpr( without_lmd ) ),
11844 mkU32( 0x83FFFFFF ) ),
11845 mkexpr( g0_4 ) ),
11846 unop( Iop_64to32, mkexpr( without_lmd ) ) ) );
11847
11848 } else if ( s == 1 ) {
11849 IRTemp sign = newTemp( Ity_I32 );
11850 IRTemp sign_bit = newTemp( Ity_I32 );
11851 IRTemp pos_sign_mask = newTemp( Ity_I32 );
11852 IRTemp neg_sign_mask = newTemp( Ity_I32 );
11853 IRTemp tmp = newTemp( Ity_I64 );
11854
11855 /* Signed BCD string, least significant 4 bits are sign bits
11856 * positive sign = 0xC, negative sign = 0xD
11857 */
11858 assign( tmp, unop( Iop_BCDtoDPB,
11859 binop( Iop_32HLto64,
11860 binop( Iop_Shr32,
11861 unop( Iop_64HIto32,
11862 mkexpr( frBI64 ) ),
11863 mkU8( 4 ) ),
11864 binop( Iop_Or32,
11865 binop( Iop_Shr32,
11866 unop( Iop_64to32,
11867 mkexpr( frBI64 ) ),
11868 mkU8( 4 ) ),
11869 binop( Iop_Shl32,
11870 unop( Iop_64HIto32,
11871 mkexpr( frBI64 ) ),
11872 mkU8( 28 ) ) ) ) ) );
11873
11874 assign( dbcd_u, unop( Iop_64HIto32, mkexpr( tmp ) ) );
11875 assign( dbcd_l, unop( Iop_64to32, mkexpr( tmp ) ) );
11876
11877 /* Get the sign of the BCD string. */
11878 assign( sign,
11879 binop( Iop_And32,
11880 unop( Iop_64to32, mkexpr( frBI64 ) ),
11881 mkU32( 0xF ) ) );
11882
11883 assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) );
11884 assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) );
11885 assign( sign_bit,
11886 Generate_sign_bit( mkexpr( pos_sign_mask ),
11887 mkexpr( neg_sign_mask ) ) );
11888
11889 /* Check for invalid sign and BCD digit. Don't check the bottom
11890 * four bits of bcd_l as that is the sign value.
11891 */
11892 assign( invalid_mask,
11893 Generate_inv_mask(
11894 bcd_digit_inval( unop( Iop_64HIto32,
11895 mkexpr( frBI64 ) ),
11896 binop( Iop_Shr32,
11897 unop( Iop_64to32,
11898 mkexpr( frBI64 ) ),
11899 mkU8( 4 ) ) ),
11900 mkexpr( pos_sign_mask ),
11901 mkexpr( neg_sign_mask ) ) );
11902
11903 assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
11904
11905 /* Generate the result assuming the sign value was valid. */
11906 assign( tmp64,
11907 unop( Iop_ReinterpD64asI64,
11908 binop( Iop_InsertExpD64,
11909 mkU64( DFP_LONG_BIAS ),
11910 unop( Iop_ReinterpI64asD64,
11911 binop( Iop_32HLto64,
11912 binop( Iop_Or32,
11913 mkexpr( dbcd_u ),
11914 mkexpr( sign_bit ) ),
11915 mkexpr( dbcd_l ) ) ) ) ) );
11916 }
11917
11918 /* Generate the value to store depending on the validity of the
11919 * sign value and the validity of the BCD digits.
11920 */
11921 assign( resultD64,
11922 unop( Iop_ReinterpI64asD64,
11923 binop( Iop_32HLto64,
11924 binop( Iop_Or32,
11925 binop( Iop_And32,
11926 mkexpr( valid_mask ),
11927 unop( Iop_64HIto32,
11928 mkexpr( tmp64 ) ) ),
11929 binop( Iop_And32,
11930 mkU32( 0x7C000000 ),
11931 mkexpr( invalid_mask ) ) ),
11932 binop( Iop_Or32,
11933 binop( Iop_And32,
11934 mkexpr( valid_mask ),
11935 unop( Iop_64to32, mkexpr( tmp64 ) ) ),
11936 binop( Iop_And32,
11937 mkU32( 0x0 ),
11938 mkexpr( invalid_mask ) ) ) ) ) );
11939 putDReg( frT_addr, mkexpr( resultD64 ) );
11940 }
11941 break;
11942 default:
11943 vpanic( "ERROR: dis_dfp_bcd(ppc), undefined opc2 case " );
11944 return False;
11945 }
11946 return True;
11947 }
11948
dis_dfp_bcdq(UInt theInstr)11949 static Bool dis_dfp_bcdq( UInt theInstr )
11950 {
11951 UInt opc2 = ifieldOPClo10( theInstr );
11952 ULong sp = IFIELD(theInstr, 19, 2);
11953 ULong s = IFIELD(theInstr, 20, 1);
11954 IRTemp frB_hi = newTemp( Ity_D64 );
11955 IRTemp frB_lo = newTemp( Ity_D64 );
11956 IRTemp frBI64_hi = newTemp( Ity_I64 );
11957 IRTemp frBI64_lo = newTemp( Ity_I64 );
11958 UChar frT_addr = ifieldRegDS( theInstr );
11959 UChar frB_addr = ifieldRegB( theInstr );
11960
11961 IRTemp lmd = newTemp( Ity_I32 );
11962 IRTemp result_hi = newTemp( Ity_I64 );
11963 IRTemp result_lo = newTemp( Ity_I64 );
11964
11965 assign( frB_hi, getDReg( frB_addr ) );
11966 assign( frB_lo, getDReg( frB_addr + 1 ) );
11967 assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) );
11968 assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) );
11969
11970 switch ( opc2 ) {
11971 case 0x142: // ddedpdq DFP Decode DPD to BCD
11972 {
11973 IRTemp low_60_u = newTemp( Ity_I32 );
11974 IRTemp low_60_l = newTemp( Ity_I32 );
11975 IRTemp mid_60_u = newTemp( Ity_I32 );
11976 IRTemp mid_60_l = newTemp( Ity_I32 );
11977 IRTemp top_12_l = newTemp( Ity_I32 );
11978
11979 DIP( "ddedpdq %llu,r%u,r%u\n", sp, frT_addr, frB_addr );
11980
11981 /* Note, instruction only stores the lower 32 BCD digits in
11982 * the result
11983 */
11984 Generate_132_bit_bcd_string( mkexpr( frBI64_hi ),
11985 mkexpr( frBI64_lo ),
11986 &top_12_l,
11987 &mid_60_u,
11988 &mid_60_l,
11989 &low_60_u,
11990 &low_60_l );
11991
11992 if ( ( sp == 0 ) || ( sp == 1 ) ) {
11993 /* Unsigned BCD string */
11994 assign( result_hi,
11995 binop( Iop_32HLto64,
11996 binop( Iop_Or32,
11997 binop( Iop_Shl32,
11998 mkexpr( top_12_l ),
11999 mkU8( 24 ) ),
12000 binop( Iop_Shr32,
12001 mkexpr( mid_60_u ),
12002 mkU8( 4 ) ) ),
12003 binop( Iop_Or32,
12004 binop( Iop_Shl32,
12005 mkexpr( mid_60_u ),
12006 mkU8( 28 ) ),
12007 binop( Iop_Shr32,
12008 mkexpr( mid_60_l ),
12009 mkU8( 4 ) ) ) ) );
12010
12011 assign( result_lo,
12012 binop( Iop_32HLto64,
12013 binop( Iop_Or32,
12014 binop( Iop_Shl32,
12015 mkexpr( mid_60_l ),
12016 mkU8( 28 ) ),
12017 mkexpr( low_60_u ) ),
12018 mkexpr( low_60_l ) ) );
12019
12020 } else {
12021 /* Signed BCD string, the cases for sp 2 and 3 only differ in how
12022 * the positive and negative values are encoded in the least
12023 * significant bits.
12024 */
12025 IRTemp sign = newTemp( Ity_I32 );
12026
12027 if ( sp == 2 ) {
12028 /* Positive sign = 0xC, negative sign = 0xD */
12029 assign( sign,
12030 binop( Iop_Or32,
12031 binop( Iop_Shr32,
12032 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
12033 mkU8( 31 ) ),
12034 mkU32( 0xC ) ) );
12035
12036 } else if ( sp == 3 ) {
12037 IRTemp tmp32 = newTemp( Ity_I32 );
12038
12039 /* Positive sign = 0xF, negative sign = 0xD.
12040 * Need to complement sign bit then OR into bit position 1.
12041 */
12042 assign( tmp32,
12043 binop( Iop_Xor32,
12044 binop( Iop_Shr32,
12045 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
12046 mkU8( 30 ) ),
12047 mkU32( 0x2 ) ) );
12048
12049 assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) );
12050
12051 } else {
12052 vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
12053 }
12054
12055 assign( result_hi,
12056 binop( Iop_32HLto64,
12057 binop( Iop_Or32,
12058 binop( Iop_Shl32,
12059 mkexpr( top_12_l ),
12060 mkU8( 28 ) ),
12061 mkexpr( mid_60_u ) ),
12062 mkexpr( mid_60_l ) ) );
12063
12064 assign( result_lo,
12065 binop( Iop_32HLto64,
12066 binop( Iop_Or32,
12067 binop( Iop_Shl32,
12068 mkexpr( low_60_u ),
12069 mkU8( 4 ) ),
12070 binop( Iop_Shr32,
12071 mkexpr( low_60_l ),
12072 mkU8( 28 ) ) ),
12073 binop( Iop_Or32,
12074 binop( Iop_Shl32,
12075 mkexpr( low_60_l ),
12076 mkU8( 4 ) ),
12077 mkexpr( sign ) ) ) );
12078 }
12079
12080 putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) );
12081 putDReg( frT_addr + 1,
12082 unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) );
12083 }
12084 break;
12085 case 0x342: // denbcdq DFP Encode BCD to DPD
12086 {
12087 IRTemp valid_mask = newTemp( Ity_I32 );
12088 IRTemp invalid_mask = newTemp( Ity_I32 );
12089 IRTemp result128 = newTemp( Ity_D128 );
12090 IRTemp dfp_significand = newTemp( Ity_D128 );
12091 IRTemp tmp_hi = newTemp( Ity_I64 );
12092 IRTemp tmp_lo = newTemp( Ity_I64 );
12093 IRTemp dbcd_top_l = newTemp( Ity_I32 );
12094 IRTemp dbcd_mid_u = newTemp( Ity_I32 );
12095 IRTemp dbcd_mid_l = newTemp( Ity_I32 );
12096 IRTemp dbcd_low_u = newTemp( Ity_I32 );
12097 IRTemp dbcd_low_l = newTemp( Ity_I32 );
12098 IRTemp bcd_top_8 = newTemp( Ity_I64 );
12099 IRTemp bcd_mid_60 = newTemp( Ity_I64 );
12100 IRTemp bcd_low_60 = newTemp( Ity_I64 );
12101 IRTemp sign_bit = newTemp( Ity_I32 );
12102 IRTemp tmptop10 = newTemp( Ity_I64 );
12103 IRTemp tmpmid50 = newTemp( Ity_I64 );
12104 IRTemp tmplow50 = newTemp( Ity_I64 );
12105 IRTemp inval_bcd_digit_mask = newTemp( Ity_I32 );
12106
12107 DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr );
12108
12109 if ( s == 0 ) {
12110 /* Unsigned BCD string */
12111 assign( sign_bit, mkU32( 0 ) ); // set to zero for unsigned string
12112
12113 assign( bcd_top_8,
12114 binop( Iop_32HLto64,
12115 mkU32( 0 ),
12116 binop( Iop_And32,
12117 binop( Iop_Shr32,
12118 unop( Iop_64HIto32,
12119 mkexpr( frBI64_hi ) ),
12120 mkU8( 24 ) ),
12121 mkU32( 0xFF ) ) ) );
12122 assign( bcd_mid_60,
12123 binop( Iop_32HLto64,
12124 binop( Iop_Or32,
12125 binop( Iop_Shr32,
12126 unop( Iop_64to32,
12127 mkexpr( frBI64_hi ) ),
12128 mkU8( 28 ) ),
12129 binop( Iop_Shl32,
12130 unop( Iop_64HIto32,
12131 mkexpr( frBI64_hi ) ),
12132 mkU8( 4 ) ) ),
12133 binop( Iop_Or32,
12134 binop( Iop_Shl32,
12135 unop( Iop_64to32,
12136 mkexpr( frBI64_hi ) ),
12137 mkU8( 4 ) ),
12138 binop( Iop_Shr32,
12139 unop( Iop_64HIto32,
12140 mkexpr( frBI64_lo ) ),
12141 mkU8( 28 ) ) ) ) );
12142
12143 /* Note, the various helper functions ignores top 4-bits */
12144 assign( bcd_low_60, mkexpr( frBI64_lo ) );
12145
12146 assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr( bcd_top_8 ) ) );
12147 assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) );
12148
12149 assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr( bcd_mid_60 ) ) );
12150 assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) );
12151 assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) );
12152
12153 assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) );
12154 assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) );
12155 assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) );
12156
12157 /* The entire BCD string fits in lower 110-bits. The LMD = 0,
12158 * value is not part of the final result. Only the right most
12159 * BCD digits are stored.
12160 */
12161 assign( lmd, mkU32( 0 ) );
12162
12163 assign( invalid_mask,
12164 binop( Iop_Or32,
12165 bcd_digit_inval( mkU32( 0 ),
12166 unop( Iop_64to32,
12167 mkexpr( bcd_top_8 ) ) ),
12168 binop( Iop_Or32,
12169 bcd_digit_inval( unop( Iop_64HIto32,
12170 mkexpr( bcd_mid_60 ) ),
12171 unop( Iop_64to32,
12172 mkexpr( bcd_mid_60 ) ) ),
12173 bcd_digit_inval( unop( Iop_64HIto32,
12174 mkexpr( bcd_low_60 ) ),
12175 unop( Iop_64to32,
12176 mkexpr( bcd_low_60 ) )
12177 ) ) ) );
12178
12179 } else if ( s == 1 ) {
12180 IRTemp sign = newTemp( Ity_I32 );
12181 IRTemp zero = newTemp( Ity_I32 );
12182 IRTemp pos_sign_mask = newTemp( Ity_I32 );
12183 IRTemp neg_sign_mask = newTemp( Ity_I32 );
12184
12185 /* The sign of the BCD string is stored in lower 4 bits */
12186 assign( sign,
12187 binop( Iop_And32,
12188 unop( Iop_64to32, mkexpr( frBI64_lo ) ),
12189 mkU32( 0xF ) ) );
12190 assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) );
12191 assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) );
12192 assign( sign_bit,
12193 Generate_sign_bit( mkexpr( pos_sign_mask ),
12194 mkexpr( neg_sign_mask ) ) );
12195
12196 /* Generate the value assuminig the sign and BCD digits are vaild */
12197 assign( bcd_top_8,
12198 binop( Iop_32HLto64,
12199 mkU32( 0x0 ),
12200 binop( Iop_Shr32,
12201 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
12202 mkU8( 28 ) ) ) );
12203
12204 /* The various helper routines ignore the upper 4-bits */
12205 assign( bcd_mid_60, mkexpr( frBI64_hi ) );
12206
12207 /* Remove bottom four sign bits */
12208 assign( bcd_low_60,
12209 binop( Iop_32HLto64,
12210 binop( Iop_Shr32,
12211 unop( Iop_64HIto32,
12212 mkexpr( frBI64_lo ) ),
12213 mkU8( 4 ) ),
12214 binop( Iop_Or32,
12215 binop( Iop_Shl32,
12216 unop( Iop_64HIto32,
12217 mkexpr( frBI64_lo ) ),
12218 mkU8( 28 ) ),
12219 binop( Iop_Shr32,
12220 unop( Iop_64to32,
12221 mkexpr( frBI64_lo ) ),
12222 mkU8( 4 ) ) ) ) );
12223 assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr(bcd_top_8 ) ) );
12224 assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) );
12225
12226 assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr(bcd_mid_60 ) ) );
12227 assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) );
12228 assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) );
12229
12230 assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) );
12231 assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) );
12232 assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) );
12233
12234 /* The entire BCD string fits in lower 110-bits. The LMD value
12235 * is not stored in the final result for the DFP Long instruction.
12236 */
12237 assign( lmd, mkU32( 0 ) );
12238
12239 /* Check for invalid sign and invalid BCD digit. Don't check the
12240 * bottom four bits of frBI64_lo as that is the sign value.
12241 */
12242 assign( zero, mkU32( 0 ) );
12243 assign( inval_bcd_digit_mask,
12244 binop( Iop_Or32,
12245 bcd_digit_inval( mkexpr( zero ),
12246 unop( Iop_64to32,
12247 mkexpr( bcd_top_8 ) ) ),
12248 binop( Iop_Or32,
12249 bcd_digit_inval( unop( Iop_64HIto32,
12250 mkexpr( bcd_mid_60 ) ),
12251 unop( Iop_64to32,
12252 mkexpr( bcd_mid_60 ) ) ),
12253 bcd_digit_inval( unop( Iop_64HIto32,
12254 mkexpr( frBI64_lo ) ),
12255 binop( Iop_Shr32,
12256 unop( Iop_64to32,
12257 mkexpr( frBI64_lo ) ),
12258 mkU8( 4 ) ) ) ) ) );
12259 assign( invalid_mask,
12260 Generate_inv_mask( mkexpr( inval_bcd_digit_mask ),
12261 mkexpr( pos_sign_mask ),
12262 mkexpr( neg_sign_mask ) ) );
12263
12264 }
12265
12266 assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
12267
12268 /* Calculate the value of the result assuming sign and BCD digits
12269 * are all valid.
12270 */
12271 assign( dfp_significand,
12272 binop( Iop_D64HLtoD128,
12273 unop( Iop_ReinterpI64asD64,
12274 binop( Iop_32HLto64,
12275 binop( Iop_Or32,
12276 mkexpr( sign_bit ),
12277 mkexpr( dbcd_top_l ) ),
12278 binop( Iop_Or32,
12279 binop( Iop_Shl32,
12280 mkexpr( dbcd_mid_u ),
12281 mkU8( 18 ) ),
12282 binop( Iop_Shr32,
12283 mkexpr( dbcd_mid_l ),
12284 mkU8( 14 ) ) ) ) ),
12285 unop( Iop_ReinterpI64asD64,
12286 binop( Iop_32HLto64,
12287 binop( Iop_Or32,
12288 mkexpr( dbcd_low_u ),
12289 binop( Iop_Shl32,
12290 mkexpr( dbcd_mid_l ),
12291 mkU8( 18 ) ) ),
12292 mkexpr( dbcd_low_l ) ) ) ) );
12293
12294 /* Break the result back down to 32-bit chunks and replace chunks.
12295 * If there was an invalid BCD digit or invalid sign value, replace
12296 * the calculated result with the invalid bit string.
12297 */
12298 assign( result128,
12299 binop( Iop_InsertExpD128,
12300 mkU64( DFP_EXTND_BIAS ),
12301 mkexpr( dfp_significand ) ) );
12302
12303 assign( tmp_hi,
12304 unop( Iop_ReinterpD64asI64,
12305 unop( Iop_D128HItoD64, mkexpr( result128 ) ) ) );
12306
12307 assign( tmp_lo,
12308 unop( Iop_ReinterpD64asI64,
12309 unop( Iop_D128LOtoD64, mkexpr( result128 ) ) ) );
12310
12311 assign( result_hi,
12312 binop( Iop_32HLto64,
12313 binop( Iop_Or32,
12314 binop( Iop_And32,
12315 mkexpr( valid_mask ),
12316 unop( Iop_64HIto32, mkexpr( tmp_hi ) ) ),
12317 binop( Iop_And32,
12318 mkU32( 0x7C000000 ),
12319 mkexpr( invalid_mask ) ) ),
12320 binop( Iop_Or32,
12321 binop( Iop_And32,
12322 mkexpr( valid_mask ),
12323 unop( Iop_64to32, mkexpr( tmp_hi ) ) ),
12324 binop( Iop_And32,
12325 mkU32( 0x0 ),
12326 mkexpr( invalid_mask ) ) ) ) );
12327
12328 assign( result_lo,
12329 binop( Iop_32HLto64,
12330 binop( Iop_Or32,
12331 binop( Iop_And32,
12332 mkexpr( valid_mask ),
12333 unop( Iop_64HIto32, mkexpr( tmp_lo ) ) ),
12334 binop( Iop_And32,
12335 mkU32( 0x0 ),
12336 mkexpr( invalid_mask ) ) ),
12337 binop( Iop_Or32,
12338 binop( Iop_And32,
12339 mkexpr( valid_mask ),
12340 unop( Iop_64to32, mkexpr( tmp_lo ) ) ),
12341 binop( Iop_And32,
12342 mkU32( 0x0 ),
12343 mkexpr( invalid_mask ) ) ) ) );
12344
12345 putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) );
12346 putDReg( frT_addr + 1,
12347 unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) );
12348
12349 }
12350 break;
12351 default:
12352 vpanic( "ERROR: dis_dfp_bcdq(ppc), undefined opc2 case " );
12353 break;
12354 }
12355 return True;
12356 }
12357
dis_dfp_significant_digits(UInt theInstr)12358 static Bool dis_dfp_significant_digits( UInt theInstr )
12359 {
12360 UChar frA_addr = ifieldRegA( theInstr );
12361 UChar frB_addr = ifieldRegB( theInstr );
12362 IRTemp frA = newTemp( Ity_D64 );
12363 UInt opc1 = ifieldOPC( theInstr );
12364 IRTemp B_sig = newTemp( Ity_I8 );
12365 IRTemp K = newTemp( Ity_I8 );
12366 IRTemp lmd_B = newTemp( Ity_I32 );
12367 IRTemp field = newTemp( Ity_I32 );
12368 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF
12369 IRTemp Unordered_true = newTemp( Ity_I32 );
12370 IRTemp Eq_true_mask = newTemp( Ity_I32 );
12371 IRTemp Lt_true_mask = newTemp( Ity_I32 );
12372 IRTemp Gt_true_mask = newTemp( Ity_I32 );
12373 IRTemp KisZero_true_mask = newTemp( Ity_I32 );
12374 IRTemp KisZero_false_mask = newTemp( Ity_I32 );
12375
12376 /* Get the reference singificance stored in frA */
12377 assign( frA, getDReg( frA_addr ) );
12378
12379 /* Convert from 64 bit to 8 bits in two steps. The Iop_64to8 is not
12380 * supported in 32-bit mode.
12381 */
12382 assign( K, unop( Iop_32to8,
12383 binop( Iop_And32,
12384 unop( Iop_64to32,
12385 unop( Iop_ReinterpD64asI64,
12386 mkexpr( frA ) ) ),
12387 mkU32( 0x3F ) ) ) );
12388
12389 switch ( opc1 ) {
12390 case 0x3b: // dtstsf DFP Test Significance
12391 {
12392 IRTemp frB = newTemp( Ity_D64 );
12393 IRTemp frBI64 = newTemp( Ity_I64 );
12394 IRTemp B_bcd_u = newTemp( Ity_I32 );
12395 IRTemp B_bcd_l = newTemp( Ity_I32 );
12396 IRTemp tmp64 = newTemp( Ity_I64 );
12397
12398 DIP( "dtstsf %u,r%u,r%u\n", crfD, frA_addr, frB_addr );
12399
12400 assign( frB, getDReg( frB_addr ) );
12401 assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) );
12402
12403 /* Get the BCD string for the value stored in a series of I32 values.
12404 * Count the number of leading zeros. Subtract the number of leading
12405 * zeros from 16 (maximum number of significant digits in DFP
12406 * Long).
12407 */
12408 Get_lmd( &lmd_B,
12409 binop( Iop_Shr32,
12410 unop( Iop_64HIto32, mkexpr( frBI64 ) ),
12411 mkU8( 31 - 5 ) ) ); // G-field[0:4]
12412
12413 assign( tmp64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) );
12414 assign( B_bcd_u, unop( Iop_64HIto32, mkexpr( tmp64 ) ) );
12415 assign( B_bcd_l, unop( Iop_64to32, mkexpr( tmp64 ) ) );
12416
12417 assign( B_sig,
12418 binop( Iop_Sub8,
12419 mkU8( DFP_LONG_MAX_SIG_DIGITS ),
12420 Count_leading_zeros_60( mkexpr( lmd_B ),
12421 mkexpr( B_bcd_u ),
12422 mkexpr( B_bcd_l ) ) ) );
12423 assign( Unordered_true, Check_unordered( mkexpr( frBI64 ) ) );
12424 }
12425 break;
12426 case 0x3F: // dtstsfq DFP Test Significance
12427 {
12428 IRTemp frB_hi = newTemp( Ity_D64 );
12429 IRTemp frB_lo = newTemp( Ity_D64 );
12430 IRTemp frBI64_hi = newTemp( Ity_I64 );
12431 IRTemp frBI64_lo = newTemp( Ity_I64 );
12432 IRTemp B_low_60_u = newTemp( Ity_I32 );
12433 IRTemp B_low_60_l = newTemp( Ity_I32 );
12434 IRTemp B_mid_60_u = newTemp( Ity_I32 );
12435 IRTemp B_mid_60_l = newTemp( Ity_I32 );
12436 IRTemp B_top_12_l = newTemp( Ity_I32 );
12437
12438 DIP( "dtstsfq %u,r%u,r%u\n", crfD, frA_addr, frB_addr );
12439
12440 assign( frB_hi, getDReg( frB_addr ) );
12441 assign( frB_lo, getDReg( frB_addr + 1 ) );
12442
12443 assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) );
12444 assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) );
12445
12446 /* Get the BCD string for the value stored in a series of I32 values.
12447 * Count the number of leading zeros. Subtract the number of leading
12448 * zeros from 32 (maximum number of significant digits in DFP
12449 * extended).
12450 */
12451 Get_lmd( &lmd_B,
12452 binop( Iop_Shr32,
12453 unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
12454 mkU8( 31 - 5 ) ) ); // G-field[0:4]
12455
12456 Generate_132_bit_bcd_string( mkexpr( frBI64_hi ),
12457 mkexpr( frBI64_lo ),
12458 &B_top_12_l,
12459 &B_mid_60_u,
12460 &B_mid_60_l,
12461 &B_low_60_u,
12462 &B_low_60_l );
12463
12464 assign( B_sig,
12465 binop( Iop_Sub8,
12466 mkU8( DFP_EXTND_MAX_SIG_DIGITS ),
12467 Count_leading_zeros_128( mkexpr( lmd_B ),
12468 mkexpr( B_top_12_l ),
12469 mkexpr( B_mid_60_u ),
12470 mkexpr( B_mid_60_l ),
12471 mkexpr( B_low_60_u ),
12472 mkexpr( B_low_60_l ) ) ) );
12473
12474 assign( Unordered_true, Check_unordered( mkexpr( frBI64_hi ) ) );
12475 }
12476 break;
12477 }
12478
12479 /* Compare (16 - cnt[0]) against K and set the condition code field
12480 * accordingly.
12481 *
12482 * The field layout is as follows:
12483 *
12484 * bit[3:0] Description
12485 * 3 K != 0 and K < Number of significant digits if FRB
12486 * 2 K != 0 and K > Number of significant digits if FRB OR K = 0
12487 * 1 K != 0 and K = Number of significant digits if FRB
12488 * 0 K ? Number of significant digits if FRB
12489 */
12490 assign( Eq_true_mask,
12491 unop( Iop_1Sto32,
12492 binop( Iop_CmpEQ32,
12493 unop( Iop_8Uto32, mkexpr( K ) ),
12494 unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) );
12495 assign( Lt_true_mask,
12496 unop( Iop_1Sto32,
12497 binop( Iop_CmpLT32U,
12498 unop( Iop_8Uto32, mkexpr( K ) ),
12499 unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) );
12500 assign( Gt_true_mask,
12501 unop( Iop_1Sto32,
12502 binop( Iop_CmpLT32U,
12503 unop( Iop_8Uto32, mkexpr( B_sig ) ),
12504 unop( Iop_8Uto32, mkexpr( K ) ) ) ) );
12505
12506 assign( KisZero_true_mask,
12507 unop( Iop_1Sto32,
12508 binop( Iop_CmpEQ32,
12509 unop( Iop_8Uto32, mkexpr( K ) ),
12510 mkU32( 0 ) ) ) );
12511 assign( KisZero_false_mask,
12512 unop( Iop_1Sto32,
12513 binop( Iop_CmpNE32,
12514 unop( Iop_8Uto32, mkexpr( K ) ),
12515 mkU32( 0 ) ) ) );
12516
12517 assign( field,
12518 binop( Iop_Or32,
12519 binop( Iop_And32,
12520 mkexpr( KisZero_false_mask ),
12521 binop( Iop_Or32,
12522 binop( Iop_And32,
12523 mkexpr( Lt_true_mask ),
12524 mkU32( 0x8 ) ),
12525 binop( Iop_Or32,
12526 binop( Iop_And32,
12527 mkexpr( Gt_true_mask ),
12528 mkU32( 0x4 ) ),
12529 binop( Iop_And32,
12530 mkexpr( Eq_true_mask ),
12531 mkU32( 0x2 ) ) ) ) ),
12532 binop( Iop_And32,
12533 mkexpr( KisZero_true_mask ),
12534 mkU32( 0x4 ) ) ) );
12535
12536 putGST_field( PPC_GST_CR,
12537 binop( Iop_Or32,
12538 binop( Iop_And32,
12539 mkexpr( Unordered_true ),
12540 mkU32( 0x1 ) ),
12541 binop( Iop_And32,
12542 unop( Iop_Not32, mkexpr( Unordered_true ) ),
12543 mkexpr( field ) ) ),
12544 crfD );
12545
12546 return True;
12547 }
12548
12549 /*------------------------------------------------------------*/
12550 /*--- AltiVec Instruction Translation ---*/
12551 /*------------------------------------------------------------*/
12552
12553 /*
12554 Altivec Cache Control Instructions (Data Streams)
12555 */
dis_av_datastream(UInt theInstr)12556 static Bool dis_av_datastream ( UInt theInstr )
12557 {
12558 /* X-Form */
12559 UChar opc1 = ifieldOPC(theInstr);
12560 UChar flag_T = toUChar( IFIELD( theInstr, 25, 1 ) );
12561 UChar flag_A = flag_T;
12562 UChar b23to24 = toUChar( IFIELD( theInstr, 23, 2 ) );
12563 UChar STRM = toUChar( IFIELD( theInstr, 21, 2 ) );
12564 UChar rA_addr = ifieldRegA(theInstr);
12565 UChar rB_addr = ifieldRegB(theInstr);
12566 UInt opc2 = ifieldOPClo10(theInstr);
12567 UChar b0 = ifieldBIT0(theInstr);
12568
12569 if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) {
12570 vex_printf("dis_av_datastream(ppc)(instr)\n");
12571 return False;
12572 }
12573
12574 switch (opc2) {
12575 case 0x156: // dst (Data Stream Touch, AV p115)
12576 DIP("dst%s r%u,r%u,%d\n", flag_T ? "t" : "",
12577 rA_addr, rB_addr, STRM);
12578 break;
12579
12580 case 0x176: // dstst (Data Stream Touch for Store, AV p117)
12581 DIP("dstst%s r%u,r%u,%d\n", flag_T ? "t" : "",
12582 rA_addr, rB_addr, STRM);
12583 break;
12584
12585 case 0x336: // dss (Data Stream Stop, AV p114)
12586 if (rA_addr != 0 || rB_addr != 0) {
12587 vex_printf("dis_av_datastream(ppc)(opc2,dst)\n");
12588 return False;
12589 }
12590 if (flag_A == 0) {
12591 DIP("dss %d\n", STRM);
12592 } else {
12593 DIP("dssall\n");
12594 }
12595 break;
12596
12597 default:
12598 vex_printf("dis_av_datastream(ppc)(opc2)\n");
12599 return False;
12600 }
12601 return True;
12602 }
12603
12604 /*
12605 AltiVec Processor Control Instructions
12606 */
dis_av_procctl(UInt theInstr)12607 static Bool dis_av_procctl ( UInt theInstr )
12608 {
12609 /* VX-Form */
12610 UChar opc1 = ifieldOPC(theInstr);
12611 UChar vD_addr = ifieldRegDS(theInstr);
12612 UChar vA_addr = ifieldRegA(theInstr);
12613 UChar vB_addr = ifieldRegB(theInstr);
12614 UInt opc2 = IFIELD( theInstr, 0, 11 );
12615
12616 if (opc1 != 0x4) {
12617 vex_printf("dis_av_procctl(ppc)(instr)\n");
12618 return False;
12619 }
12620
12621 switch (opc2) {
12622 case 0x604: // mfvscr (Move from VSCR, AV p129)
12623 if (vA_addr != 0 || vB_addr != 0) {
12624 vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
12625 return False;
12626 }
12627 DIP("mfvscr v%d\n", vD_addr);
12628 putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) );
12629 break;
12630
12631 case 0x644: { // mtvscr (Move to VSCR, AV p130)
12632 IRTemp vB = newTemp(Ity_V128);
12633 if (vD_addr != 0 || vA_addr != 0) {
12634 vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
12635 return False;
12636 }
12637 DIP("mtvscr v%d\n", vB_addr);
12638 assign( vB, getVReg(vB_addr));
12639 putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) );
12640 break;
12641 }
12642 default:
12643 vex_printf("dis_av_procctl(ppc)(opc2)\n");
12644 return False;
12645 }
12646 return True;
12647 }
12648
12649 /*
12650 * VSX scalar and vector convert instructions
12651 */
12652 static Bool
dis_vx_conv(UInt theInstr,UInt opc2)12653 dis_vx_conv ( UInt theInstr, UInt opc2 )
12654 {
12655 /* XX2-Form */
12656 UChar opc1 = ifieldOPC( theInstr );
12657 UChar XT = ifieldRegXT( theInstr );
12658 UChar XB = ifieldRegXB( theInstr );
12659 IRTemp xB, xB2;
12660 IRTemp b3, b2, b1, b0;
12661 xB = xB2 = IRTemp_INVALID;
12662
12663 if (opc1 != 0x3C) {
12664 vex_printf( "dis_vx_conv(ppc)(instr)\n" );
12665 return False;
12666 }
12667
12668 /* Create and assign temps only as needed for the given instruction. */
12669 switch (opc2) {
12670 // scalar double-precision floating point argument
12671 case 0x2B0: case 0x0b0: case 0x290: case 0x212: case 0x216: case 0x090:
12672 xB = newTemp(Ity_F64);
12673 assign( xB,
12674 unop( Iop_ReinterpI64asF64,
12675 unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
12676 break;
12677 // vector double-precision floating point arguments
12678 case 0x1b0: case 0x312: case 0x390: case 0x190: case 0x3B0:
12679
12680 xB = newTemp(Ity_F64);
12681 xB2 = newTemp(Ity_F64);
12682 assign( xB,
12683 unop( Iop_ReinterpI64asF64,
12684 unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
12685 assign( xB2,
12686 unop( Iop_ReinterpI64asF64,
12687 unop( Iop_V128to64, getVSReg( XB ) ) ) );
12688 break;
12689 // vector single precision or [un]signed integer word arguments
12690 case 0x130: case 0x392: case 0x330: case 0x310: case 0x110:
12691 case 0x1f0: case 0x1d0:
12692 b3 = b2 = b1 = b0 = IRTemp_INVALID;
12693 breakV128to4x32(getVSReg(XB), &b3, &b2, &b1, &b0);
12694 break;
12695 // vector [un]signed integer doubleword argument
12696 case 0x3f0: case 0x370: case 0x3d0: case 0x350:
12697 xB = newTemp(Ity_I64);
12698 assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
12699 xB2 = newTemp(Ity_I64);
12700 assign( xB2, unop( Iop_V128to64, getVSReg( XB ) ) );
12701 break;
12702 // scalar [un]signed integer doubleword argument
12703 case 0x250: case 0x270: case 0x2D0: case 0x2F0:
12704 xB = newTemp(Ity_I64);
12705 assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
12706 break;
12707 // scalar single precision argument
12708 case 0x292: // xscvspdp
12709 xB = newTemp(Ity_I32);
12710
12711 assign( xB, handle_SNaN_to_QNaN_32(unop( Iop_64HIto32,
12712 unop( Iop_V128HIto64,
12713 getVSReg( XB ) ) ) ) );
12714 break;
12715 case 0x296: // xscvspdpn (non signaling version of xscvpdp)
12716 xB = newTemp(Ity_I32);
12717 assign( xB,
12718 unop( Iop_64HIto32, unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
12719 break;
12720
12721 /* Certain instructions have their complete implementation in the main switch statement
12722 * that follows this one; thus we have a "do nothing" case for those instructions here.
12723 */
12724 case 0x170: case 0x150:
12725 break; // do nothing
12726
12727 default:
12728 vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
12729 return False;
12730 }
12731
12732
12733 switch (opc2) {
12734 case 0x2B0:
12735 // xscvdpsxds (VSX Scalar truncate Double-Precision to integer and Convert
12736 // to Signed Integer Doubleword format with Saturate)
12737 DIP("xscvdpsxds v%u,v%u\n", XT, XB);
12738 putVSReg( XT,
12739 binop( Iop_64HLtoV128, binop( Iop_F64toI64S,
12740 mkU32( Irrm_ZERO ),
12741 mkexpr( xB ) ), mkU64( 0 ) ) );
12742 break;
12743 case 0x0b0: // xscvdpsxws (VSX Scalar truncate Double-Precision to integer and
12744 // Convert to Signed Integer Word format with Saturate)
12745 DIP("xscvdpsxws v%u,v%u\n", XT, XB);
12746 putVSReg( XT,
12747 binop( Iop_64HLtoV128,
12748 unop( Iop_32Sto64,
12749 binop( Iop_F64toI32S,
12750 mkU32( Irrm_ZERO ),
12751 mkexpr( xB ) ) ),
12752 mkU64( 0ULL ) ) );
12753 break;
12754 case 0x290: // xscvdpuxds (VSX Scalar truncate Double-Precision integer and Convert
12755 // to Unsigned Integer Doubleword format with Saturate)
12756 DIP("xscvdpuxds v%u,v%u\n", XT, XB);
12757 putVSReg( XT,
12758 binop( Iop_64HLtoV128,
12759 binop( Iop_F64toI64U,
12760 mkU32( Irrm_ZERO ),
12761 mkexpr( xB ) ),
12762 mkU64( 0ULL ) ) );
12763 break;
12764 case 0x270:
12765 // xscvsxdsp (VSX Scalar Convert and round Signed Integer Doubleword
12766 // to Single-Precision format)
12767 DIP("xscvsxdsp v%u,v%u\n", XT, XB);
12768 putVSReg( XT,
12769 binop( Iop_64HLtoV128,
12770 unop( Iop_ReinterpF64asI64,
12771 binop( Iop_RoundF64toF32,
12772 get_IR_roundingmode(),
12773 binop( Iop_I64StoF64,
12774 get_IR_roundingmode(),
12775 mkexpr( xB ) ) ) ),
12776 mkU64( 0 ) ) );
12777 break;
12778 case 0x2F0:
12779 // xscvsxddp (VSX Scalar Convert and round Signed Integer Doubleword to
12780 // Double-Precision format)
12781 DIP("xscvsxddp v%u,v%u\n", XT, XB);
12782 putVSReg( XT,
12783 binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
12784 binop( Iop_I64StoF64, get_IR_roundingmode(),
12785 mkexpr( xB ) ) ),
12786 mkU64( 0 ) ) );
12787 break;
12788 case 0x250:
12789 // xscvuxdsp (VSX Scalar Convert and round Unsigned Integer
12790 // Doubleword to Singel-Precision format)
12791 DIP("xscvuxdsp v%u,v%u\n", XT, XB);
12792 putVSReg( XT,
12793 binop( Iop_64HLtoV128,
12794 unop( Iop_ReinterpF64asI64,
12795 binop( Iop_RoundF64toF32,
12796 get_IR_roundingmode(),
12797 binop( Iop_I64UtoF64,
12798 get_IR_roundingmode(),
12799 mkexpr( xB ) ) ) ),
12800 mkU64( 0 ) ) );
12801 break;
12802 case 0x2D0:
12803 // xscvuxddp (VSX Scalar Convert and round Unsigned Integer Doubleword to
12804 // Double-Precision format)
12805 DIP("xscvuxddp v%u,v%u\n", XT, XB);
12806 putVSReg( XT,
12807 binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
12808 binop( Iop_I64UtoF64, get_IR_roundingmode(),
12809 mkexpr( xB ) ) ),
12810 mkU64( 0 ) ) );
12811 break;
12812 case 0x1b0: // xvcvdpsxws (VSX Vector truncate Double-Precision to integer and Convert
12813 // to Signed Integer Word format with Saturate)
12814 {
12815 IRTemp hiResult_32 = newTemp(Ity_I32);
12816 IRTemp loResult_32 = newTemp(Ity_I32);
12817 IRExpr* rmZero = mkU32(Irrm_ZERO);
12818
12819 DIP("xvcvdpsxws v%u,v%u\n", XT, XB);
12820 assign(hiResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB)));
12821 assign(loResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB2)));
12822 putVSReg( XT,
12823 binop( Iop_64HLtoV128,
12824 unop( Iop_32Sto64, mkexpr( hiResult_32 ) ),
12825 unop( Iop_32Sto64, mkexpr( loResult_32 ) ) ) );
12826 break;
12827 }
12828 case 0x130: case 0x110: // xvcvspsxws, xvcvspuxws
12829 // (VSX Vector truncate Single-Precision to integer and
12830 // Convert to [Un]signed Integer Word format with Saturate)
12831 {
12832 IRExpr * b0_result, * b1_result, * b2_result, * b3_result;
12833 IRTemp tempResult = newTemp(Ity_V128);
12834 IRTemp res0 = newTemp(Ity_I32);
12835 IRTemp res1 = newTemp(Ity_I32);
12836 IRTemp res2 = newTemp(Ity_I32);
12837 IRTemp res3 = newTemp(Ity_I32);
12838 IRTemp hi64 = newTemp(Ity_I64);
12839 IRTemp lo64 = newTemp(Ity_I64);
12840 Bool un_signed = (opc2 == 0x110);
12841 IROp op = un_signed ? Iop_QFtoI32Ux4_RZ : Iop_QFtoI32Sx4_RZ;
12842
12843 DIP("xvcvsp%sxws v%u,v%u\n", un_signed ? "u" : "s", XT, XB);
12844 /* The xvcvsp{s|u}xws instruction is similar to vct{s|u}xs, except if src is a NaN,
12845 * then result is set to 0x80000000. */
12846 assign(tempResult, unop(op, getVSReg(XB)));
12847 assign( hi64, unop(Iop_V128HIto64, mkexpr(tempResult)) );
12848 assign( lo64, unop(Iop_V128to64, mkexpr(tempResult)) );
12849 assign( res3, unop(Iop_64HIto32, mkexpr(hi64)) );
12850 assign( res2, unop(Iop_64to32, mkexpr(hi64)) );
12851 assign( res1, unop(Iop_64HIto32, mkexpr(lo64)) );
12852 assign( res0, unop(Iop_64to32, mkexpr(lo64)) );
12853
12854 b3_result = IRExpr_ITE(is_NaN_32(b3),
12855 // then: result is 0x{8|0}80000000
12856 mkU32(un_signed ? 0x00000000 : 0x80000000),
12857 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
12858 mkexpr(res3));
12859 b2_result = IRExpr_ITE(is_NaN_32(b2),
12860 // then: result is 0x{8|0}80000000
12861 mkU32(un_signed ? 0x00000000 : 0x80000000),
12862 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
12863 mkexpr(res2));
12864 b1_result = IRExpr_ITE(is_NaN_32(b1),
12865 // then: result is 0x{8|0}80000000
12866 mkU32(un_signed ? 0x00000000 : 0x80000000),
12867 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
12868 mkexpr(res1));
12869 b0_result = IRExpr_ITE(is_NaN_32(b0),
12870 // then: result is 0x{8|0}80000000
12871 mkU32(un_signed ? 0x00000000 : 0x80000000),
12872 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
12873 mkexpr(res0));
12874
12875 putVSReg( XT,
12876 binop( Iop_64HLtoV128,
12877 binop( Iop_32HLto64, b3_result, b2_result ),
12878 binop( Iop_32HLto64, b1_result, b0_result ) ) );
12879 break;
12880 }
12881 case 0x212: // xscvdpsp (VSX Scalar round Double-Precision to single-precision and
12882 // Convert to Single-Precision format
12883 DIP("xscvdpsp v%u,v%u\n", XT, XB);
12884 putVSReg( XT,
12885 binop( Iop_64HLtoV128,
12886 binop( Iop_32HLto64,
12887 unop( Iop_ReinterpF32asI32,
12888 unop( Iop_TruncF64asF32,
12889 binop( Iop_RoundF64toF32,
12890 get_IR_roundingmode(),
12891 mkexpr( xB ) ) ) ),
12892 mkU32( 0 ) ),
12893 mkU64( 0ULL ) ) );
12894 break;
12895 case 0x216: /* xscvdpspn (VSX Scalar convert scalar Single-Precision to
12896 vector Single-Precision non-signalling */
12897 DIP("xscvdpspn v%u,v%u\n", XT, XB);
12898 putVSReg( XT,
12899 binop( Iop_64HLtoV128,
12900 binop( Iop_32HLto64,
12901 unop( Iop_ReinterpF32asI32,
12902 unop( Iop_TruncF64asF32,
12903 mkexpr( xB ) ) ),
12904 mkU32( 0 ) ),
12905 mkU64( 0ULL ) ) );
12906 break;
12907 case 0x090: // xscvdpuxws (VSX Scalar truncate Double-Precision to integer
12908 // and Convert to Unsigned Integer Word format with Saturate)
12909 DIP("xscvdpuxws v%u,v%u\n", XT, XB);
12910 putVSReg( XT,
12911 binop( Iop_64HLtoV128,
12912 binop( Iop_32HLto64,
12913 mkU32( 0 ),
12914 binop( Iop_F64toI32U,
12915 mkU32( Irrm_ZERO ),
12916 mkexpr( xB ) ) ),
12917 mkU64( 0ULL ) ) );
12918 break;
12919 case 0x292: // xscvspdp (VSX Scalar Convert Single-Precision to Double-Precision format, signaling)
12920 DIP("xscvspdp v%u,v%u\n", XT, XB);
12921 putVSReg( XT,
12922 binop( Iop_64HLtoV128,
12923 unop( Iop_ReinterpF64asI64,
12924 unop( Iop_F32toF64,
12925 unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
12926 mkU64( 0ULL ) ) );
12927 break;
12928 case 0x296: // xscvspdpn (VSX Scalar Convert Single-Precision to Double-Precision format Non signaling)
12929 DIP("xscvspdpn v%u,v%u\n", XT, XB);
12930 putVSReg( XT,
12931 binop( Iop_64HLtoV128,
12932 unop( Iop_ReinterpF64asI64,
12933 unop( Iop_F32toF64,
12934 unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
12935 mkU64( 0ULL ) ) );
12936 break;
12937 case 0x312: // xvcvdpsp (VSX Vector round Double-Precision to single-precision
12938 // and Convert to Single-Precision format)
12939 DIP("xvcvdpsp v%u,v%u\n", XT, XB);
12940 putVSReg( XT,
12941 binop( Iop_64HLtoV128,
12942 binop( Iop_32HLto64,
12943 unop( Iop_ReinterpF32asI32,
12944 unop( Iop_TruncF64asF32,
12945 binop( Iop_RoundF64toF32,
12946 get_IR_roundingmode(),
12947 mkexpr( xB ) ) ) ),
12948 mkU32( 0 ) ),
12949 binop( Iop_32HLto64,
12950 unop( Iop_ReinterpF32asI32,
12951 unop( Iop_TruncF64asF32,
12952 binop( Iop_RoundF64toF32,
12953 get_IR_roundingmode(),
12954 mkexpr( xB2 ) ) ) ),
12955 mkU32( 0 ) ) ) );
12956 break;
12957 case 0x390: // xvcvdpuxds (VSX Vector truncate Double-Precision to integer
12958 // and Convert to Unsigned Integer Doubleword format
12959 // with Saturate)
12960 DIP("xvcvdpuxds v%u,v%u\n", XT, XB);
12961 putVSReg( XT,
12962 binop( Iop_64HLtoV128,
12963 binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
12964 binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
12965 break;
12966 case 0x190: // xvcvdpuxws (VSX Vector truncate Double-Precision to integer and
12967 // Convert to Unsigned Integer Word format with Saturate)
12968 DIP("xvcvdpuxws v%u,v%u\n", XT, XB);
12969 putVSReg( XT,
12970 binop( Iop_64HLtoV128,
12971 binop( Iop_32HLto64,
12972 binop( Iop_F64toI32U,
12973 mkU32( Irrm_ZERO ),
12974 mkexpr( xB ) ),
12975 mkU32( 0 ) ),
12976 binop( Iop_32HLto64,
12977 binop( Iop_F64toI32U,
12978 mkU32( Irrm_ZERO ),
12979 mkexpr( xB2 ) ),
12980 mkU32( 0 ) ) ) );
12981 break;
12982 case 0x392: // xvcvspdp (VSX Vector Convert Single-Precision to Double-Precision format)
12983 DIP("xvcvspdp v%u,v%u\n", XT, XB);
12984 putVSReg( XT,
12985 binop( Iop_64HLtoV128,
12986 unop( Iop_ReinterpF64asI64,
12987 unop( Iop_F32toF64,
12988 unop( Iop_ReinterpI32asF32,
12989 handle_SNaN_to_QNaN_32( mkexpr( b3 ) ) ) ) ),
12990 unop( Iop_ReinterpF64asI64,
12991 unop( Iop_F32toF64,
12992 unop( Iop_ReinterpI32asF32,
12993 handle_SNaN_to_QNaN_32( mkexpr( b1 ) ) ) ) ) ) );
12994 break;
12995 case 0x330: // xvcvspsxds (VSX Vector truncate Single-Precision to integer and
12996 // Convert to Signed Integer Doubleword format with Saturate)
12997 DIP("xvcvspsxds v%u,v%u\n", XT, XB);
12998 putVSReg( XT,
12999 binop( Iop_64HLtoV128,
13000 binop( Iop_F64toI64S,
13001 mkU32( Irrm_ZERO ),
13002 unop( Iop_F32toF64,
13003 unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
13004 binop( Iop_F64toI64S,
13005 mkU32( Irrm_ZERO ),
13006 unop( Iop_F32toF64,
13007 unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
13008 break;
13009 case 0x310: // xvcvspuxds (VSX Vector truncate Single-Precision to integer and
13010 // Convert to Unsigned Integer Doubleword format with Saturate)
13011 DIP("xvcvspuxds v%u,v%u\n", XT, XB);
13012 putVSReg( XT,
13013 binop( Iop_64HLtoV128,
13014 binop( Iop_F64toI64U,
13015 mkU32( Irrm_ZERO ),
13016 unop( Iop_F32toF64,
13017 unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
13018 binop( Iop_F64toI64U,
13019 mkU32( Irrm_ZERO ),
13020 unop( Iop_F32toF64,
13021 unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
13022 break;
13023 case 0x3B0: // xvcvdpsxds (VSX Vector truncate Double-Precision to integer and
13024 // Convert to Signed Integer Doubleword format with Saturate)
13025 DIP("xvcvdpsxds v%u,v%u\n", XT, XB);
13026 putVSReg( XT,
13027 binop( Iop_64HLtoV128,
13028 binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
13029 binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
13030 break;
13031 case 0x3f0: // xvcvsxddp (VSX Vector Convert and round Signed Integer Doubleword
13032 // to Double-Precision format)
13033 DIP("xvcvsxddp v%u,v%u\n", XT, XB);
13034 putVSReg( XT,
13035 binop( Iop_64HLtoV128,
13036 unop( Iop_ReinterpF64asI64,
13037 binop( Iop_I64StoF64,
13038 get_IR_roundingmode(),
13039 mkexpr( xB ) ) ),
13040 unop( Iop_ReinterpF64asI64,
13041 binop( Iop_I64StoF64,
13042 get_IR_roundingmode(),
13043 mkexpr( xB2 ) ) ) ) );
13044 break;
13045 case 0x3d0: // xvcvuxddp (VSX Vector Convert and round Unsigned Integer Doubleword
13046 // to Double-Precision format)
13047 DIP("xvcvuxddp v%u,v%u\n", XT, XB);
13048 putVSReg( XT,
13049 binop( Iop_64HLtoV128,
13050 unop( Iop_ReinterpF64asI64,
13051 binop( Iop_I64UtoF64,
13052 get_IR_roundingmode(),
13053 mkexpr( xB ) ) ),
13054 unop( Iop_ReinterpF64asI64,
13055 binop( Iop_I64UtoF64,
13056 get_IR_roundingmode(),
13057 mkexpr( xB2 ) ) ) ) );
13058
13059 break;
13060 case 0x370: // xvcvsxdsp (VSX Vector Convert and round Signed Integer Doubleword
13061 // to Single-Precision format)
13062 DIP("xvcvsxddp v%u,v%u\n", XT, XB);
13063 putVSReg( XT,
13064 binop( Iop_64HLtoV128,
13065 binop( Iop_32HLto64,
13066 unop( Iop_ReinterpF32asI32,
13067 unop( Iop_TruncF64asF32,
13068 binop( Iop_RoundF64toF32,
13069 get_IR_roundingmode(),
13070 binop( Iop_I64StoF64,
13071 get_IR_roundingmode(),
13072 mkexpr( xB ) ) ) ) ),
13073 mkU32( 0 ) ),
13074 binop( Iop_32HLto64,
13075 unop( Iop_ReinterpF32asI32,
13076 unop( Iop_TruncF64asF32,
13077 binop( Iop_RoundF64toF32,
13078 get_IR_roundingmode(),
13079 binop( Iop_I64StoF64,
13080 get_IR_roundingmode(),
13081 mkexpr( xB2 ) ) ) ) ),
13082 mkU32( 0 ) ) ) );
13083 break;
13084 case 0x350: // xvcvuxdsp (VSX Vector Convert and round Unsigned Integer Doubleword
13085 // to Single-Precision format)
13086 DIP("xvcvuxddp v%u,v%u\n", XT, XB);
13087 putVSReg( XT,
13088 binop( Iop_64HLtoV128,
13089 binop( Iop_32HLto64,
13090 unop( Iop_ReinterpF32asI32,
13091 unop( Iop_TruncF64asF32,
13092 binop( Iop_RoundF64toF32,
13093 get_IR_roundingmode(),
13094 binop( Iop_I64UtoF64,
13095 get_IR_roundingmode(),
13096 mkexpr( xB ) ) ) ) ),
13097 mkU32( 0 ) ),
13098 binop( Iop_32HLto64,
13099 unop( Iop_ReinterpF32asI32,
13100 unop( Iop_TruncF64asF32,
13101 binop( Iop_RoundF64toF32,
13102 get_IR_roundingmode(),
13103 binop( Iop_I64UtoF64,
13104 get_IR_roundingmode(),
13105 mkexpr( xB2 ) ) ) ) ),
13106 mkU32( 0 ) ) ) );
13107 break;
13108
13109 case 0x1f0: // xvcvsxwdp (VSX Vector Convert Signed Integer Word to Double-Precision format)
13110 DIP("xvcvsxwdp v%u,v%u\n", XT, XB);
13111 putVSReg( XT,
13112 binop( Iop_64HLtoV128,
13113 unop( Iop_ReinterpF64asI64,
13114 binop( Iop_I64StoF64, get_IR_roundingmode(),
13115 unop( Iop_32Sto64, mkexpr( b3 ) ) ) ),
13116 unop( Iop_ReinterpF64asI64,
13117 binop( Iop_I64StoF64, get_IR_roundingmode(),
13118 unop( Iop_32Sto64, mkexpr( b1 ) ) ) ) ) );
13119 break;
13120 case 0x1d0: // xvcvuxwdp (VSX Vector Convert Unsigned Integer Word to Double-Precision format)
13121 DIP("xvcvuxwdp v%u,v%u\n", XT, XB);
13122 putVSReg( XT,
13123 binop( Iop_64HLtoV128,
13124 unop( Iop_ReinterpF64asI64,
13125 binop( Iop_I64UtoF64, get_IR_roundingmode(),
13126 unop( Iop_32Uto64, mkexpr( b3 ) ) ) ),
13127 unop( Iop_ReinterpF64asI64,
13128 binop( Iop_I64UtoF64, get_IR_roundingmode(),
13129 unop( Iop_32Uto64, mkexpr( b1 ) ) ) ) ) );
13130 break;
13131 case 0x170: // xvcvsxwsp (VSX Vector Convert Signed Integer Word to Single-Precision format)
13132 DIP("xvcvsxwsp v%u,v%u\n", XT, XB);
13133 putVSReg( XT, unop( Iop_I32StoFx4, getVSReg( XB ) ) );
13134 break;
13135 case 0x150: // xvcvuxwsp (VSX Vector Convert Unsigned Integer Word to Single-Precision format)
13136 DIP("xvcvuxwsp v%u,v%u\n", XT, XB);
13137 putVSReg( XT, unop( Iop_I32UtoFx4, getVSReg( XB ) ) );
13138 break;
13139
13140 default:
13141 vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
13142 return False;
13143 }
13144 return True;
13145 }
13146
13147 /*
13148 * VSX vector Double Precision Floating Point Arithmetic Instructions
13149 */
13150 static Bool
dis_vxv_dp_arith(UInt theInstr,UInt opc2)13151 dis_vxv_dp_arith ( UInt theInstr, UInt opc2 )
13152 {
13153 /* XX3-Form */
13154 UChar opc1 = ifieldOPC( theInstr );
13155 UChar XT = ifieldRegXT( theInstr );
13156 UChar XA = ifieldRegXA( theInstr );
13157 UChar XB = ifieldRegXB( theInstr );
13158 IRExpr* rm = get_IR_roundingmode();
13159 IRTemp frA = newTemp(Ity_F64);
13160 IRTemp frB = newTemp(Ity_F64);
13161 IRTemp frA2 = newTemp(Ity_F64);
13162 IRTemp frB2 = newTemp(Ity_F64);
13163
13164 if (opc1 != 0x3C) {
13165 vex_printf( "dis_vxv_dp_arith(ppc)(instr)\n" );
13166 return False;
13167 }
13168
13169 assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
13170 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
13171 assign(frA2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XA ))));
13172 assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XB ))));
13173
13174 switch (opc2) {
13175 case 0x1E0: // xvdivdp (VSX Vector Divide Double-Precision)
13176 case 0x1C0: // xvmuldp (VSX Vector Multiply Double-Precision)
13177 case 0x180: // xvadddp (VSX Vector Add Double-Precision)
13178 case 0x1A0: // xvsubdp (VSX Vector Subtract Double-Precision)
13179 {
13180 IROp mOp;
13181 const HChar * oper_name;
13182 switch (opc2) {
13183 case 0x1E0:
13184 mOp = Iop_DivF64;
13185 oper_name = "div";
13186 break;
13187 case 0x1C0:
13188 mOp = Iop_MulF64;
13189 oper_name = "mul";
13190 break;
13191 case 0x180:
13192 mOp = Iop_AddF64;
13193 oper_name = "add";
13194 break;
13195 case 0x1A0:
13196 mOp = Iop_SubF64;
13197 oper_name = "sub";
13198 break;
13199
13200 default:
13201 vpanic("The impossible happened: dis_vxv_dp_arith(ppc)");
13202 }
13203 IRTemp hiResult = newTemp(Ity_I64);
13204 IRTemp loResult = newTemp(Ity_I64);
13205 DIP("xv%sdp v%d,v%d,v%d\n", oper_name, XT, XA, XB);
13206
13207 assign( hiResult,
13208 unop( Iop_ReinterpF64asI64,
13209 triop( mOp, rm, mkexpr( frA ), mkexpr( frB ) ) ) );
13210 assign( loResult,
13211 unop( Iop_ReinterpF64asI64,
13212 triop( mOp, rm, mkexpr( frA2 ), mkexpr( frB2 ) ) ) );
13213 putVSReg( XT,
13214 binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
13215 break;
13216 }
13217 case 0x196: // xvsqrtdp
13218 {
13219 IRTemp hiResult = newTemp(Ity_I64);
13220 IRTemp loResult = newTemp(Ity_I64);
13221 DIP("xvsqrtdp v%d,v%d\n", XT, XB);
13222
13223 assign( hiResult,
13224 unop( Iop_ReinterpF64asI64,
13225 binop( Iop_SqrtF64, rm, mkexpr( frB ) ) ) );
13226 assign( loResult,
13227 unop( Iop_ReinterpF64asI64,
13228 binop( Iop_SqrtF64, rm, mkexpr( frB2 ) ) ) );
13229 putVSReg( XT,
13230 binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
13231 break;
13232 }
13233 case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp (VSX Vector Multiply-Add Double-Precision)
13234 case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp (VSX Vector Multiply-Subtract Double-Precision)
13235 case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp (VSX Vector Negate Multiply-Add Double-Precision)
13236 case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp (VSX Vector Negate Multiply-Subtract Double-Precision)
13237 {
13238 /* xvm{add|sub}mdp XT,XA,XB is element-wise equivalent to fm{add|sub} FRT,FRA,FRC,FRB with . . .
13239 * XT == FRC
13240 * XA == FRA
13241 * XB == FRB
13242 *
13243 * and for xvm{add|sub}adp . . .
13244 * XT == FRB
13245 * XA == FRA
13246 * XB == FRC
13247 */
13248 Bool negate;
13249 IROp mOp = Iop_INVALID;
13250 const HChar * oper_name = NULL;
13251 Bool mdp = False;
13252
13253 switch (opc2) {
13254 case 0x184: case 0x1A4:
13255 case 0x384: case 0x3A4:
13256 mOp = Iop_MAddF64;
13257 oper_name = "add";
13258 mdp = (opc2 & 0x0FF) == 0x0A4;
13259 break;
13260
13261 case 0x1C4: case 0x1E4:
13262 case 0x3C4: case 0x3E4:
13263 mOp = Iop_MSubF64;
13264 oper_name = "sub";
13265 mdp = (opc2 & 0x0FF) == 0x0E4;
13266 break;
13267
13268 default:
13269 vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
13270 }
13271
13272 switch (opc2) {
13273 case 0x384: case 0x3A4:
13274 case 0x3C4: case 0x3E4:
13275 negate = True;
13276 break;
13277 default:
13278 negate = False;
13279 }
13280 IRTemp hiResult = newTemp(Ity_I64);
13281 IRTemp loResult = newTemp(Ity_I64);
13282 IRTemp frT = newTemp(Ity_F64);
13283 IRTemp frT2 = newTemp(Ity_F64);
13284 DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, mdp ? "mdp" : "adp",
13285 XT, XA, XB);
13286 assign(frT, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XT ) ) ) );
13287 assign(frT2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XT ) ) ) );
13288
13289 assign( hiResult,
13290 unop( Iop_ReinterpF64asI64,
13291 qop( mOp,
13292 rm,
13293 mkexpr( frA ),
13294 mkexpr( mdp ? frT : frB ),
13295 mkexpr( mdp ? frB : frT ) ) ) );
13296 assign( loResult,
13297 unop( Iop_ReinterpF64asI64,
13298 qop( mOp,
13299 rm,
13300 mkexpr( frA2 ),
13301 mkexpr( mdp ? frT2 : frB2 ),
13302 mkexpr( mdp ? frB2 : frT2 ) ) ) );
13303 putVSReg( XT,
13304 binop( Iop_64HLtoV128,
13305 mkexpr( negate ? getNegatedResult( hiResult )
13306 : hiResult ),
13307 mkexpr( negate ? getNegatedResult( loResult )
13308 : loResult ) ) );
13309 break;
13310 }
13311 case 0x1D4: // xvtsqrtdp (VSX Vector Test for software Square Root Double-Precision)
13312 {
13313 IRTemp frBHi_I64 = newTemp(Ity_I64);
13314 IRTemp frBLo_I64 = newTemp(Ity_I64);
13315 IRTemp flagsHi = newTemp(Ity_I32);
13316 IRTemp flagsLo = newTemp(Ity_I32);
13317 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) );
13318 IRTemp fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
13319 fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
13320
13321 DIP("xvtsqrtdp cr%d,v%d\n", crfD, XB);
13322 assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
13323 assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
13324 do_fp_tsqrt(frBHi_I64, False /*not single precision*/, &fe_flagHi, &fg_flagHi);
13325 do_fp_tsqrt(frBLo_I64, False /*not single precision*/, &fe_flagLo, &fg_flagLo);
13326 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
13327 * where fl_flag == 1 on ppc64.
13328 */
13329 assign( flagsHi,
13330 binop( Iop_Or32,
13331 binop( Iop_Or32, mkU32( 8 ), // fl_flag
13332 binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
13333 binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
13334 assign( flagsLo,
13335 binop( Iop_Or32,
13336 binop( Iop_Or32, mkU32( 8 ), // fl_flag
13337 binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
13338 binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
13339 putGST_field( PPC_GST_CR,
13340 binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
13341 crfD );
13342 break;
13343 }
13344 case 0x1F4: // xvtdivdp (VSX Vector Test for software Divide Double-Precision)
13345 {
13346 IRTemp frBHi_I64 = newTemp(Ity_I64);
13347 IRTemp frBLo_I64 = newTemp(Ity_I64);
13348 IRTemp frAHi_I64 = newTemp(Ity_I64);
13349 IRTemp frALo_I64 = newTemp(Ity_I64);
13350 IRTemp flagsHi = newTemp(Ity_I32);
13351 IRTemp flagsLo = newTemp(Ity_I32);
13352 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) );
13353 IRTemp fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
13354 fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
13355
13356 DIP("xvtdivdp cr%d,v%d,v%d\n", crfD, XA, XB);
13357 assign( frAHi_I64, unop(Iop_V128HIto64, getVSReg( XA )) );
13358 assign( frALo_I64, unop(Iop_V128to64, getVSReg( XA )) );
13359 assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
13360 assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
13361
13362 _do_fp_tdiv(frAHi_I64, frBHi_I64, False/*dp*/, &fe_flagHi, &fg_flagHi);
13363 _do_fp_tdiv(frALo_I64, frBLo_I64, False/*dp*/, &fe_flagLo, &fg_flagLo);
13364 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
13365 * where fl_flag == 1 on ppc64.
13366 */
13367 assign( flagsHi,
13368 binop( Iop_Or32,
13369 binop( Iop_Or32, mkU32( 8 ), // fl_flag
13370 binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
13371 binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
13372 assign( flagsLo,
13373 binop( Iop_Or32,
13374 binop( Iop_Or32, mkU32( 8 ), // fl_flag
13375 binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
13376 binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
13377 putGST_field( PPC_GST_CR,
13378 binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
13379 crfD );
13380 break;
13381 }
13382
13383 default:
13384 vex_printf( "dis_vxv_dp_arith(ppc)(opc2)\n" );
13385 return False;
13386 }
13387 return True;
13388 }
13389
13390 /*
13391 * VSX vector Single Precision Floating Point Arithmetic Instructions
13392 */
13393 static Bool
dis_vxv_sp_arith(UInt theInstr,UInt opc2)13394 dis_vxv_sp_arith ( UInt theInstr, UInt opc2 )
13395 {
13396 /* XX3-Form */
13397 UChar opc1 = ifieldOPC( theInstr );
13398 UChar XT = ifieldRegXT( theInstr );
13399 UChar XA = ifieldRegXA( theInstr );
13400 UChar XB = ifieldRegXB( theInstr );
13401 IRExpr* rm = get_IR_roundingmode();
13402 IRTemp a3, a2, a1, a0;
13403 IRTemp b3, b2, b1, b0;
13404 IRTemp res0 = newTemp(Ity_I32);
13405 IRTemp res1 = newTemp(Ity_I32);
13406 IRTemp res2 = newTemp(Ity_I32);
13407 IRTemp res3 = newTemp(Ity_I32);
13408
13409 a3 = a2 = a1 = a0 = IRTemp_INVALID;
13410 b3 = b2 = b1 = b0 = IRTemp_INVALID;
13411
13412 if (opc1 != 0x3C) {
13413 vex_printf( "dis_vxv_sp_arith(ppc)(instr)\n" );
13414 return False;
13415 }
13416
13417 switch (opc2) {
13418 case 0x100: // xvaddsp (VSX Vector Add Single-Precision)
13419 DIP("xvaddsp v%d,v%d,v%d\n", XT, XA, XB);
13420 // WARNING: BOGUS! The backend ignores rm on Iop_Add32Fx4
13421 putVSReg( XT, triop(Iop_Add32Fx4, rm,
13422 getVSReg( XA ), getVSReg( XB )) );
13423 break;
13424
13425 case 0x140: // xvmulsp (VSX Vector Multiply Single-Precision)
13426 DIP("xvmulsp v%d,v%d,v%d\n", XT, XA, XB);
13427 // WARNING: BOGUS! The backend ignores rm on Iop_Mul32Fx4
13428 putVSReg( XT, triop(Iop_Mul32Fx4, rm,
13429 getVSReg( XA ), getVSReg( XB )) );
13430 break;
13431
13432 case 0x120: // xvsubsp (VSX Vector Subtract Single-Precision)
13433 DIP("xvsubsp v%d,v%d,v%d\n", XT, XA, XB);
13434 // WARNING: BOGUS! The backend ignores rm on Iop_Sub32Fx4
13435 putVSReg( XT, triop(Iop_Sub32Fx4, rm,
13436 getVSReg( XA ), getVSReg( XB )) );
13437 break;
13438
13439 case 0x160: // xvdivsp (VSX Vector Divide Single-Precision)
13440 {
13441 /* Iop_Div32Fx4 is not implemented for ppc64 (in host_ppc_{isel|defs}.c.
13442 * So there are two choices:
13443 * 1. Implement the xvdivsp with a native insn; or
13444 * 2. Extract the 4 single precision floats from each vector
13445 * register inputs and perform fdivs on each pair
13446 * I will do the latter, due to the general philosophy of
13447 * reusing existing implementations when practical.
13448 */
13449 DIP("xvdivsp v%d,v%d,v%d\n", XT, XA, XB);
13450 breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
13451 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
13452
13453 assign( res0,
13454 unop( Iop_ReinterpF32asI32,
13455 unop( Iop_TruncF64asF32,
13456 triop( Iop_DivF64r32, rm, mkexpr( a0 ), mkexpr( b0 ) ) ) ) );
13457 assign( res1,
13458 unop( Iop_ReinterpF32asI32,
13459 unop( Iop_TruncF64asF32,
13460 triop( Iop_DivF64r32, rm, mkexpr( a1 ), mkexpr( b1 ) ) ) ) );
13461 assign( res2,
13462 unop( Iop_ReinterpF32asI32,
13463 unop( Iop_TruncF64asF32,
13464 triop( Iop_DivF64r32, rm, mkexpr( a2 ), mkexpr( b2 ) ) ) ) );
13465 assign( res3,
13466 unop( Iop_ReinterpF32asI32,
13467 unop( Iop_TruncF64asF32,
13468 triop( Iop_DivF64r32, rm, mkexpr( a3 ), mkexpr( b3 ) ) ) ) );
13469
13470 putVSReg( XT,
13471 binop( Iop_64HLtoV128,
13472 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
13473 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
13474 break;
13475 }
13476 case 0x116: // xvsqrtsp (VSX Vector Square Root Single-Precision)
13477 {
13478 DIP("xvsqrtsp v%d,v%d\n", XT, XB);
13479 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
13480 /* Note: The native xvsqrtsp insruction does not always give the same precision
13481 * as what we get with Iop_SqrtF64. But it doesn't seem worthwhile to implement
13482 * an Iop_SqrtF32 that would give us a lower precision result, albeit more true
13483 * to the actual instruction.
13484 */
13485
13486 assign( res0,
13487 unop( Iop_ReinterpF32asI32,
13488 unop( Iop_TruncF64asF32,
13489 binop(Iop_SqrtF64, rm, mkexpr( b0 ) ) ) ) );
13490 assign( res1,
13491 unop( Iop_ReinterpF32asI32,
13492 unop( Iop_TruncF64asF32,
13493 binop(Iop_SqrtF64, rm, mkexpr( b1 ) ) ) ) );
13494 assign( res2,
13495 unop( Iop_ReinterpF32asI32,
13496 unop( Iop_TruncF64asF32,
13497 binop(Iop_SqrtF64, rm, mkexpr( b2) ) ) ) );
13498 assign( res3,
13499 unop( Iop_ReinterpF32asI32,
13500 unop( Iop_TruncF64asF32,
13501 binop(Iop_SqrtF64, rm, mkexpr( b3 ) ) ) ) );
13502
13503 putVSReg( XT,
13504 binop( Iop_64HLtoV128,
13505 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
13506 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
13507 break;
13508 }
13509
13510 case 0x104: case 0x124: // xvmaddasp, xvmaddmsp (VSX Vector Multiply-Add Single-Precision)
13511 case 0x144: case 0x164: // xvmsubasp, xvmsubmsp (VSX Vector Multiply-Subtract Single-Precision)
13512 case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp (VSX Vector Negate Multiply-Add Single-Precision)
13513 case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp (VSX Vector Negate Multiply-Subtract Single-Precision)
13514 {
13515 IRTemp t3, t2, t1, t0;
13516 Bool msp = False;
13517 Bool negate;
13518 const HChar * oper_name = NULL;
13519 IROp mOp = Iop_INVALID;
13520 switch (opc2) {
13521 case 0x104: case 0x124:
13522 case 0x304: case 0x324:
13523 msp = (opc2 & 0x0FF) == 0x024;
13524 mOp = Iop_MAddF64r32;
13525 oper_name = "madd";
13526 break;
13527
13528 case 0x144: case 0x164:
13529 case 0x344: case 0x364:
13530 msp = (opc2 & 0x0FF) == 0x064;
13531 mOp = Iop_MSubF64r32;
13532 oper_name = "sub";
13533 break;
13534
13535 default:
13536 vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
13537 }
13538
13539 switch (opc2) {
13540 case 0x304: case 0x324:
13541 case 0x344: case 0x364:
13542 negate = True;
13543 break;
13544
13545 default:
13546 negate = False;
13547 }
13548
13549 DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name,
13550 msp ? "msp" : "asp", XT, XA, XB);
13551
13552 t3 = t2 = t1 = t0 = IRTemp_INVALID;
13553 breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
13554 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
13555 breakV128to4xF64( getVSReg( XT ), &t3, &t2, &t1, &t0 );
13556
13557 assign( res0,
13558 unop( Iop_ReinterpF32asI32,
13559 unop( Iop_TruncF64asF32,
13560 qop( mOp,
13561 rm,
13562 mkexpr( a0 ),
13563 mkexpr( msp ? t0 : b0 ),
13564 mkexpr( msp ? b0 : t0 ) ) ) ) );
13565 assign( res1,
13566 unop( Iop_ReinterpF32asI32,
13567 unop( Iop_TruncF64asF32,
13568 qop( mOp,
13569 rm,
13570 mkexpr( a1 ),
13571 mkexpr( msp ? t1 : b1 ),
13572 mkexpr( msp ? b1 : t1 ) ) ) ) );
13573 assign( res2,
13574 unop( Iop_ReinterpF32asI32,
13575 unop( Iop_TruncF64asF32,
13576 qop( mOp,
13577 rm,
13578 mkexpr( a2 ),
13579 mkexpr( msp ? t2 : b2 ),
13580 mkexpr( msp ? b2 : t2 ) ) ) ) );
13581 assign( res3,
13582 unop( Iop_ReinterpF32asI32,
13583 unop( Iop_TruncF64asF32,
13584 qop( mOp,
13585 rm,
13586 mkexpr( a3 ),
13587 mkexpr( msp ? t3 : b3 ),
13588 mkexpr( msp ? b3 : t3 ) ) ) ) );
13589
13590 putVSReg( XT,
13591 binop( Iop_64HLtoV128,
13592 binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res3 ) : res3 ),
13593 mkexpr( negate ? getNegatedResult_32( res2 ) : res2 ) ),
13594 binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res1 ) : res1 ),
13595 mkexpr( negate ? getNegatedResult_32( res0 ) : res0 ) ) ) );
13596
13597 break;
13598 }
13599 case 0x154: // xvtsqrtsp (VSX Vector Test for software Square Root Single-Precision)
13600 {
13601 IRTemp flags0 = newTemp(Ity_I32);
13602 IRTemp flags1 = newTemp(Ity_I32);
13603 IRTemp flags2 = newTemp(Ity_I32);
13604 IRTemp flags3 = newTemp(Ity_I32);
13605 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) );
13606 IRTemp fe_flag0, fg_flag0, fe_flag1, fg_flag1;
13607 IRTemp fe_flag2, fg_flag2, fe_flag3, fg_flag3;
13608 fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
13609 fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
13610 DIP("xvtsqrtsp cr%d,v%d\n", crfD, XB);
13611
13612 breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
13613 do_fp_tsqrt(b0, True /* single precision*/, &fe_flag0, &fg_flag0);
13614 do_fp_tsqrt(b1, True /* single precision*/, &fe_flag1, &fg_flag1);
13615 do_fp_tsqrt(b2, True /* single precision*/, &fe_flag2, &fg_flag2);
13616 do_fp_tsqrt(b3, True /* single precision*/, &fe_flag3, &fg_flag3);
13617
13618 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
13619 * where fl_flag == 1 on ppc64.
13620 */
13621 assign( flags0,
13622 binop( Iop_Or32,
13623 binop( Iop_Or32, mkU32( 8 ), // fl_flag
13624 binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
13625 binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
13626 assign( flags1,
13627 binop( Iop_Or32,
13628 binop( Iop_Or32, mkU32( 8 ), // fl_flag
13629 binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
13630 binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
13631 assign( flags2,
13632 binop( Iop_Or32,
13633 binop( Iop_Or32, mkU32( 8 ), // fl_flag
13634 binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
13635 binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
13636 assign( flags3,
13637 binop( Iop_Or32,
13638 binop( Iop_Or32, mkU32( 8 ), // fl_flag
13639 binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
13640 binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
13641 putGST_field( PPC_GST_CR,
13642 binop( Iop_Or32,
13643 mkexpr( flags0 ),
13644 binop( Iop_Or32,
13645 mkexpr( flags1 ),
13646 binop( Iop_Or32,
13647 mkexpr( flags2 ),
13648 mkexpr( flags3 ) ) ) ),
13649 crfD );
13650
13651 break;
13652 }
13653 case 0x174: // xvtdivsp (VSX Vector Test for software Divide Single-Precision)
13654 {
13655 IRTemp flags0 = newTemp(Ity_I32);
13656 IRTemp flags1 = newTemp(Ity_I32);
13657 IRTemp flags2 = newTemp(Ity_I32);
13658 IRTemp flags3 = newTemp(Ity_I32);
13659 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) );
13660 IRTemp fe_flag0, fg_flag0, fe_flag1, fg_flag1;
13661 IRTemp fe_flag2, fg_flag2, fe_flag3, fg_flag3;
13662 fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
13663 fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
13664 DIP("xvtdivsp cr%d,v%d,v%d\n", crfD, XA, XB);
13665
13666 breakV128to4x32( getVSReg( XA ), &a3, &a2, &a1, &a0 );
13667 breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
13668 _do_fp_tdiv(a0, b0, True /* single precision*/, &fe_flag0, &fg_flag0);
13669 _do_fp_tdiv(a1, b1, True /* single precision*/, &fe_flag1, &fg_flag1);
13670 _do_fp_tdiv(a2, b2, True /* single precision*/, &fe_flag2, &fg_flag2);
13671 _do_fp_tdiv(a3, b3, True /* single precision*/, &fe_flag3, &fg_flag3);
13672
13673 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
13674 * where fl_flag == 1 on ppc64.
13675 */
13676 assign( flags0,
13677 binop( Iop_Or32,
13678 binop( Iop_Or32, mkU32( 8 ), // fl_flag
13679 binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
13680 binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
13681 assign( flags1,
13682 binop( Iop_Or32,
13683 binop( Iop_Or32, mkU32( 8 ), // fl_flag
13684 binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
13685 binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
13686 assign( flags2,
13687 binop( Iop_Or32,
13688 binop( Iop_Or32, mkU32( 8 ), // fl_flag
13689 binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
13690 binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
13691 assign( flags3,
13692 binop( Iop_Or32,
13693 binop( Iop_Or32, mkU32( 8 ), // fl_flag
13694 binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
13695 binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
13696 putGST_field( PPC_GST_CR,
13697 binop( Iop_Or32,
13698 mkexpr( flags0 ),
13699 binop( Iop_Or32,
13700 mkexpr( flags1 ),
13701 binop( Iop_Or32,
13702 mkexpr( flags2 ),
13703 mkexpr( flags3 ) ) ) ),
13704 crfD );
13705
13706 break;
13707 }
13708
13709 default:
13710 vex_printf( "dis_vxv_sp_arith(ppc)(opc2)\n" );
13711 return False;
13712 }
13713 return True;
13714 }
13715
13716 /*
13717 * Vector Population Count/bit matrix transpose
13718 */
13719 static Bool
dis_av_count_bitTranspose(UInt theInstr,UInt opc2)13720 dis_av_count_bitTranspose ( UInt theInstr, UInt opc2 )
13721 {
13722 UChar vRB_addr = ifieldRegB(theInstr);
13723 UChar vRT_addr = ifieldRegDS(theInstr);
13724 UChar opc1 = ifieldOPC( theInstr );
13725 IRTemp vB = newTemp(Ity_V128);
13726 assign( vB, getVReg(vRB_addr));
13727
13728 if (opc1 != 0x4) {
13729 vex_printf( "dis_av_count_bitTranspose(ppc)(instr)\n" );
13730 return False;
13731 }
13732
13733 switch (opc2) {
13734 case 0x702: // vclzb
13735 DIP("vclzb v%d,v%d\n", vRT_addr, vRB_addr);
13736 putVReg( vRT_addr, unop(Iop_Clz8x16, mkexpr( vB ) ) );
13737 break;
13738
13739 case 0x742: // vclzh
13740 DIP("vclzh v%d,v%d\n", vRT_addr, vRB_addr);
13741 putVReg( vRT_addr, unop(Iop_Clz16x8, mkexpr( vB ) ) );
13742 break;
13743
13744 case 0x782: // vclzw
13745 DIP("vclzw v%d,v%d\n", vRT_addr, vRB_addr);
13746 putVReg( vRT_addr, unop(Iop_Clz32x4, mkexpr( vB ) ) );
13747 break;
13748
13749 case 0x7C2: // vclzd
13750 DIP("vclzd v%d,v%d\n", vRT_addr, vRB_addr);
13751 putVReg( vRT_addr, unop(Iop_Clz64x2, mkexpr( vB ) ) );
13752 break;
13753
13754 case 0x703: // vpopcntb
13755 {
13756 /* Break vector into 32-bit words and do the population count
13757 * on byte in the words
13758 */
13759 IRType ty = Ity_I32;
13760 IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
13761 bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
13762 IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
13763 cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
13764
13765 DIP("vpopcntb v%d,v%d\n", vRT_addr, vRB_addr);
13766 breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
13767 cnt_bits0_31 = gen_POPCOUNT(ty, bits0_31, BYTE);
13768 cnt_bits32_63 = gen_POPCOUNT(ty, bits32_63, BYTE);
13769 cnt_bits64_95 = gen_POPCOUNT(ty, bits64_95, BYTE);
13770 cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, BYTE);
13771
13772 putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
13773 cnt_bits32_63, cnt_bits0_31) );
13774 break;
13775 }
13776
13777 case 0x743: // vpopcnth
13778 {
13779 /* Break vector into 32-bit words and do the population count
13780 * for each half word
13781 */
13782 IRType ty = Ity_I32;
13783 IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
13784 bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
13785 IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
13786 cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
13787
13788 DIP("vpopcnth v%d,v%d\n", vRT_addr, vRB_addr);
13789 breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
13790
13791 cnt_bits0_31 = gen_POPCOUNT(ty, bits0_31, HWORD);
13792 cnt_bits32_63 = gen_POPCOUNT(ty, bits32_63, HWORD);
13793 cnt_bits64_95 = gen_POPCOUNT(ty, bits64_95, HWORD);
13794 cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, HWORD);
13795
13796 putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
13797 cnt_bits32_63, cnt_bits0_31) );
13798 break;
13799 }
13800
13801 case 0x783: // vpopcntw
13802 {
13803 /* Break vector into 32-bit words and do the population count
13804 * on each word.
13805 */
13806 IRType ty = Ity_I32;
13807 IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
13808 bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
13809 IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
13810 cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
13811
13812 DIP("vpopcntw v%d,v%d\n", vRT_addr, vRB_addr);
13813 breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
13814
13815 cnt_bits0_31 = gen_POPCOUNT(ty, bits0_31, WORD);
13816 cnt_bits32_63 = gen_POPCOUNT(ty, bits32_63, WORD);
13817 cnt_bits64_95 = gen_POPCOUNT(ty, bits64_95, WORD);
13818 cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, WORD);
13819
13820 putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
13821 cnt_bits32_63, cnt_bits0_31) );
13822 break;
13823 }
13824
13825 case 0x7C3: // vpopcntd
13826 {
13827 if (mode64) {
13828 /* Break vector into 64-bit double words and do the population count
13829 * on each double word.
13830 */
13831 IRType ty = Ity_I64;
13832 IRTemp bits0_63 = newTemp(Ity_I64);
13833 IRTemp bits64_127 = newTemp(Ity_I64);
13834 IRTemp cnt_bits0_63 = newTemp(Ity_I64);
13835 IRTemp cnt_bits64_127 = newTemp(Ity_I64);
13836
13837 DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr);
13838
13839 assign(bits0_63, unop( Iop_V128to64, mkexpr( vB ) ) );
13840 assign(bits64_127, unop( Iop_V128HIto64, mkexpr( vB ) ) );
13841 cnt_bits0_63 = gen_POPCOUNT(ty, bits0_63, DWORD);
13842 cnt_bits64_127 = gen_POPCOUNT(ty, bits64_127, DWORD);
13843
13844 putVReg( vRT_addr, binop( Iop_64HLtoV128,
13845 mkexpr( cnt_bits64_127 ),
13846 mkexpr( cnt_bits0_63 ) ) );
13847 } else {
13848 /* Break vector into 32-bit words and do the population count
13849 * on each doubleword.
13850 */
13851 IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
13852 bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
13853 IRTemp cnt_bits0_63 = newTemp(Ity_I64);
13854 IRTemp cnt_bits64_127 = newTemp(Ity_I64);
13855
13856 DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr);
13857 breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
13858
13859 cnt_bits0_63 = gen_vpopcntd_mode32(bits0_31, bits32_63);
13860 cnt_bits64_127 = gen_vpopcntd_mode32(bits64_95, bits96_127);
13861
13862 putVReg( vRT_addr, binop( Iop_64HLtoV128,
13863 mkexpr( cnt_bits64_127 ),
13864 mkexpr( cnt_bits0_63 ) ) );
13865 }
13866 break;
13867 }
13868
13869 case 0x50C: // vgbbd Vector Gather Bits by Bytes by Doubleword
13870 DIP("vgbbd v%d,v%d\n", vRT_addr, vRB_addr);
13871 putVReg( vRT_addr, unop( Iop_PwBitMtxXpose64x2, mkexpr( vB ) ) );
13872 break;
13873
13874 default:
13875 vex_printf("dis_av_count_bitTranspose(ppc)(opc2)\n");
13876 return False;
13877 break;
13878 }
13879 return True;
13880 }
13881
13882 typedef enum {
13883 PPC_CMP_EQ = 2,
13884 PPC_CMP_GT = 4,
13885 PPC_CMP_GE = 6,
13886 PPC_CMP_LT = 8
13887 } ppc_cmp_t;
13888
13889
13890 /*
13891 This helper function takes as input the IRExpr returned
13892 from a binop( Iop_CmpF64, fpA, fpB), whose result is returned
13893 in IR form. This helper function converts it to PPC form.
13894
13895 Map compare result from IR to PPC
13896
13897 FP cmp result | PPC | IR
13898 --------------------------
13899 UN | 0x1 | 0x45
13900 EQ | 0x2 | 0x40
13901 GT | 0x4 | 0x00
13902 LT | 0x8 | 0x01
13903
13904 condcode = Shl(1, (~(ccIR>>5) & 2)
13905 | ((ccIR ^ (ccIR>>6)) & 1)
13906 */
13907 static IRTemp
get_fp_cmp_CR_val(IRExpr * ccIR_expr)13908 get_fp_cmp_CR_val (IRExpr * ccIR_expr)
13909 {
13910 IRTemp condcode = newTemp( Ity_I32 );
13911 IRTemp ccIR = newTemp( Ity_I32 );
13912
13913 assign(ccIR, ccIR_expr);
13914 assign( condcode,
13915 binop( Iop_Shl32,
13916 mkU32( 1 ),
13917 unop( Iop_32to8,
13918 binop( Iop_Or32,
13919 binop( Iop_And32,
13920 unop( Iop_Not32,
13921 binop( Iop_Shr32,
13922 mkexpr( ccIR ),
13923 mkU8( 5 ) ) ),
13924 mkU32( 2 ) ),
13925 binop( Iop_And32,
13926 binop( Iop_Xor32,
13927 mkexpr( ccIR ),
13928 binop( Iop_Shr32,
13929 mkexpr( ccIR ),
13930 mkU8( 6 ) ) ),
13931 mkU32( 1 ) ) ) ) ) );
13932 return condcode;
13933 }
13934
13935 /*
13936 * Helper function for get_max_min_fp for ascertaining the max or min between two doubles
13937 * following these special rules:
13938 * - The max/min of a QNaN and any value is that value
13939 * (When two QNaNs are being compared, the frA QNaN is the return value.)
13940 * - The max/min of any value and an SNaN is that SNaN converted to a QNaN
13941 * (When two SNaNs are being compared, the frA SNaN is converted to a QNaN.)
13942 */
_get_maxmin_fp_NaN(IRTemp frA_I64,IRTemp frB_I64)13943 static IRExpr * _get_maxmin_fp_NaN(IRTemp frA_I64, IRTemp frB_I64)
13944 {
13945 IRTemp frA_isNaN = newTemp(Ity_I1);
13946 IRTemp frB_isNaN = newTemp(Ity_I1);
13947 IRTemp frA_isSNaN = newTemp(Ity_I1);
13948 IRTemp frB_isSNaN = newTemp(Ity_I1);
13949 IRTemp frA_isQNaN = newTemp(Ity_I1);
13950 IRTemp frB_isQNaN = newTemp(Ity_I1);
13951
13952 assign( frA_isNaN, is_NaN( frA_I64 ) );
13953 assign( frB_isNaN, is_NaN( frB_I64 ) );
13954 // If operand is a NAN and bit 12 is '0', then it's an SNaN
13955 assign( frA_isSNaN,
13956 mkAND1( mkexpr(frA_isNaN),
13957 binop( Iop_CmpEQ32,
13958 binop( Iop_And32,
13959 unop( Iop_64HIto32, mkexpr( frA_I64 ) ),
13960 mkU32( 0x00080000 ) ),
13961 mkU32( 0 ) ) ) );
13962 assign( frB_isSNaN,
13963 mkAND1( mkexpr(frB_isNaN),
13964 binop( Iop_CmpEQ32,
13965 binop( Iop_And32,
13966 unop( Iop_64HIto32, mkexpr( frB_I64 ) ),
13967 mkU32( 0x00080000 ) ),
13968 mkU32( 0 ) ) ) );
13969 assign( frA_isQNaN,
13970 mkAND1( mkexpr( frA_isNaN ), unop( Iop_Not1, mkexpr( frA_isSNaN ) ) ) );
13971 assign( frB_isQNaN,
13972 mkAND1( mkexpr( frB_isNaN ), unop( Iop_Not1, mkexpr( frB_isSNaN ) ) ) );
13973
13974 /* Based on the rules specified in the function prologue, the algorithm is as follows:
13975 * <<<<<<<<<>>>>>>>>>>>>>>>>>>
13976 * if frA is a SNaN
13977 * result = frA converted to QNaN
13978 * else if frB is a SNaN
13979 * result = frB converted to QNaN
13980 * else if frB is a QNaN
13981 * result = frA
13982 * // One of frA or frB was a NaN in order for this function to be called, so
13983 * // if we get to this point, we KNOW that frA must be a QNaN.
13984 * else // frA is a QNaN
13985 * result = frB
13986 * <<<<<<<<<>>>>>>>>>>>>>>>>>>
13987 */
13988
13989 #define SNAN_MASK 0x0008000000000000ULL
13990 return
13991 IRExpr_ITE(mkexpr(frA_isSNaN),
13992 /* then: result = frA converted to QNaN */
13993 binop(Iop_Or64, mkexpr(frA_I64), mkU64(SNAN_MASK)),
13994 /* else: if frB is a SNaN */
13995 IRExpr_ITE(mkexpr(frB_isSNaN),
13996 /* then: result = frB converted to QNaN */
13997 binop(Iop_Or64, mkexpr(frB_I64), mkU64(SNAN_MASK)),
13998 /* else: if frB is a QNaN */
13999 IRExpr_ITE(mkexpr(frB_isQNaN),
14000 /* then: result = frA */
14001 mkexpr(frA_I64),
14002 /* else: frA is a QNaN, so result = frB */
14003 mkexpr(frB_I64))));
14004 }
14005
14006 /*
14007 * Helper function for get_max_min_fp.
14008 */
_get_maxmin_fp_cmp(IRTemp src1,IRTemp src2,Bool isMin)14009 static IRExpr * _get_maxmin_fp_cmp(IRTemp src1, IRTemp src2, Bool isMin)
14010 {
14011 IRTemp src1cmpsrc2 = get_fp_cmp_CR_val( binop( Iop_CmpF64,
14012 unop( Iop_ReinterpI64asF64,
14013 mkexpr( src1 ) ),
14014 unop( Iop_ReinterpI64asF64,
14015 mkexpr( src2 ) ) ) );
14016
14017 return IRExpr_ITE( binop( Iop_CmpEQ32,
14018 mkexpr( src1cmpsrc2 ),
14019 mkU32( isMin ? PPC_CMP_LT : PPC_CMP_GT ) ),
14020 /* then: use src1 */
14021 mkexpr( src1 ),
14022 /* else: use src2 */
14023 mkexpr( src2 ) );
14024 }
14025
14026 /*
14027 * Helper function for "Maximum/Minimum Double Precision" operations.
14028 * Arguments: frA and frb are Ity_I64
14029 * Returns Ity_I64 IRExpr that answers the "which is Maxiumum/Minimum" question
14030 */
get_max_min_fp(IRTemp frA_I64,IRTemp frB_I64,Bool isMin)14031 static IRExpr * get_max_min_fp(IRTemp frA_I64, IRTemp frB_I64, Bool isMin)
14032 {
14033 /* There are three special cases where get_fp_cmp_CR_val is not helpful
14034 * for ascertaining the maximum between two doubles:
14035 * 1. The max/min of +0 and -0 is +0.
14036 * 2. The max/min of a QNaN and any value is that value.
14037 * 3. The max/min of any value and an SNaN is that SNaN converted to a QNaN.
14038 * We perform the check for [+/-]0 here in this function and use the
14039 * _get_maxmin_fp_NaN helper for the two NaN cases; otherwise we call _get_maxmin_fp_cmp
14040 * to do the standard comparison function.
14041 */
14042 IRTemp anyNaN = newTemp(Ity_I1);
14043 IRTemp frA_isZero = newTemp(Ity_I1);
14044 IRTemp frB_isZero = newTemp(Ity_I1);
14045 assign(frA_isZero, is_Zero(frA_I64, False /*not single precision*/ ));
14046 assign(frB_isZero, is_Zero(frB_I64, False /*not single precision*/ ));
14047 assign(anyNaN, mkOR1(is_NaN(frA_I64), is_NaN(frB_I64)));
14048 #define MINUS_ZERO 0x8000000000000000ULL
14049
14050 return IRExpr_ITE( /* If both arguments are zero . . . */
14051 mkAND1( mkexpr( frA_isZero ), mkexpr( frB_isZero ) ),
14052 /* then: if frA is -0 and isMin==True, return -0;
14053 * else if frA is +0 and isMin==False; return +0;
14054 * otherwise, simply return frB. */
14055 IRExpr_ITE( binop( Iop_CmpEQ32,
14056 unop( Iop_64HIto32,
14057 mkexpr( frA_I64 ) ),
14058 mkU32( isMin ? 0x80000000 : 0 ) ),
14059 mkU64( isMin ? MINUS_ZERO : 0ULL ),
14060 mkexpr( frB_I64 ) ),
14061 /* else: check if either input is a NaN*/
14062 IRExpr_ITE( mkexpr( anyNaN ),
14063 /* then: use "NaN helper" */
14064 _get_maxmin_fp_NaN( frA_I64, frB_I64 ),
14065 /* else: use "comparison helper" */
14066 _get_maxmin_fp_cmp( frB_I64, frA_I64, isMin ) ));
14067 }
14068
_get_vsx_rdpi_suffix(UInt opc2)14069 static const HChar * _get_vsx_rdpi_suffix(UInt opc2)
14070 {
14071 switch (opc2 & 0x7F) {
14072 case 0x72:
14073 return "m";
14074 case 0x52:
14075 return "p";
14076 case 0x56:
14077 return "c";
14078 case 0x32:
14079 return "z";
14080 case 0x12:
14081 return "";
14082
14083 default: // Impossible to get here
14084 vex_printf("Unrecognized opcode %x\n", opc2);
14085 vpanic("_get_vsx_rdpi_suffix(ppc)(opc2)");
14086 }
14087 }
14088
14089 /*
14090 * Helper function for vector/scalar double precision fp round to integer instructions.
14091 */
_do_vsx_fp_roundToInt(IRTemp frB_I64,UInt opc2)14092 static IRExpr * _do_vsx_fp_roundToInt(IRTemp frB_I64, UInt opc2)
14093 {
14094
14095 /* The same rules apply for x{s|v}rdpi{m|p|c|z} as for floating point round operations (fri{m|n|p|z}). */
14096 IRTemp frB = newTemp(Ity_F64);
14097 IRTemp frD = newTemp(Ity_F64);
14098 IRTemp intermediateResult = newTemp(Ity_I64);
14099 IRTemp is_SNAN = newTemp(Ity_I1);
14100 IRExpr * hi32;
14101 IRExpr * rxpi_rm;
14102 switch (opc2 & 0x7F) {
14103 case 0x72:
14104 rxpi_rm = mkU32(Irrm_NegINF);
14105 break;
14106 case 0x52:
14107 rxpi_rm = mkU32(Irrm_PosINF);
14108 break;
14109 case 0x56:
14110 rxpi_rm = get_IR_roundingmode();
14111 break;
14112 case 0x32:
14113 rxpi_rm = mkU32(Irrm_ZERO);
14114 break;
14115 case 0x12:
14116 rxpi_rm = mkU32(Irrm_NEAREST);
14117 break;
14118
14119 default: // Impossible to get here
14120 vex_printf("Unrecognized opcode %x\n", opc2);
14121 vpanic("_do_vsx_fp_roundToInt(ppc)(opc2)");
14122 }
14123 assign(frB, unop(Iop_ReinterpI64asF64, mkexpr(frB_I64)));
14124 assign( intermediateResult,
14125 binop( Iop_F64toI64S, rxpi_rm,
14126 mkexpr( frB ) ) );
14127
14128 /* don't use the rounded integer if frB is outside -9e18..9e18 */
14129 /* F64 has only log10(2**52) significant digits anyway */
14130 /* need to preserve sign of zero */
14131 /* frD = (fabs(frB) > 9e18) ? frB :
14132 (sign(frB)) ? -fabs((double)intermediateResult) : (double)intermediateResult */
14133 assign( frD,
14134 IRExpr_ITE(
14135 binop( Iop_CmpNE8,
14136 unop( Iop_32to8,
14137 binop( Iop_CmpF64,
14138 IRExpr_Const( IRConst_F64( 9e18 ) ),
14139 unop( Iop_AbsF64, mkexpr( frB ) ) ) ),
14140 mkU8(0) ),
14141 mkexpr( frB ),
14142 IRExpr_ITE(
14143 binop( Iop_CmpNE32,
14144 binop( Iop_Shr32,
14145 unop( Iop_64HIto32,
14146 mkexpr( frB_I64 ) ),
14147 mkU8( 31 ) ),
14148 mkU32(0) ),
14149 unop( Iop_NegF64,
14150 unop( Iop_AbsF64,
14151 binop( Iop_I64StoF64,
14152 mkU32( 0 ),
14153 mkexpr( intermediateResult ) ) ) ),
14154 binop( Iop_I64StoF64,
14155 mkU32( 0 ),
14156 mkexpr( intermediateResult ) )
14157 )
14158 )
14159 );
14160
14161 /* See Appendix "Floating-Point Round to Integer Model" in ISA doc.
14162 * If frB is a SNAN, then frD <- frB, with bit 12 set to '1'.
14163 */
14164 #define SNAN_MASK 0x0008000000000000ULL
14165 hi32 = unop( Iop_64HIto32, mkexpr(frB_I64) );
14166 assign( is_SNAN,
14167 mkAND1( is_NaN( frB_I64 ),
14168 binop( Iop_CmpEQ32,
14169 binop( Iop_And32, hi32, mkU32( 0x00080000 ) ),
14170 mkU32( 0 ) ) ) );
14171
14172 return IRExpr_ITE( mkexpr( is_SNAN ),
14173 unop( Iop_ReinterpI64asF64,
14174 binop( Iop_Xor64,
14175 mkU64( SNAN_MASK ),
14176 mkexpr( frB_I64 ) ) ),
14177 mkexpr( frD ));
14178 }
14179
14180 /*
14181 * Miscellaneous VSX vector instructions
14182 */
14183 static Bool
dis_vxv_misc(UInt theInstr,UInt opc2)14184 dis_vxv_misc ( UInt theInstr, UInt opc2 )
14185 {
14186 /* XX3-Form */
14187 UChar opc1 = ifieldOPC( theInstr );
14188 UChar XT = ifieldRegXT( theInstr );
14189 UChar XB = ifieldRegXB( theInstr );
14190
14191 if (opc1 != 0x3C) {
14192 vex_printf( "dis_vxv_misc(ppc)(instr)\n" );
14193 return False;
14194 }
14195
14196 switch (opc2) {
14197 case 0x1B4: // xvredp (VSX Vector Reciprocal Estimate Double-Precision)
14198 case 0x194: // xvrsqrtedp (VSX Vector Reciprocal Square Root Estimate
14199 // Double-Precision)
14200 {
14201 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
14202 IRExpr* rm = get_IR_roundingmode();
14203 IRTemp frB = newTemp(Ity_I64);
14204 IRTemp frB2 = newTemp(Ity_I64);
14205 Bool redp = opc2 == 0x1B4;
14206 IRTemp sqrtHi = newTemp(Ity_F64);
14207 IRTemp sqrtLo = newTemp(Ity_F64);
14208 assign(frB, unop(Iop_V128HIto64, getVSReg( XB )));
14209 assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
14210
14211 DIP("%s v%d,v%d\n", redp ? "xvredp" : "xvrsqrtedp", XT, XB);
14212 if (!redp) {
14213 assign( sqrtHi,
14214 binop( Iop_SqrtF64,
14215 rm,
14216 unop( Iop_ReinterpI64asF64, mkexpr( frB ) ) ) );
14217 assign( sqrtLo,
14218 binop( Iop_SqrtF64,
14219 rm,
14220 unop( Iop_ReinterpI64asF64, mkexpr( frB2 ) ) ) );
14221 }
14222 putVSReg( XT,
14223 binop( Iop_64HLtoV128,
14224 unop( Iop_ReinterpF64asI64,
14225 triop( Iop_DivF64,
14226 rm,
14227 ieee_one,
14228 redp ? unop( Iop_ReinterpI64asF64,
14229 mkexpr( frB ) )
14230 : mkexpr( sqrtHi ) ) ),
14231 unop( Iop_ReinterpF64asI64,
14232 triop( Iop_DivF64,
14233 rm,
14234 ieee_one,
14235 redp ? unop( Iop_ReinterpI64asF64,
14236 mkexpr( frB2 ) )
14237 : mkexpr( sqrtLo ) ) ) ) );
14238 break;
14239
14240 }
14241 case 0x134: // xvresp (VSX Vector Reciprocal Estimate Single-Precision)
14242 case 0x114: // xvrsqrtesp (VSX Vector Reciprocal Square Root Estimate Single-Precision)
14243 {
14244 IRTemp b3, b2, b1, b0;
14245 IRTemp res0 = newTemp(Ity_I32);
14246 IRTemp res1 = newTemp(Ity_I32);
14247 IRTemp res2 = newTemp(Ity_I32);
14248 IRTemp res3 = newTemp(Ity_I32);
14249 IRTemp sqrt3 = newTemp(Ity_F64);
14250 IRTemp sqrt2 = newTemp(Ity_F64);
14251 IRTemp sqrt1 = newTemp(Ity_F64);
14252 IRTemp sqrt0 = newTemp(Ity_F64);
14253 IRExpr* rm = get_IR_roundingmode();
14254 Bool resp = opc2 == 0x134;
14255
14256 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
14257
14258 b3 = b2 = b1 = b0 = IRTemp_INVALID;
14259 DIP("%s v%d,v%d\n", resp ? "xvresp" : "xvrsqrtesp", XT, XB);
14260 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
14261
14262 if (!resp) {
14263 assign( sqrt3, binop( Iop_SqrtF64, rm, mkexpr( b3 ) ) );
14264 assign( sqrt2, binop( Iop_SqrtF64, rm, mkexpr( b2 ) ) );
14265 assign( sqrt1, binop( Iop_SqrtF64, rm, mkexpr( b1 ) ) );
14266 assign( sqrt0, binop( Iop_SqrtF64, rm, mkexpr( b0 ) ) );
14267 }
14268
14269 assign( res0,
14270 unop( Iop_ReinterpF32asI32,
14271 unop( Iop_TruncF64asF32,
14272 triop( Iop_DivF64r32,
14273 rm,
14274 ieee_one,
14275 resp ? mkexpr( b0 ) : mkexpr( sqrt0 ) ) ) ) );
14276 assign( res1,
14277 unop( Iop_ReinterpF32asI32,
14278 unop( Iop_TruncF64asF32,
14279 triop( Iop_DivF64r32,
14280 rm,
14281 ieee_one,
14282 resp ? mkexpr( b1 ) : mkexpr( sqrt1 ) ) ) ) );
14283 assign( res2,
14284 unop( Iop_ReinterpF32asI32,
14285 unop( Iop_TruncF64asF32,
14286 triop( Iop_DivF64r32,
14287 rm,
14288 ieee_one,
14289 resp ? mkexpr( b2 ) : mkexpr( sqrt2 ) ) ) ) );
14290 assign( res3,
14291 unop( Iop_ReinterpF32asI32,
14292 unop( Iop_TruncF64asF32,
14293 triop( Iop_DivF64r32,
14294 rm,
14295 ieee_one,
14296 resp ? mkexpr( b3 ) : mkexpr( sqrt3 ) ) ) ) );
14297 putVSReg( XT,
14298 binop( Iop_64HLtoV128,
14299 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
14300 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
14301 break;
14302 }
14303 case 0x300: // xvmaxsp (VSX Vector Maximum Single-Precision)
14304 case 0x320: // xvminsp (VSX Vector Minimum Single-Precision)
14305 {
14306 UChar XA = ifieldRegXA( theInstr );
14307 IRTemp a3, a2, a1, a0;
14308 IRTemp b3, b2, b1, b0;
14309 IRTemp res0 = newTemp( Ity_I32 );
14310 IRTemp res1 = newTemp( Ity_I32 );
14311 IRTemp res2 = newTemp( Ity_I32 );
14312 IRTemp res3 = newTemp( Ity_I32 );
14313 IRTemp a0_I64 = newTemp( Ity_I64 );
14314 IRTemp a1_I64 = newTemp( Ity_I64 );
14315 IRTemp a2_I64 = newTemp( Ity_I64 );
14316 IRTemp a3_I64 = newTemp( Ity_I64 );
14317 IRTemp b0_I64 = newTemp( Ity_I64 );
14318 IRTemp b1_I64 = newTemp( Ity_I64 );
14319 IRTemp b2_I64 = newTemp( Ity_I64 );
14320 IRTemp b3_I64 = newTemp( Ity_I64 );
14321
14322 Bool isMin = opc2 == 0x320 ? True : False;
14323
14324 a3 = a2 = a1 = a0 = IRTemp_INVALID;
14325 b3 = b2 = b1 = b0 = IRTemp_INVALID;
14326 DIP("%s v%d,v%d v%d\n", isMin ? "xvminsp" : "xvmaxsp", XT, XA, XB);
14327 breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
14328 breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
14329 assign( a0_I64, unop( Iop_ReinterpF64asI64, mkexpr( a0 ) ) );
14330 assign( b0_I64, unop( Iop_ReinterpF64asI64, mkexpr( b0 ) ) );
14331 assign( a1_I64, unop( Iop_ReinterpF64asI64, mkexpr( a1 ) ) );
14332 assign( b1_I64, unop( Iop_ReinterpF64asI64, mkexpr( b1 ) ) );
14333 assign( a2_I64, unop( Iop_ReinterpF64asI64, mkexpr( a2 ) ) );
14334 assign( b2_I64, unop( Iop_ReinterpF64asI64, mkexpr( b2 ) ) );
14335 assign( a3_I64, unop( Iop_ReinterpF64asI64, mkexpr( a3 ) ) );
14336 assign( b3_I64, unop( Iop_ReinterpF64asI64, mkexpr( b3 ) ) );
14337 assign( res0,
14338 unop( Iop_ReinterpF32asI32,
14339 unop( Iop_TruncF64asF32,
14340 unop( Iop_ReinterpI64asF64,
14341 get_max_min_fp( a0_I64, b0_I64, isMin ) ) ) ) );
14342 assign( res1,
14343 unop( Iop_ReinterpF32asI32,
14344 unop( Iop_TruncF64asF32,
14345 unop( Iop_ReinterpI64asF64,
14346 get_max_min_fp( a1_I64, b1_I64, isMin ) ) ) ) );
14347 assign( res2,
14348 unop( Iop_ReinterpF32asI32,
14349 unop( Iop_TruncF64asF32,
14350 unop( Iop_ReinterpI64asF64,
14351 get_max_min_fp( a2_I64, b2_I64, isMin ) ) ) ) );
14352 assign( res3,
14353 unop( Iop_ReinterpF32asI32,
14354 unop( Iop_TruncF64asF32,
14355 unop( Iop_ReinterpI64asF64,
14356 get_max_min_fp( a3_I64, b3_I64, isMin ) ) ) ) );
14357 putVSReg( XT,
14358 binop( Iop_64HLtoV128,
14359 binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
14360 binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
14361 break;
14362 }
14363 case 0x380: // xvmaxdp (VSX Vector Maximum Double-Precision)
14364 case 0x3A0: // xvmindp (VSX Vector Minimum Double-Precision)
14365 {
14366 UChar XA = ifieldRegXA( theInstr );
14367 IRTemp frA = newTemp(Ity_I64);
14368 IRTemp frB = newTemp(Ity_I64);
14369 IRTemp frA2 = newTemp(Ity_I64);
14370 IRTemp frB2 = newTemp(Ity_I64);
14371 Bool isMin = opc2 == 0x3A0 ? True : False;
14372
14373 assign(frA, unop(Iop_V128HIto64, getVSReg( XA )));
14374 assign(frB, unop(Iop_V128HIto64, getVSReg( XB )));
14375 assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
14376 assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
14377 DIP("%s v%d,v%d v%d\n", isMin ? "xvmindp" : "xvmaxdp", XT, XA, XB);
14378 putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), get_max_min_fp(frA2, frB2, isMin) ) );
14379
14380 break;
14381 }
14382 case 0x3c0: // xvcpsgndp (VSX Vector Copy Sign Double-Precision)
14383 {
14384 UChar XA = ifieldRegXA( theInstr );
14385 IRTemp frA = newTemp(Ity_I64);
14386 IRTemp frB = newTemp(Ity_I64);
14387 IRTemp frA2 = newTemp(Ity_I64);
14388 IRTemp frB2 = newTemp(Ity_I64);
14389 assign(frA, unop(Iop_V128HIto64, getVSReg( XA )));
14390 assign(frB, unop(Iop_V128HIto64, getVSReg( XB )));
14391 assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
14392 assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
14393
14394 DIP("xvcpsgndp v%d,v%d,v%d\n", XT, XA, XB);
14395 putVSReg( XT,
14396 binop( Iop_64HLtoV128,
14397 binop( Iop_Or64,
14398 binop( Iop_And64,
14399 mkexpr( frA ),
14400 mkU64( SIGN_BIT ) ),
14401 binop( Iop_And64,
14402 mkexpr( frB ),
14403 mkU64( SIGN_MASK ) ) ),
14404 binop( Iop_Or64,
14405 binop( Iop_And64,
14406 mkexpr( frA2 ),
14407 mkU64( SIGN_BIT ) ),
14408 binop( Iop_And64,
14409 mkexpr( frB2 ),
14410 mkU64( SIGN_MASK ) ) ) ) );
14411 break;
14412 }
14413 case 0x340: // xvcpsgnsp
14414 {
14415 UChar XA = ifieldRegXA( theInstr );
14416 IRTemp a3_I64, a2_I64, a1_I64, a0_I64;
14417 IRTemp b3_I64, b2_I64, b1_I64, b0_I64;
14418 IRTemp resHi = newTemp(Ity_I64);
14419 IRTemp resLo = newTemp(Ity_I64);
14420
14421 a3_I64 = a2_I64 = a1_I64 = a0_I64 = IRTemp_INVALID;
14422 b3_I64 = b2_I64 = b1_I64 = b0_I64 = IRTemp_INVALID;
14423 DIP("xvcpsgnsp v%d,v%d v%d\n",XT, XA, XB);
14424 breakV128to4x64U( getVSReg( XA ), &a3_I64, &a2_I64, &a1_I64, &a0_I64 );
14425 breakV128to4x64U( getVSReg( XB ), &b3_I64, &b2_I64, &b1_I64, &b0_I64 );
14426
14427 assign( resHi,
14428 binop( Iop_32HLto64,
14429 binop( Iop_Or32,
14430 binop( Iop_And32,
14431 unop(Iop_64to32, mkexpr( a3_I64 ) ),
14432 mkU32( SIGN_BIT32 ) ),
14433 binop( Iop_And32,
14434 unop(Iop_64to32, mkexpr( b3_I64 ) ),
14435 mkU32( SIGN_MASK32) ) ),
14436
14437 binop( Iop_Or32,
14438 binop( Iop_And32,
14439 unop(Iop_64to32, mkexpr( a2_I64 ) ),
14440 mkU32( SIGN_BIT32 ) ),
14441 binop( Iop_And32,
14442 unop(Iop_64to32, mkexpr( b2_I64 ) ),
14443 mkU32( SIGN_MASK32 ) ) ) ) );
14444 assign( resLo,
14445 binop( Iop_32HLto64,
14446 binop( Iop_Or32,
14447 binop( Iop_And32,
14448 unop(Iop_64to32, mkexpr( a1_I64 ) ),
14449 mkU32( SIGN_BIT32 ) ),
14450 binop( Iop_And32,
14451 unop(Iop_64to32, mkexpr( b1_I64 ) ),
14452 mkU32( SIGN_MASK32 ) ) ),
14453
14454 binop( Iop_Or32,
14455 binop( Iop_And32,
14456 unop(Iop_64to32, mkexpr( a0_I64 ) ),
14457 mkU32( SIGN_BIT32 ) ),
14458 binop( Iop_And32,
14459 unop(Iop_64to32, mkexpr( b0_I64 ) ),
14460 mkU32( SIGN_MASK32 ) ) ) ) );
14461 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( resHi ), mkexpr( resLo ) ) );
14462 break;
14463 }
14464 case 0x3B2: // xvabsdp (VSX Vector Absolute Value Double-Precision)
14465 case 0x3D2: // xvnabsdp VSX Vector Negative Absolute Value Double-Precision)
14466 {
14467 IRTemp frB = newTemp(Ity_F64);
14468 IRTemp frB2 = newTemp(Ity_F64);
14469 IRTemp abs_resultHi = newTemp(Ity_F64);
14470 IRTemp abs_resultLo = newTemp(Ity_F64);
14471 Bool make_negative = (opc2 == 0x3D2) ? True : False;
14472 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
14473 assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
14474
14475 DIP("xv%sabsdp v%d,v%d\n", make_negative ? "n" : "", XT, XB);
14476 if (make_negative) {
14477 assign(abs_resultHi, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB ) ) ) );
14478 assign(abs_resultLo, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB2 ) ) ) );
14479
14480 } else {
14481 assign(abs_resultHi, unop( Iop_AbsF64, mkexpr( frB ) ) );
14482 assign(abs_resultLo, unop( Iop_AbsF64, mkexpr( frB2 ) ) );
14483 }
14484 putVSReg( XT, binop( Iop_64HLtoV128,
14485 unop( Iop_ReinterpF64asI64, mkexpr( abs_resultHi ) ),
14486 unop( Iop_ReinterpF64asI64, mkexpr( abs_resultLo ) ) ) );
14487 break;
14488 }
14489 case 0x332: // xvabssp (VSX Vector Absolute Value Single-Precision)
14490 case 0x352: // xvnabssp (VSX Vector Negative Absolute Value Single-Precision)
14491 {
14492 /*
14493 * The Iop_AbsF32 IRop is not implemented for ppc64 since, up until introduction
14494 * of xvabssp, there has not been an abs(sp) type of instruction. But since emulation
14495 * of this function is so easy using shifts, I choose to emulate this instruction that
14496 * way versus a native instruction method of implementation.
14497 */
14498 Bool make_negative = (opc2 == 0x352) ? True : False;
14499 IRTemp shiftVector = newTemp(Ity_V128);
14500 IRTemp absVal_vector = newTemp(Ity_V128);
14501 assign( shiftVector,
14502 binop( Iop_64HLtoV128,
14503 binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ),
14504 binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ) ) );
14505 assign( absVal_vector,
14506 binop( Iop_Shr32x4,
14507 binop( Iop_Shl32x4,
14508 getVSReg( XB ),
14509 mkexpr( shiftVector ) ),
14510 mkexpr( shiftVector ) ) );
14511 if (make_negative) {
14512 IRTemp signBit_vector = newTemp(Ity_V128);
14513 assign( signBit_vector,
14514 binop( Iop_64HLtoV128,
14515 binop( Iop_32HLto64,
14516 mkU32( 0x80000000 ),
14517 mkU32( 0x80000000 ) ),
14518 binop( Iop_32HLto64,
14519 mkU32( 0x80000000 ),
14520 mkU32( 0x80000000 ) ) ) );
14521 putVSReg( XT,
14522 binop( Iop_OrV128,
14523 mkexpr( absVal_vector ),
14524 mkexpr( signBit_vector ) ) );
14525 } else {
14526 putVSReg( XT, mkexpr( absVal_vector ) );
14527 }
14528 break;
14529 }
14530 case 0x3F2: // xvnegdp (VSX Vector Negate Double-Precision)
14531 {
14532 IRTemp frB = newTemp(Ity_F64);
14533 IRTemp frB2 = newTemp(Ity_F64);
14534 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
14535 assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
14536 DIP("xvnegdp v%d,v%d\n", XT, XB);
14537 putVSReg( XT,
14538 binop( Iop_64HLtoV128,
14539 unop( Iop_ReinterpF64asI64,
14540 unop( Iop_NegF64, mkexpr( frB ) ) ),
14541 unop( Iop_ReinterpF64asI64,
14542 unop( Iop_NegF64, mkexpr( frB2 ) ) ) ) );
14543 break;
14544 }
14545 case 0x192: // xvrdpi (VSX Vector Round to Double-Precision Integer using round toward Nearest Away)
14546 case 0x1D6: // xvrdpic (VSX Vector Round to Double-Precision Integer using Current rounding mode)
14547 case 0x1F2: // xvrdpim (VSX Vector Round to Double-Precision Integer using round toward -Infinity)
14548 case 0x1D2: // xvrdpip (VSX Vector Round to Double-Precision Integer using round toward +Infinity)
14549 case 0x1B2: // xvrdpiz (VSX Vector Round to Double-Precision Integer using round toward Zero)
14550 {
14551 IRTemp frBHi_I64 = newTemp(Ity_I64);
14552 IRTemp frBLo_I64 = newTemp(Ity_I64);
14553 IRExpr * frD_fp_roundHi = NULL;
14554 IRExpr * frD_fp_roundLo = NULL;
14555
14556 assign( frBHi_I64, unop( Iop_V128HIto64, getVSReg( XB ) ) );
14557 frD_fp_roundHi = _do_vsx_fp_roundToInt(frBHi_I64, opc2);
14558 assign( frBLo_I64, unop( Iop_V128to64, getVSReg( XB ) ) );
14559 frD_fp_roundLo = _do_vsx_fp_roundToInt(frBLo_I64, opc2);
14560
14561 DIP("xvrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), XT, XB);
14562 putVSReg( XT,
14563 binop( Iop_64HLtoV128,
14564 unop( Iop_ReinterpF64asI64, frD_fp_roundHi ),
14565 unop( Iop_ReinterpF64asI64, frD_fp_roundLo ) ) );
14566 break;
14567 }
14568 case 0x112: // xvrspi (VSX Vector Round to Single-Precision Integer using round toward Nearest Away)
14569 case 0x156: // xvrspic (VSX Vector Round to SinglePrecision Integer using Current rounding mode)
14570 case 0x172: // xvrspim (VSX Vector Round to SinglePrecision Integer using round toward -Infinity)
14571 case 0x152: // xvrspip (VSX Vector Round to SinglePrecision Integer using round toward +Infinity)
14572 case 0x132: // xvrspiz (VSX Vector Round to SinglePrecision Integer using round toward Zero)
14573 {
14574 const HChar * insn_suffix = NULL;
14575 IROp op;
14576 if (opc2 != 0x156) {
14577 // Use pre-defined IRop's for vrfi{m|n|p|z}
14578 switch (opc2) {
14579 case 0x112:
14580 insn_suffix = "";
14581 op = Iop_RoundF32x4_RN;
14582 break;
14583 case 0x172:
14584 insn_suffix = "m";
14585 op = Iop_RoundF32x4_RM;
14586 break;
14587 case 0x152:
14588 insn_suffix = "p";
14589 op = Iop_RoundF32x4_RP;
14590 break;
14591 case 0x132:
14592 insn_suffix = "z";
14593 op = Iop_RoundF32x4_RZ;
14594 break;
14595
14596 default:
14597 vex_printf("Unrecognized opcode %x\n", opc2);
14598 vpanic("dis_vxv_misc(ppc)(vrspi<x>)(opc2)\n");
14599 }
14600 DIP("xvrspi%s v%d,v%d\n", insn_suffix, XT, XB);
14601 putVSReg( XT, unop( op, getVSReg(XB) ) );
14602 } else {
14603 // Handle xvrspic. Unfortunately there is no corresponding "vfric" instruction.
14604 IRExpr * frD_fp_roundb3, * frD_fp_roundb2, * frD_fp_roundb1, * frD_fp_roundb0;
14605 IRTemp b3_F64, b2_F64, b1_F64, b0_F64;
14606 IRTemp b3_I64 = newTemp(Ity_I64);
14607 IRTemp b2_I64 = newTemp(Ity_I64);
14608 IRTemp b1_I64 = newTemp(Ity_I64);
14609 IRTemp b0_I64 = newTemp(Ity_I64);
14610
14611 b3_F64 = b2_F64 = b1_F64 = b0_F64 = IRTemp_INVALID;
14612 frD_fp_roundb3 = frD_fp_roundb2 = frD_fp_roundb1 = frD_fp_roundb0 = NULL;
14613 breakV128to4xF64( getVSReg(XB), &b3_F64, &b2_F64, &b1_F64, &b0_F64);
14614 assign(b3_I64, unop(Iop_ReinterpF64asI64, mkexpr(b3_F64)));
14615 assign(b2_I64, unop(Iop_ReinterpF64asI64, mkexpr(b2_F64)));
14616 assign(b1_I64, unop(Iop_ReinterpF64asI64, mkexpr(b1_F64)));
14617 assign(b0_I64, unop(Iop_ReinterpF64asI64, mkexpr(b0_F64)));
14618 frD_fp_roundb3 = unop(Iop_TruncF64asF32,
14619 _do_vsx_fp_roundToInt(b3_I64, opc2));
14620 frD_fp_roundb2 = unop(Iop_TruncF64asF32,
14621 _do_vsx_fp_roundToInt(b2_I64, opc2));
14622 frD_fp_roundb1 = unop(Iop_TruncF64asF32,
14623 _do_vsx_fp_roundToInt(b1_I64, opc2));
14624 frD_fp_roundb0 = unop(Iop_TruncF64asF32,
14625 _do_vsx_fp_roundToInt(b0_I64, opc2));
14626 DIP("xvrspic v%d,v%d\n", XT, XB);
14627 putVSReg( XT,
14628 binop( Iop_64HLtoV128,
14629 binop( Iop_32HLto64,
14630 unop( Iop_ReinterpF32asI32, frD_fp_roundb3 ),
14631 unop( Iop_ReinterpF32asI32, frD_fp_roundb2 ) ),
14632 binop( Iop_32HLto64,
14633 unop( Iop_ReinterpF32asI32, frD_fp_roundb1 ),
14634 unop( Iop_ReinterpF32asI32, frD_fp_roundb0 ) ) ) );
14635 }
14636 break;
14637 }
14638
14639 default:
14640 vex_printf( "dis_vxv_misc(ppc)(opc2)\n" );
14641 return False;
14642 }
14643 return True;
14644 }
14645
14646
14647 /*
14648 * VSX Scalar Floating Point Arithmetic Instructions
14649 */
14650 static Bool
dis_vxs_arith(UInt theInstr,UInt opc2)14651 dis_vxs_arith ( UInt theInstr, UInt opc2 )
14652 {
14653 /* XX3-Form */
14654 UChar opc1 = ifieldOPC( theInstr );
14655 UChar XT = ifieldRegXT( theInstr );
14656 UChar XA = ifieldRegXA( theInstr );
14657 UChar XB = ifieldRegXB( theInstr );
14658 IRExpr* rm = get_IR_roundingmode();
14659 IRTemp frA = newTemp(Ity_F64);
14660 IRTemp frB = newTemp(Ity_F64);
14661
14662 if (opc1 != 0x3C) {
14663 vex_printf( "dis_vxs_arith(ppc)(instr)\n" );
14664 return False;
14665 }
14666
14667 assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
14668 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
14669
14670 /* For all the VSX sclar arithmetic instructions, the contents of doubleword element 1
14671 * of VSX[XT] are undefined after the operation; therefore, we can simply set
14672 * element to zero where it makes sense to do so.
14673 */
14674 switch (opc2) {
14675 case 0x000: // xsaddsp (VSX Scalar Add Single-Precision)
14676 DIP("xsaddsp v%d,v%d,v%d\n", XT, XA, XB);
14677 putVSReg( XT, binop( Iop_64HLtoV128,
14678 unop( Iop_ReinterpF64asI64,
14679 binop( Iop_RoundF64toF32, rm,
14680 triop( Iop_AddF64, rm,
14681 mkexpr( frA ),
14682 mkexpr( frB ) ) ) ),
14683 mkU64( 0 ) ) );
14684 break;
14685 case 0x020: // xssubsp (VSX Scalar Subtract Single-Precision)
14686 DIP("xssubsp v%d,v%d,v%d\n", XT, XA, XB);
14687 putVSReg( XT, binop( Iop_64HLtoV128,
14688 unop( Iop_ReinterpF64asI64,
14689 binop( Iop_RoundF64toF32, rm,
14690 triop( Iop_SubF64, rm,
14691 mkexpr( frA ),
14692 mkexpr( frB ) ) ) ),
14693 mkU64( 0 ) ) );
14694 break;
14695 case 0x080: // xsadddp (VSX scalar add double-precision)
14696 DIP("xsadddp v%d,v%d,v%d\n", XT, XA, XB);
14697 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
14698 triop( Iop_AddF64, rm,
14699 mkexpr( frA ),
14700 mkexpr( frB ) ) ),
14701 mkU64( 0 ) ) );
14702 break;
14703 case 0x060: // xsdivsp (VSX scalar divide single-precision)
14704 DIP("xsdivsp v%d,v%d,v%d\n", XT, XA, XB);
14705 putVSReg( XT, binop( Iop_64HLtoV128,
14706 unop( Iop_ReinterpF64asI64,
14707 binop( Iop_RoundF64toF32, rm,
14708 triop( Iop_DivF64, rm,
14709 mkexpr( frA ),
14710 mkexpr( frB ) ) ) ),
14711 mkU64( 0 ) ) );
14712 break;
14713 case 0x0E0: // xsdivdp (VSX scalar divide double-precision)
14714 DIP("xsdivdp v%d,v%d,v%d\n", XT, XA, XB);
14715 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
14716 triop( Iop_DivF64, rm,
14717 mkexpr( frA ),
14718 mkexpr( frB ) ) ),
14719 mkU64( 0 ) ) );
14720 break;
14721 case 0x004: case 0x024: /* xsmaddasp, xsmaddmsp (VSX scalar multiply-add
14722 * single-precision)
14723 */
14724 {
14725 IRTemp frT = newTemp(Ity_F64);
14726 Bool mdp = opc2 == 0x024;
14727 DIP("xsmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
14728 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14729 getVSReg( XT ) ) ) );
14730 putVSReg( XT,
14731 binop( Iop_64HLtoV128,
14732 unop( Iop_ReinterpF64asI64,
14733 binop( Iop_RoundF64toF32, rm,
14734 qop( Iop_MAddF64, rm,
14735 mkexpr( frA ),
14736 mkexpr( mdp ? frT : frB ),
14737 mkexpr( mdp ? frB : frT ) ) ) ),
14738 mkU64( 0 ) ) );
14739 break;
14740 }
14741 case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp (VSX scalar multiply-add double-precision)
14742 {
14743 IRTemp frT = newTemp(Ity_F64);
14744 Bool mdp = opc2 == 0x0A4;
14745 DIP("xsmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
14746 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14747 getVSReg( XT ) ) ) );
14748 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
14749 qop( Iop_MAddF64, rm,
14750 mkexpr( frA ),
14751 mkexpr( mdp ? frT : frB ),
14752 mkexpr( mdp ? frB : frT ) ) ),
14753 mkU64( 0 ) ) );
14754 break;
14755 }
14756 case 0x044: case 0x064: /* xsmsubasp, xsmsubmsp (VSX scalar
14757 * multiply-subtract single-precision)
14758 */
14759 {
14760 IRTemp frT = newTemp(Ity_F64);
14761 Bool mdp = opc2 == 0x064;
14762 DIP("xsmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
14763 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14764 getVSReg( XT ) ) ) );
14765 putVSReg( XT,
14766 binop( Iop_64HLtoV128,
14767 unop( Iop_ReinterpF64asI64,
14768 binop( Iop_RoundF64toF32, rm,
14769 qop( Iop_MSubF64, rm,
14770 mkexpr( frA ),
14771 mkexpr( mdp ? frT : frB ),
14772 mkexpr( mdp ? frB : frT ) ) ) ),
14773 mkU64( 0 ) ) );
14774 break;
14775 }
14776 case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp (VSX scalar multiply-subtract double-precision)
14777 {
14778 IRTemp frT = newTemp(Ity_F64);
14779 Bool mdp = opc2 == 0x0E4;
14780 DIP("xsmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
14781 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14782 getVSReg( XT ) ) ) );
14783 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
14784 qop( Iop_MSubF64, rm,
14785 mkexpr( frA ),
14786 mkexpr( mdp ? frT : frB ),
14787 mkexpr( mdp ? frB : frT ) ) ),
14788 mkU64( 0 ) ) );
14789 break;
14790 }
14791 case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp (VSX scalar multiply-add double-precision)
14792 {
14793 /* TODO: mpj -- Naturally, I expected to be able to leverage the implementation
14794 * of fnmadd and use pretty much the same code. However, that code has a bug in the
14795 * way it blindly negates the signbit, even if the floating point result is a NaN.
14796 * So, the TODO is to fix fnmadd (which I'll do in a different patch).
14797 * FIXED 7/1/2012: carll fnmadd and fnmsubs fixed to not negate sign
14798 * bit for NaN result.
14799 */
14800 Bool mdp = opc2 == 0x2A4;
14801 IRTemp frT = newTemp(Ity_F64);
14802 IRTemp maddResult = newTemp(Ity_I64);
14803
14804 DIP("xsnmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
14805 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14806 getVSReg( XT ) ) ) );
14807 assign( maddResult, unop( Iop_ReinterpF64asI64, qop( Iop_MAddF64, rm,
14808 mkexpr( frA ),
14809 mkexpr( mdp ? frT : frB ),
14810 mkexpr( mdp ? frB : frT ) ) ) );
14811
14812 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(maddResult) ),
14813 mkU64( 0 ) ) );
14814 break;
14815 }
14816 case 0x204: case 0x224: /* xsnmaddasp, xsnmaddmsp (VSX scalar
14817 * multiply-add single-precision)
14818 */
14819 {
14820 Bool mdp = opc2 == 0x224;
14821 IRTemp frT = newTemp(Ity_F64);
14822 IRTemp maddResult = newTemp(Ity_I64);
14823
14824 DIP("xsnmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
14825 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14826 getVSReg( XT ) ) ) );
14827 assign( maddResult,
14828 unop( Iop_ReinterpF64asI64,
14829 binop( Iop_RoundF64toF32, rm,
14830 qop( Iop_MAddF64, rm,
14831 mkexpr( frA ),
14832 mkexpr( mdp ? frT : frB ),
14833 mkexpr( mdp ? frB : frT ) ) ) ) );
14834
14835 putVSReg( XT, binop( Iop_64HLtoV128,
14836 mkexpr( getNegatedResult(maddResult) ),
14837 mkU64( 0 ) ) );
14838 break;
14839 }
14840 case 0x244: case 0x264: /* xsnmsubasp, xsnmsubmsp (VSX Scalar Negative
14841 * Multiply-Subtract Single-Precision)
14842 */
14843 {
14844 IRTemp frT = newTemp(Ity_F64);
14845 Bool mdp = opc2 == 0x264;
14846 IRTemp msubResult = newTemp(Ity_I64);
14847
14848 DIP("xsnmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
14849 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14850 getVSReg( XT ) ) ) );
14851 assign( msubResult,
14852 unop( Iop_ReinterpF64asI64,
14853 binop( Iop_RoundF64toF32, rm,
14854 qop( Iop_MSubF64, rm,
14855 mkexpr( frA ),
14856 mkexpr( mdp ? frT : frB ),
14857 mkexpr( mdp ? frB : frT ) ) ) ) );
14858
14859 putVSReg( XT, binop( Iop_64HLtoV128,
14860 mkexpr( getNegatedResult(msubResult) ),
14861 mkU64( 0 ) ) );
14862
14863 break;
14864 }
14865
14866 case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp (VSX Scalar Negative Multiply-Subtract Double-Precision)
14867 {
14868 IRTemp frT = newTemp(Ity_F64);
14869 Bool mdp = opc2 == 0x2E4;
14870 IRTemp msubResult = newTemp(Ity_I64);
14871
14872 DIP("xsnmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
14873 assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14874 getVSReg( XT ) ) ) );
14875 assign(msubResult, unop( Iop_ReinterpF64asI64,
14876 qop( Iop_MSubF64,
14877 rm,
14878 mkexpr( frA ),
14879 mkexpr( mdp ? frT : frB ),
14880 mkexpr( mdp ? frB : frT ) ) ));
14881
14882 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(msubResult) ), mkU64( 0 ) ) );
14883
14884 break;
14885 }
14886
14887 case 0x040: // xsmulsp (VSX Scalar Multiply Single-Precision)
14888 DIP("xsmulsp v%d,v%d,v%d\n", XT, XA, XB);
14889 putVSReg( XT, binop( Iop_64HLtoV128,
14890 unop( Iop_ReinterpF64asI64,
14891 binop( Iop_RoundF64toF32, rm,
14892 triop( Iop_MulF64, rm,
14893 mkexpr( frA ),
14894 mkexpr( frB ) ) ) ),
14895 mkU64( 0 ) ) );
14896 break;
14897
14898 case 0x0C0: // xsmuldp (VSX Scalar Multiply Double-Precision)
14899 DIP("xsmuldp v%d,v%d,v%d\n", XT, XA, XB);
14900 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
14901 triop( Iop_MulF64, rm,
14902 mkexpr( frA ),
14903 mkexpr( frB ) ) ),
14904 mkU64( 0 ) ) );
14905 break;
14906 case 0x0A0: // xssubdp (VSX Scalar Subtract Double-Precision)
14907 DIP("xssubdp v%d,v%d,v%d\n", XT, XA, XB);
14908 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
14909 triop( Iop_SubF64, rm,
14910 mkexpr( frA ),
14911 mkexpr( frB ) ) ),
14912 mkU64( 0 ) ) );
14913 break;
14914
14915 case 0x016: // xssqrtsp (VSX Scalar Square Root Single-Precision)
14916 DIP("xssqrtsp v%d,v%d\n", XT, XB);
14917 putVSReg( XT,
14918 binop( Iop_64HLtoV128,
14919 unop( Iop_ReinterpF64asI64,
14920 binop( Iop_RoundF64toF32, rm,
14921 binop( Iop_SqrtF64, rm,
14922 mkexpr( frB ) ) ) ),
14923 mkU64( 0 ) ) );
14924 break;
14925
14926 case 0x096: // xssqrtdp (VSX Scalar Square Root Double-Precision)
14927 DIP("xssqrtdp v%d,v%d\n", XT, XB);
14928 putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
14929 binop( Iop_SqrtF64, rm,
14930 mkexpr( frB ) ) ),
14931 mkU64( 0 ) ) );
14932 break;
14933
14934 case 0x0F4: // xstdivdp (VSX Scalar Test for software Divide Double-Precision)
14935 {
14936 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) );
14937 IRTemp frA_I64 = newTemp(Ity_I64);
14938 IRTemp frB_I64 = newTemp(Ity_I64);
14939 DIP("xstdivdp crf%d,v%d,v%d\n", crfD, XA, XB);
14940 assign( frA_I64, unop( Iop_ReinterpF64asI64, mkexpr( frA ) ) );
14941 assign( frB_I64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
14942 putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
14943 break;
14944 }
14945 case 0x0D4: // xstsqrtdp (VSX Vector Test for software Square Root Double-Precision)
14946 {
14947 IRTemp frB_I64 = newTemp(Ity_I64);
14948 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) );
14949 IRTemp flags = newTemp(Ity_I32);
14950 IRTemp fe_flag, fg_flag;
14951 fe_flag = fg_flag = IRTemp_INVALID;
14952 DIP("xstsqrtdp v%d,v%d\n", XT, XB);
14953 assign( frB_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
14954 do_fp_tsqrt(frB_I64, False /*not single precision*/, &fe_flag, &fg_flag);
14955 /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
14956 * where fl_flag == 1 on ppc64.
14957 */
14958 assign( flags,
14959 binop( Iop_Or32,
14960 binop( Iop_Or32, mkU32( 8 ), // fl_flag
14961 binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
14962 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
14963 putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
14964 break;
14965 }
14966
14967 default:
14968 vex_printf( "dis_vxs_arith(ppc)(opc2)\n" );
14969 return False;
14970 }
14971
14972 return True;
14973 }
14974
14975
14976 /*
14977 * VSX Floating Point Compare Instructions
14978 */
14979 static Bool
dis_vx_cmp(UInt theInstr,UInt opc2)14980 dis_vx_cmp( UInt theInstr, UInt opc2 )
14981 {
14982 /* XX3-Form and XX2-Form */
14983 UChar opc1 = ifieldOPC( theInstr );
14984 UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) );
14985 IRTemp ccPPC32;
14986 UChar XA = ifieldRegXA ( theInstr );
14987 UChar XB = ifieldRegXB ( theInstr );
14988 IRTemp frA = newTemp(Ity_F64);
14989 IRTemp frB = newTemp(Ity_F64);
14990
14991 if (opc1 != 0x3C) {
14992 vex_printf( "dis_vx_cmp(ppc)(instr)\n" );
14993 return False;
14994 }
14995
14996 assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
14997 assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
14998 switch (opc2) {
14999 case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
15000 /* Note: Differences between xscmpudp and xscmpodp are only in
15001 * exception flag settings, which aren't supported anyway. */
15002 DIP("xscmp%sdp crf%d,fr%u,fr%u\n", opc2 == 0x08c ? "u" : "o",
15003 crfD, XA, XB);
15004 ccPPC32 = get_fp_cmp_CR_val( binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)));
15005 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
15006 break;
15007
15008 default:
15009 vex_printf( "dis_vx_cmp(ppc)(opc2)\n" );
15010 return False;
15011 }
15012 return True;
15013 }
15014
15015 static void
do_vvec_fp_cmp(IRTemp vA,IRTemp vB,UChar XT,UChar flag_rC,ppc_cmp_t cmp_type)15016 do_vvec_fp_cmp ( IRTemp vA, IRTemp vB, UChar XT, UChar flag_rC,
15017 ppc_cmp_t cmp_type )
15018 {
15019 IRTemp frA_hi = newTemp(Ity_F64);
15020 IRTemp frB_hi = newTemp(Ity_F64);
15021 IRTemp frA_lo = newTemp(Ity_F64);
15022 IRTemp frB_lo = newTemp(Ity_F64);
15023 IRTemp ccPPC32 = newTemp(Ity_I32);
15024 IRTemp ccIR_hi;
15025 IRTemp ccIR_lo;
15026
15027 IRTemp hiResult = newTemp(Ity_I64);
15028 IRTemp loResult = newTemp(Ity_I64);
15029 IRTemp hiEQlo = newTemp(Ity_I1);
15030 IRTemp all_elem_true = newTemp(Ity_I32);
15031 IRTemp all_elem_false = newTemp(Ity_I32);
15032
15033 assign(frA_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vA ))));
15034 assign(frB_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vB ))));
15035 assign(frA_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vA ))));
15036 assign(frB_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vB ))));
15037
15038 ccIR_hi = get_fp_cmp_CR_val( binop( Iop_CmpF64,
15039 mkexpr( frA_hi ),
15040 mkexpr( frB_hi ) ) );
15041 ccIR_lo = get_fp_cmp_CR_val( binop( Iop_CmpF64,
15042 mkexpr( frA_lo ),
15043 mkexpr( frB_lo ) ) );
15044
15045 if (cmp_type != PPC_CMP_GE) {
15046 assign( hiResult,
15047 unop( Iop_1Sto64,
15048 binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( cmp_type ) ) ) );
15049 assign( loResult,
15050 unop( Iop_1Sto64,
15051 binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( cmp_type ) ) ) );
15052 } else {
15053 // For PPC_CMP_GE, one element compare may return "4" (for "greater than") and
15054 // the other element compare may return "2" (for "equal to").
15055 IRTemp lo_GE = newTemp(Ity_I1);
15056 IRTemp hi_GE = newTemp(Ity_I1);
15057
15058 assign(hi_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 2 ) ),
15059 binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 4 ) ) ) );
15060 assign( hiResult,unop( Iop_1Sto64, mkexpr( hi_GE ) ) );
15061
15062 assign(lo_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 2 ) ),
15063 binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 4 ) ) ) );
15064 assign( loResult, unop( Iop_1Sto64, mkexpr( lo_GE ) ) );
15065 }
15066
15067 // The [hi/lo]Result will be all 1's or all 0's. We just look at the lower word.
15068 assign( hiEQlo,
15069 binop( Iop_CmpEQ32,
15070 unop( Iop_64to32, mkexpr( hiResult ) ),
15071 unop( Iop_64to32, mkexpr( loResult ) ) ) );
15072 putVSReg( XT,
15073 binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
15074
15075 assign( all_elem_true,
15076 unop( Iop_1Uto32,
15077 mkAND1( mkexpr( hiEQlo ),
15078 binop( Iop_CmpEQ32,
15079 mkU32( 0xffffffff ),
15080 unop( Iop_64to32,
15081 mkexpr( hiResult ) ) ) ) ) );
15082
15083 assign( all_elem_false,
15084 unop( Iop_1Uto32,
15085 mkAND1( mkexpr( hiEQlo ),
15086 binop( Iop_CmpEQ32,
15087 mkU32( 0 ),
15088 unop( Iop_64to32,
15089 mkexpr( hiResult ) ) ) ) ) );
15090 assign( ccPPC32,
15091 binop( Iop_Or32,
15092 binop( Iop_Shl32, mkexpr( all_elem_false ), mkU8( 1 ) ),
15093 binop( Iop_Shl32, mkexpr( all_elem_true ), mkU8( 3 ) ) ) );
15094
15095 if (flag_rC) {
15096 putGST_field( PPC_GST_CR, mkexpr(ccPPC32), 6 );
15097 }
15098 }
15099
15100 /*
15101 * VSX Vector Compare Instructions
15102 */
15103 static Bool
dis_vvec_cmp(UInt theInstr,UInt opc2)15104 dis_vvec_cmp( UInt theInstr, UInt opc2 )
15105 {
15106 /* XX3-Form */
15107 UChar opc1 = ifieldOPC( theInstr );
15108 UChar XT = ifieldRegXT ( theInstr );
15109 UChar XA = ifieldRegXA ( theInstr );
15110 UChar XB = ifieldRegXB ( theInstr );
15111 UChar flag_rC = ifieldBIT10(theInstr);
15112 IRTemp vA = newTemp( Ity_V128 );
15113 IRTemp vB = newTemp( Ity_V128 );
15114
15115 if (opc1 != 0x3C) {
15116 vex_printf( "dis_vvec_cmp(ppc)(instr)\n" );
15117 return False;
15118 }
15119
15120 assign( vA, getVSReg( XA ) );
15121 assign( vB, getVSReg( XB ) );
15122
15123 switch (opc2) {
15124 case 0x18C: case 0x38C: // xvcmpeqdp[.] (VSX Vector Compare Equal To Double-Precision [ & Record ])
15125 {
15126 DIP("xvcmpeqdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
15127 XT, XA, XB);
15128 do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_EQ);
15129 break;
15130 }
15131
15132 case 0x1CC: case 0x3CC: // xvcmpgedp[.] (VSX Vector Compare Greater Than or Equal To Double-Precision [ & Record ])
15133 {
15134 DIP("xvcmpgedp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
15135 XT, XA, XB);
15136 do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GE);
15137 break;
15138 }
15139
15140 case 0x1AC: case 0x3AC: // xvcmpgtdp[.] (VSX Vector Compare Greater Than Double-Precision [ & Record ])
15141 {
15142 DIP("xvcmpgtdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
15143 XT, XA, XB);
15144 do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GT);
15145 break;
15146 }
15147
15148 case 0x10C: case 0x30C: // xvcmpeqsp[.] (VSX Vector Compare Equal To Single-Precision [ & Record ])
15149 {
15150 IRTemp vD = newTemp(Ity_V128);
15151
15152 DIP("xvcmpeqsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
15153 XT, XA, XB);
15154 assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
15155 putVSReg( XT, mkexpr(vD) );
15156 if (flag_rC) {
15157 set_AV_CR6( mkexpr(vD), True );
15158 }
15159 break;
15160 }
15161
15162 case 0x14C: case 0x34C: // xvcmpgesp[.] (VSX Vector Compare Greater Than or Equal To Single-Precision [ & Record ])
15163 {
15164 IRTemp vD = newTemp(Ity_V128);
15165
15166 DIP("xvcmpgesp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
15167 XT, XA, XB);
15168 assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
15169 putVSReg( XT, mkexpr(vD) );
15170 if (flag_rC) {
15171 set_AV_CR6( mkexpr(vD), True );
15172 }
15173 break;
15174 }
15175
15176 case 0x12C: case 0x32C: //xvcmpgtsp[.] (VSX Vector Compare Greater Than Single-Precision [ & Record ])
15177 {
15178 IRTemp vD = newTemp(Ity_V128);
15179
15180 DIP("xvcmpgtsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
15181 XT, XA, XB);
15182 assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
15183 putVSReg( XT, mkexpr(vD) );
15184 if (flag_rC) {
15185 set_AV_CR6( mkexpr(vD), True );
15186 }
15187 break;
15188 }
15189
15190 default:
15191 vex_printf( "dis_vvec_cmp(ppc)(opc2)\n" );
15192 return False;
15193 }
15194 return True;
15195 }
15196 /*
15197 * Miscellaneous VSX Scalar Instructions
15198 */
15199 static Bool
dis_vxs_misc(UInt theInstr,UInt opc2)15200 dis_vxs_misc( UInt theInstr, UInt opc2 )
15201 {
15202 #define VG_PPC_SIGN_MASK 0x7fffffffffffffffULL
15203 /* XX3-Form and XX2-Form */
15204 UChar opc1 = ifieldOPC( theInstr );
15205 UChar XT = ifieldRegXT ( theInstr );
15206 UChar XA = ifieldRegXA ( theInstr );
15207 UChar XB = ifieldRegXB ( theInstr );
15208 IRTemp vA = newTemp( Ity_V128 );
15209 IRTemp vB = newTemp( Ity_V128 );
15210
15211 if (opc1 != 0x3C) {
15212 vex_printf( "dis_vxs_misc(ppc)(instr)\n" );
15213 return False;
15214 }
15215
15216 assign( vA, getVSReg( XA ) );
15217 assign( vB, getVSReg( XB ) );
15218
15219 /* For all the VSX move instructions, the contents of doubleword element 1
15220 * of VSX[XT] are undefined after the operation; therefore, we can simply
15221 * move the entire array element where it makes sense to do so.
15222 */
15223
15224 switch (opc2) {
15225 case 0x2B2: // xsabsdp (VSX scalar absolute value double-precision
15226 {
15227 /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */
15228 IRTemp absVal = newTemp(Ity_V128);
15229 if (host_endness == VexEndnessLE) {
15230 IRTemp hi64 = newTemp(Ity_I64);
15231 IRTemp lo64 = newTemp(Ity_I64);
15232 assign( hi64, unop( Iop_V128HIto64, mkexpr(vB) ) );
15233 assign( lo64, unop( Iop_V128to64, mkexpr(vB) ) );
15234 assign( absVal, binop( Iop_64HLtoV128,
15235 binop( Iop_And64, mkexpr(hi64),
15236 mkU64(VG_PPC_SIGN_MASK) ),
15237 mkexpr(lo64) ) );
15238 } else {
15239 assign(absVal, binop(Iop_ShrV128,
15240 binop(Iop_ShlV128, mkexpr(vB),
15241 mkU8(1)), mkU8(1)));
15242 }
15243 DIP("xsabsdp v%d,v%d\n", XT, XB);
15244 putVSReg(XT, mkexpr(absVal));
15245 break;
15246 }
15247 case 0x2C0: // xscpsgndp
15248 {
15249 /* Scalar copy sign double-precision */
15250 IRTemp vecA_signed = newTemp(Ity_I64);
15251 IRTemp vecB_unsigned = newTemp(Ity_I64);
15252 IRTemp vec_result = newTemp(Ity_V128);
15253 DIP("xscpsgndp v%d,v%d v%d\n", XT, XA, XB);
15254 assign( vecA_signed, binop( Iop_And64,
15255 unop( Iop_V128HIto64,
15256 mkexpr(vA)),
15257 mkU64(~VG_PPC_SIGN_MASK) ) );
15258 assign( vecB_unsigned, binop( Iop_And64,
15259 unop( Iop_V128HIto64,
15260 mkexpr(vB) ),
15261 mkU64(VG_PPC_SIGN_MASK) ) );
15262 assign( vec_result, binop( Iop_64HLtoV128,
15263 binop( Iop_Or64,
15264 mkexpr(vecA_signed),
15265 mkexpr(vecB_unsigned) ),
15266 mkU64(0x0ULL)));
15267 putVSReg(XT, mkexpr(vec_result));
15268 break;
15269 }
15270 case 0x2D2: // xsnabsdp
15271 {
15272 /* Scalar negative absolute value double-precision */
15273 IRTemp BHi_signed = newTemp(Ity_I64);
15274 DIP("xsnabsdp v%d,v%d\n", XT, XB);
15275 assign( BHi_signed, binop( Iop_Or64,
15276 unop( Iop_V128HIto64,
15277 mkexpr(vB) ),
15278 mkU64(~VG_PPC_SIGN_MASK) ) );
15279 putVSReg(XT, binop( Iop_64HLtoV128,
15280 mkexpr(BHi_signed), mkU64(0x0ULL) ) );
15281 break;
15282 }
15283 case 0x2F2: // xsnegdp
15284 {
15285 /* Scalar negate double-precision */
15286 IRTemp BHi_signed = newTemp(Ity_I64);
15287 IRTemp BHi_unsigned = newTemp(Ity_I64);
15288 IRTemp BHi_negated = newTemp(Ity_I64);
15289 IRTemp BHi_negated_signbit = newTemp(Ity_I1);
15290 IRTemp vec_result = newTemp(Ity_V128);
15291 DIP("xsnabsdp v%d,v%d\n", XT, XB);
15292 assign( BHi_signed, unop( Iop_V128HIto64, mkexpr(vB) ) );
15293 assign( BHi_unsigned, binop( Iop_And64, mkexpr(BHi_signed),
15294 mkU64(VG_PPC_SIGN_MASK) ) );
15295 assign( BHi_negated_signbit,
15296 unop( Iop_Not1,
15297 unop( Iop_32to1,
15298 binop( Iop_Shr32,
15299 unop( Iop_64HIto32,
15300 binop( Iop_And64,
15301 mkexpr(BHi_signed),
15302 mkU64(~VG_PPC_SIGN_MASK) )
15303 ),
15304 mkU8(31) ) ) ) );
15305 assign( BHi_negated,
15306 binop( Iop_Or64,
15307 binop( Iop_32HLto64,
15308 binop( Iop_Shl32,
15309 unop( Iop_1Uto32,
15310 mkexpr(BHi_negated_signbit) ),
15311 mkU8(31) ),
15312 mkU32(0) ),
15313 mkexpr(BHi_unsigned) ) );
15314 assign( vec_result, binop( Iop_64HLtoV128, mkexpr(BHi_negated),
15315 mkU64(0x0ULL)));
15316 putVSReg( XT, mkexpr(vec_result));
15317 break;
15318 }
15319 case 0x280: // xsmaxdp (VSX Scalar Maximum Double-Precision)
15320 case 0x2A0: // xsmindp (VSX Scalar Minimum Double-Precision)
15321 {
15322 IRTemp frA = newTemp(Ity_I64);
15323 IRTemp frB = newTemp(Ity_I64);
15324 Bool isMin = opc2 == 0x2A0 ? True : False;
15325 DIP("%s v%d,v%d v%d\n", isMin ? "xsmaxdp" : "xsmindp", XT, XA, XB);
15326
15327 assign(frA, unop(Iop_V128HIto64, mkexpr( vA )));
15328 assign(frB, unop(Iop_V128HIto64, mkexpr( vB )));
15329 putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), mkU64( 0 ) ) );
15330
15331 break;
15332 }
15333 case 0x0F2: // xsrdpim (VSX Scalar Round to Double-Precision Integer using round toward -Infinity)
15334 case 0x0D2: // xsrdpip (VSX Scalar Round to Double-Precision Integer using round toward +Infinity)
15335 case 0x0D6: // xsrdpic (VSX Scalar Round to Double-Precision Integer using Current rounding mode)
15336 case 0x0B2: // xsrdpiz (VSX Scalar Round to Double-Precision Integer using round toward Zero)
15337 case 0x092: // xsrdpi (VSX Scalar Round to Double-Precision Integer using round toward Nearest Away)
15338 {
15339 IRTemp frB_I64 = newTemp(Ity_I64);
15340 IRExpr * frD_fp_round = NULL;
15341
15342 assign(frB_I64, unop(Iop_V128HIto64, mkexpr( vB )));
15343 frD_fp_round = _do_vsx_fp_roundToInt(frB_I64, opc2);
15344
15345 DIP("xsrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), XT, XB);
15346 putVSReg( XT,
15347 binop( Iop_64HLtoV128,
15348 unop( Iop_ReinterpF64asI64, frD_fp_round),
15349 mkU64( 0 ) ) );
15350 break;
15351 }
15352 case 0x034: // xsresp (VSX Scalar Reciprocal Estimate single-Precision)
15353 case 0x014: /* xsrsqrtesp (VSX Scalar Reciprocal Square Root Estimate
15354 * single-Precision)
15355 */
15356 {
15357 IRTemp frB = newTemp(Ity_F64);
15358 IRTemp sqrt = newTemp(Ity_F64);
15359 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
15360 IRExpr* rm = get_IR_roundingmode();
15361 Bool redp = opc2 == 0x034;
15362 DIP("%s v%d,v%d\n", redp ? "xsresp" : "xsrsqrtesp", XT,
15363 XB);
15364
15365 assign( frB,
15366 unop( Iop_ReinterpI64asF64,
15367 unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
15368
15369 if (!redp)
15370 assign( sqrt,
15371 binop( Iop_SqrtF64,
15372 rm,
15373 mkexpr(frB) ) );
15374 putVSReg( XT,
15375 binop( Iop_64HLtoV128,
15376 unop( Iop_ReinterpF64asI64,
15377 binop( Iop_RoundF64toF32, rm,
15378 triop( Iop_DivF64,
15379 rm,
15380 ieee_one,
15381 redp ? mkexpr( frB ) :
15382 mkexpr( sqrt ) ) ) ),
15383 mkU64( 0 ) ) );
15384 break;
15385 }
15386
15387 case 0x0B4: // xsredp (VSX Scalar Reciprocal Estimate Double-Precision)
15388 case 0x094: // xsrsqrtedp (VSX Scalar Reciprocal Square Root Estimate Double-Precision)
15389
15390 {
15391 IRTemp frB = newTemp(Ity_F64);
15392 IRTemp sqrt = newTemp(Ity_F64);
15393 IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
15394 IRExpr* rm = get_IR_roundingmode();
15395 Bool redp = opc2 == 0x0B4;
15396 DIP("%s v%d,v%d\n", redp ? "xsredp" : "xsrsqrtedp", XT, XB);
15397 assign( frB,
15398 unop( Iop_ReinterpI64asF64,
15399 unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
15400
15401 if (!redp)
15402 assign( sqrt,
15403 binop( Iop_SqrtF64,
15404 rm,
15405 mkexpr(frB) ) );
15406 putVSReg( XT,
15407 binop( Iop_64HLtoV128,
15408 unop( Iop_ReinterpF64asI64,
15409 triop( Iop_DivF64,
15410 rm,
15411 ieee_one,
15412 redp ? mkexpr( frB ) : mkexpr( sqrt ) ) ),
15413 mkU64( 0 ) ) );
15414 break;
15415 }
15416
15417 case 0x232: // xsrsp (VSX Scalar Round to Single-Precision)
15418 {
15419 IRTemp frB = newTemp(Ity_F64);
15420 IRExpr* rm = get_IR_roundingmode();
15421 DIP("xsrsp v%d, v%d\n", XT, XB);
15422 assign( frB,
15423 unop( Iop_ReinterpI64asF64,
15424 unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
15425
15426 putVSReg( XT, binop( Iop_64HLtoV128,
15427 unop( Iop_ReinterpF64asI64,
15428 binop( Iop_RoundF64toF32,
15429 rm,
15430 mkexpr( frB ) ) ),
15431 mkU64( 0 ) ) );
15432 break;
15433 }
15434
15435 default:
15436 vex_printf( "dis_vxs_misc(ppc)(opc2)\n" );
15437 return False;
15438 }
15439 return True;
15440 }
15441
15442 /*
15443 * VSX Logical Instructions
15444 */
15445 static Bool
dis_vx_logic(UInt theInstr,UInt opc2)15446 dis_vx_logic ( UInt theInstr, UInt opc2 )
15447 {
15448 /* XX3-Form */
15449 UChar opc1 = ifieldOPC( theInstr );
15450 UChar XT = ifieldRegXT ( theInstr );
15451 UChar XA = ifieldRegXA ( theInstr );
15452 UChar XB = ifieldRegXB ( theInstr );
15453 IRTemp vA = newTemp( Ity_V128 );
15454 IRTemp vB = newTemp( Ity_V128 );
15455
15456 if (opc1 != 0x3C) {
15457 vex_printf( "dis_vx_logic(ppc)(instr)\n" );
15458 return False;
15459 }
15460
15461 assign( vA, getVSReg( XA ) );
15462 assign( vB, getVSReg( XB ) );
15463
15464 switch (opc2) {
15465 case 0x268: // xxlxor
15466 DIP("xxlxor v%d,v%d,v%d\n", XT, XA, XB);
15467 putVSReg( XT, binop( Iop_XorV128, mkexpr( vA ), mkexpr( vB ) ) );
15468 break;
15469 case 0x248: // xxlor
15470 DIP("xxlor v%d,v%d,v%d\n", XT, XA, XB);
15471 putVSReg( XT, binop( Iop_OrV128, mkexpr( vA ), mkexpr( vB ) ) );
15472 break;
15473 case 0x288: // xxlnor
15474 DIP("xxlnor v%d,v%d,v%d\n", XT, XA, XB);
15475 putVSReg( XT, unop( Iop_NotV128, binop( Iop_OrV128, mkexpr( vA ),
15476 mkexpr( vB ) ) ) );
15477 break;
15478 case 0x208: // xxland
15479 DIP("xxland v%d,v%d,v%d\n", XT, XA, XB);
15480 putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), mkexpr( vB ) ) );
15481 break;
15482 case 0x228: //xxlandc
15483 DIP("xxlandc v%d,v%d,v%d\n", XT, XA, XB);
15484 putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), unop( Iop_NotV128,
15485 mkexpr( vB ) ) ) );
15486 break;
15487 case 0x2A8: // xxlorc (VSX Logical OR with complement)
15488 DIP("xxlorc v%d,v%d,v%d\n", XT, XA, XB);
15489 putVSReg( XT, binop( Iop_OrV128,
15490 mkexpr( vA ),
15491 unop( Iop_NotV128, mkexpr( vB ) ) ) );
15492 break;
15493 case 0x2C8: // xxlnand (VSX Logical NAND)
15494 DIP("xxlnand v%d,v%d,v%d\n", XT, XA, XB);
15495 putVSReg( XT, unop( Iop_NotV128,
15496 binop( Iop_AndV128, mkexpr( vA ),
15497 mkexpr( vB ) ) ) );
15498 break;
15499 case 0x2E8: // xxleqv (VSX Logical Equivalence)
15500 DIP("xxleqv v%d,v%d,v%d\n", XT, XA, XB);
15501 putVSReg( XT, unop( Iop_NotV128,
15502 binop( Iop_XorV128,
15503 mkexpr( vA ), mkexpr( vB ) ) ) );
15504 break;
15505 default:
15506 vex_printf( "dis_vx_logic(ppc)(opc2)\n" );
15507 return False;
15508 }
15509 return True;
15510 }
15511
15512 /*
15513 * VSX Load Instructions
15514 * NOTE: VSX supports word-aligned storage access.
15515 */
15516 static Bool
dis_vx_load(UInt theInstr)15517 dis_vx_load ( UInt theInstr )
15518 {
15519 /* XX1-Form */
15520 UChar opc1 = ifieldOPC( theInstr );
15521 UChar XT = ifieldRegXT ( theInstr );
15522 UChar rA_addr = ifieldRegA( theInstr );
15523 UChar rB_addr = ifieldRegB( theInstr );
15524 UInt opc2 = ifieldOPClo10( theInstr );
15525
15526 IRType ty = mode64 ? Ity_I64 : Ity_I32;
15527 IRTemp EA = newTemp( ty );
15528
15529 if (opc1 != 0x1F) {
15530 vex_printf( "dis_vx_load(ppc)(instr)\n" );
15531 return False;
15532 }
15533
15534 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
15535
15536 switch (opc2) {
15537 case 0x00C: // lxsiwzx (Load VSX Scalar as Integer Word and Zero Indexed)
15538 {
15539 IRExpr * exp;
15540 DIP("lxsiwzx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
15541
15542 if (host_endness == VexEndnessLE)
15543 exp = unop( Iop_64to32, load( Ity_I64, mkexpr( EA ) ) );
15544 else
15545 exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) );
15546
15547 putVSReg( XT, binop( Iop_64HLtoV128,
15548 unop( Iop_32Uto64, exp),
15549 mkU64(0) ) );
15550 break;
15551 }
15552 case 0x04C: // lxsiwax (Load VSX Scalar as Integer Word Algebraic Indexed)
15553 {
15554 IRExpr * exp;
15555 DIP("lxsiwax %d,r%u,r%u\n", XT, rA_addr, rB_addr);
15556
15557 if (host_endness == VexEndnessLE)
15558 exp = unop( Iop_64to32, load( Ity_I64, mkexpr( EA ) ) );
15559 else
15560 exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) );
15561
15562 putVSReg( XT, binop( Iop_64HLtoV128,
15563 unop( Iop_32Sto64, exp),
15564 mkU64(0) ) );
15565 break;
15566 }
15567 case 0x20C: // lxsspx (Load VSX Scalar Single-Precision Indexed)
15568 {
15569 IRExpr * exp;
15570 DIP("lxsspx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
15571 /* Take 32-bit floating point value in the upper half of the fetched
15572 * 64-bit value, convert to 64-bit floating point value and load into
15573 * top word of V128.
15574 */
15575 exp = unop( Iop_ReinterpF64asI64,
15576 unop( Iop_F32toF64,
15577 unop( Iop_ReinterpI32asF32,
15578 load( Ity_I32, mkexpr( EA ) ) ) ) );
15579
15580 putVSReg( XT, binop( Iop_64HLtoV128, exp, mkU64( 0 ) ) );
15581 break;
15582 }
15583 case 0x24C: // lxsdx
15584 {
15585 IRExpr * exp;
15586 DIP("lxsdx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
15587 exp = load( Ity_I64, mkexpr( EA ) );
15588 // We need to pass an expression of type Ity_V128 with putVSReg, but the load
15589 // we just performed is only a DW. But since the contents of VSR[XT] element 1
15590 // are undefined after this operation, we can just do a splat op.
15591 putVSReg( XT, binop( Iop_64HLtoV128, exp, exp ) );
15592 break;
15593 }
15594 case 0x34C: // lxvd2x
15595 {
15596 IROp addOp = ty == Ity_I64 ? Iop_Add64 : Iop_Add32;
15597 IRExpr * high, *low;
15598 ULong ea_off = 8;
15599 IRExpr* high_addr;
15600 DIP("lxvd2x %d,r%u,r%u\n", XT, rA_addr, rB_addr);
15601 high = load( Ity_I64, mkexpr( EA ) );
15602 high_addr = binop( addOp, mkexpr( EA ), ty == Ity_I64 ? mkU64( ea_off )
15603 : mkU32( ea_off ) );
15604 low = load( Ity_I64, high_addr );
15605 putVSReg( XT, binop( Iop_64HLtoV128, high, low ) );
15606 break;
15607 }
15608 case 0x14C: // lxvdsx
15609 {
15610 IRTemp data = newTemp(Ity_I64);
15611 DIP("lxvdsx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
15612 assign( data, load( Ity_I64, mkexpr( EA ) ) );
15613 putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( data ), mkexpr( data ) ) );
15614 break;
15615 }
15616 case 0x30C:
15617 {
15618 IRExpr *t0;
15619
15620 DIP("lxvw4x %d,r%u,r%u\n", XT, rA_addr, rB_addr);
15621
15622 /* The load will result in the data being in BE order. */
15623 if (host_endness == VexEndnessLE) {
15624 IRExpr *t0_BE;
15625 IRTemp perm_LE = newTemp(Ity_V128);
15626
15627 t0_BE = load( Ity_V128, mkexpr( EA ) );
15628
15629 /* Permute the data to LE format */
15630 assign( perm_LE, binop( Iop_64HLtoV128, mkU64(0x0c0d0e0f08090a0bULL),
15631 mkU64(0x0405060700010203ULL)));
15632
15633 t0 = binop( Iop_Perm8x16, t0_BE, mkexpr(perm_LE) );
15634 } else {
15635 t0 = load( Ity_V128, mkexpr( EA ) );
15636 }
15637
15638 putVSReg( XT, t0 );
15639 break;
15640 }
15641 default:
15642 vex_printf( "dis_vx_load(ppc)(opc2)\n" );
15643 return False;
15644 }
15645 return True;
15646 }
15647
15648 /*
15649 * VSX Store Instructions
15650 * NOTE: VSX supports word-aligned storage access.
15651 */
15652 static Bool
dis_vx_store(UInt theInstr)15653 dis_vx_store ( UInt theInstr )
15654 {
15655 /* XX1-Form */
15656 UChar opc1 = ifieldOPC( theInstr );
15657 UChar XS = ifieldRegXS( theInstr );
15658 UChar rA_addr = ifieldRegA( theInstr );
15659 UChar rB_addr = ifieldRegB( theInstr );
15660 IRTemp vS = newTemp( Ity_V128 );
15661 UInt opc2 = ifieldOPClo10( theInstr );
15662
15663 IRType ty = mode64 ? Ity_I64 : Ity_I32;
15664 IRTemp EA = newTemp( ty );
15665
15666 if (opc1 != 0x1F) {
15667 vex_printf( "dis_vx_store(ppc)(instr)\n" );
15668 return False;
15669 }
15670
15671 assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
15672 assign( vS, getVSReg( XS ) );
15673
15674 switch (opc2) {
15675 case 0x08C:
15676 {
15677 /* Need the next to the most significant 32-bit word from
15678 * the 128-bit vector.
15679 */
15680 IRExpr * high64, * low32;
15681 DIP("stxsiwx %d,r%u,r%u\n", XS, rA_addr, rB_addr);
15682 high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
15683 low32 = unop( Iop_64to32, high64 );
15684 store( mkexpr( EA ), low32 );
15685 break;
15686 }
15687 case 0x28C:
15688 {
15689 IRTemp high64 = newTemp(Ity_F64);
15690 IRTemp val32 = newTemp(Ity_I32);
15691 DIP("stxsspx %d,r%u,r%u\n", XS, rA_addr, rB_addr);
15692 assign(high64, unop( Iop_ReinterpI64asF64,
15693 unop( Iop_V128HIto64, mkexpr( vS ) ) ) );
15694 assign(val32, unop( Iop_ReinterpF32asI32,
15695 unop( Iop_TruncF64asF32,
15696 mkexpr(high64) ) ) );
15697 store( mkexpr( EA ), mkexpr( val32 ) );
15698 break;
15699 }
15700 case 0x2CC:
15701 {
15702 IRExpr * high64;
15703 DIP("stxsdx %d,r%u,r%u\n", XS, rA_addr, rB_addr);
15704 high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
15705 store( mkexpr( EA ), high64 );
15706 break;
15707 }
15708 case 0x3CC:
15709 {
15710 IRExpr * high64, *low64;
15711 DIP("stxvd2x %d,r%u,r%u\n", XS, rA_addr, rB_addr);
15712 high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
15713 low64 = unop( Iop_V128to64, mkexpr( vS ) );
15714 store( mkexpr( EA ), high64 );
15715 store( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
15716 ty == Ity_I64 ? mkU64( 8 ) : mkU32( 8 ) ), low64 );
15717 break;
15718 }
15719 case 0x38C:
15720 {
15721 UInt ea_off = 0;
15722 IRExpr* irx_addr;
15723 IRTemp hi64 = newTemp( Ity_I64 );
15724 IRTemp lo64 = newTemp( Ity_I64 );
15725
15726 DIP("stxvw4x %d,r%u,r%u\n", XS, rA_addr, rB_addr);
15727
15728 // This instruction supports word-aligned stores, so EA may not be
15729 // quad-word aligned. Therefore, do 4 individual word-size stores.
15730 assign( hi64, unop( Iop_V128HIto64, mkexpr( vS ) ) );
15731 assign( lo64, unop( Iop_V128to64, mkexpr( vS ) ) );
15732 store( mkexpr( EA ), unop( Iop_64HIto32, mkexpr( hi64 ) ) );
15733 ea_off += 4;
15734 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
15735 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
15736 store( irx_addr, unop( Iop_64to32, mkexpr( hi64 ) ) );
15737 ea_off += 4;
15738 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
15739 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
15740 store( irx_addr, unop( Iop_64HIto32, mkexpr( lo64 ) ) );
15741 ea_off += 4;
15742 irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
15743 ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
15744 store( irx_addr, unop( Iop_64to32, mkexpr( lo64 ) ) );
15745
15746 break;
15747 }
15748 default:
15749 vex_printf( "dis_vx_store(ppc)(opc2)\n" );
15750 return False;
15751 }
15752 return True;
15753 }
15754
15755 /*
15756 * VSX permute and other miscealleous instructions
15757 */
15758 static Bool
dis_vx_permute_misc(UInt theInstr,UInt opc2)15759 dis_vx_permute_misc( UInt theInstr, UInt opc2 )
15760 {
15761 /* XX3-Form */
15762 UChar opc1 = ifieldOPC( theInstr );
15763 UChar XT = ifieldRegXT ( theInstr );
15764 UChar XA = ifieldRegXA ( theInstr );
15765 UChar XB = ifieldRegXB ( theInstr );
15766 IRTemp vT = newTemp( Ity_V128 );
15767 IRTemp vA = newTemp( Ity_V128 );
15768 IRTemp vB = newTemp( Ity_V128 );
15769
15770 if (opc1 != 0x3C) {
15771 vex_printf( "dis_vx_permute_misc(ppc)(instr)\n" );
15772 return False;
15773 }
15774
15775 assign( vA, getVSReg( XA ) );
15776 assign( vB, getVSReg( XB ) );
15777
15778 switch (opc2) {
15779 case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate)
15780 {
15781 UChar SHW = ifieldSHW ( theInstr );
15782 IRTemp result = newTemp(Ity_V128);
15783 if ( SHW != 0 ) {
15784 IRTemp hi = newTemp(Ity_V128);
15785 IRTemp lo = newTemp(Ity_V128);
15786 assign( hi, binop(Iop_ShlV128, mkexpr(vA), mkU8(SHW*32)) );
15787 assign( lo, binop(Iop_ShrV128, mkexpr(vB), mkU8(128-SHW*32)) );
15788 assign ( result, binop(Iop_OrV128, mkexpr(hi), mkexpr(lo)) );
15789 } else
15790 assign ( result, mkexpr(vA) );
15791 DIP("xxsldwi v%d,v%d,v%d,%d\n", XT, XA, XB, SHW);
15792 putVSReg( XT, mkexpr(result) );
15793 break;
15794 }
15795 case 0x28: // xpermdi (VSX Permute Doubleword Immediate)
15796 {
15797 UChar DM = ifieldDM ( theInstr );
15798 IRTemp hi = newTemp(Ity_I64);
15799 IRTemp lo = newTemp(Ity_I64);
15800
15801 if (DM & 0x2)
15802 assign( hi, unop(Iop_V128to64, mkexpr(vA)) );
15803 else
15804 assign( hi, unop(Iop_V128HIto64, mkexpr(vA)) );
15805
15806 if (DM & 0x1)
15807 assign( lo, unop(Iop_V128to64, mkexpr(vB)) );
15808 else
15809 assign( lo, unop(Iop_V128HIto64, mkexpr(vB)) );
15810
15811 assign( vT, binop(Iop_64HLtoV128, mkexpr(hi), mkexpr(lo)) );
15812
15813 DIP("xxpermdi v%d,v%d,v%d,0x%x\n", XT, XA, XB, DM);
15814 putVSReg( XT, mkexpr( vT ) );
15815 break;
15816 }
15817 case 0x48: // xxmrghw (VSX Merge High Word)
15818 case 0xc8: // xxmrglw (VSX Merge Low Word)
15819 {
15820 const HChar type = (opc2 == 0x48) ? 'h' : 'l';
15821 IROp word_op = (opc2 == 0x48) ? Iop_V128HIto64 : Iop_V128to64;
15822 IRTemp a64 = newTemp(Ity_I64);
15823 IRTemp ahi32 = newTemp(Ity_I32);
15824 IRTemp alo32 = newTemp(Ity_I32);
15825 IRTemp b64 = newTemp(Ity_I64);
15826 IRTemp bhi32 = newTemp(Ity_I32);
15827 IRTemp blo32 = newTemp(Ity_I32);
15828
15829 assign( a64, unop(word_op, mkexpr(vA)) );
15830 assign( ahi32, unop(Iop_64HIto32, mkexpr(a64)) );
15831 assign( alo32, unop(Iop_64to32, mkexpr(a64)) );
15832
15833 assign( b64, unop(word_op, mkexpr(vB)) );
15834 assign( bhi32, unop(Iop_64HIto32, mkexpr(b64)) );
15835 assign( blo32, unop(Iop_64to32, mkexpr(b64)) );
15836
15837 assign( vT, binop(Iop_64HLtoV128,
15838 binop(Iop_32HLto64, mkexpr(ahi32), mkexpr(bhi32)),
15839 binop(Iop_32HLto64, mkexpr(alo32), mkexpr(blo32))) );
15840
15841 DIP("xxmrg%cw v%d,v%d,v%d\n", type, XT, XA, XB);
15842 putVSReg( XT, mkexpr( vT ) );
15843 break;
15844 }
15845 case 0x018: // xxsel (VSX Select)
15846 {
15847 UChar XC = ifieldRegXC(theInstr);
15848 IRTemp vC = newTemp( Ity_V128 );
15849 assign( vC, getVSReg( XC ) );
15850 DIP("xxsel v%d,v%d,v%d,v%d\n", XT, XA, XB, XC);
15851 /* vD = (vA & ~vC) | (vB & vC) */
15852 putVSReg( XT, binop(Iop_OrV128,
15853 binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
15854 binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
15855 break;
15856 }
15857 case 0x148: // xxspltw (VSX Splat Word)
15858 {
15859 UChar UIM = ifieldRegA(theInstr) & 3;
15860 UChar sh_uim = (3 - (UIM)) * 32;
15861 DIP("xxspltw v%d,v%d,%d\n", XT, XB, UIM);
15862 putVSReg( XT,
15863 unop( Iop_Dup32x4,
15864 unop( Iop_V128to32,
15865 binop( Iop_ShrV128, mkexpr( vB ), mkU8( sh_uim ) ) ) ) );
15866 break;
15867 }
15868
15869 default:
15870 vex_printf( "dis_vx_permute_misc(ppc)(opc2)\n" );
15871 return False;
15872 }
15873 return True;
15874 }
15875
15876 /*
15877 AltiVec Load Instructions
15878 */
dis_av_load(const VexAbiInfo * vbi,UInt theInstr)15879 static Bool dis_av_load ( const VexAbiInfo* vbi, UInt theInstr )
15880 {
15881 /* X-Form */
15882 UChar opc1 = ifieldOPC(theInstr);
15883 UChar vD_addr = ifieldRegDS(theInstr);
15884 UChar rA_addr = ifieldRegA(theInstr);
15885 UChar rB_addr = ifieldRegB(theInstr);
15886 UInt opc2 = ifieldOPClo10(theInstr);
15887 UChar b0 = ifieldBIT0(theInstr);
15888
15889 IRType ty = mode64 ? Ity_I64 : Ity_I32;
15890 IRTemp EA = newTemp(ty);
15891 IRTemp EA_align16 = newTemp(ty);
15892
15893 if (opc1 != 0x1F || b0 != 0) {
15894 vex_printf("dis_av_load(ppc)(instr)\n");
15895 return False;
15896 }
15897
15898 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
15899 assign( EA_align16, addr_align( mkexpr(EA), 16 ) );
15900
15901 switch (opc2) {
15902
15903 case 0x006: { // lvsl (Load Vector for Shift Left, AV p123)
15904 IRDirty* d;
15905 UInt vD_off = vectorGuestRegOffset(vD_addr);
15906 IRExpr** args_be = mkIRExprVec_5(
15907 IRExpr_BBPTR(),
15908 mkU32(vD_off),
15909 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
15910 mkU32(0xF)),
15911 mkU32(0)/*left*/,
15912 mkU32(1)/*Big Endian*/);
15913 IRExpr** args_le = mkIRExprVec_5(
15914 IRExpr_BBPTR(),
15915 mkU32(vD_off),
15916 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
15917 mkU32(0xF)),
15918 mkU32(0)/*left*/,
15919 mkU32(0)/*Little Endian*/);
15920 if (!mode64) {
15921 d = unsafeIRDirty_0_N (
15922 0/*regparms*/,
15923 "ppc32g_dirtyhelper_LVS",
15924 fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
15925 args_be );
15926 } else {
15927 if (host_endness == VexEndnessBE)
15928 d = unsafeIRDirty_0_N (
15929 0/*regparms*/,
15930 "ppc64g_dirtyhelper_LVS",
15931 fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
15932 args_be );
15933 else
15934 d = unsafeIRDirty_0_N (
15935 0/*regparms*/,
15936 "ppc64g_dirtyhelper_LVS",
15937 &ppc64g_dirtyhelper_LVS,
15938 args_le );
15939 }
15940 DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
15941 /* declare guest state effects */
15942 d->nFxState = 1;
15943 vex_bzero(&d->fxState, sizeof(d->fxState));
15944 d->fxState[0].fx = Ifx_Write;
15945 d->fxState[0].offset = vD_off;
15946 d->fxState[0].size = sizeof(U128);
15947
15948 /* execute the dirty call, side-effecting guest state */
15949 stmt( IRStmt_Dirty(d) );
15950 break;
15951 }
15952 case 0x026: { // lvsr (Load Vector for Shift Right, AV p125)
15953 IRDirty* d;
15954 UInt vD_off = vectorGuestRegOffset(vD_addr);
15955 IRExpr** args_be = mkIRExprVec_5(
15956 IRExpr_BBPTR(),
15957 mkU32(vD_off),
15958 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
15959 mkU32(0xF)),
15960 mkU32(1)/*right*/,
15961 mkU32(1)/*Big Endian*/);
15962 IRExpr** args_le = mkIRExprVec_5(
15963 IRExpr_BBPTR(),
15964 mkU32(vD_off),
15965 binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
15966 mkU32(0xF)),
15967 mkU32(1)/*right*/,
15968 mkU32(0)/*Little Endian*/);
15969
15970 if (!mode64) {
15971 d = unsafeIRDirty_0_N (
15972 0/*regparms*/,
15973 "ppc32g_dirtyhelper_LVS",
15974 fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
15975 args_be );
15976 } else {
15977 if (host_endness == VexEndnessBE)
15978 d = unsafeIRDirty_0_N (
15979 0/*regparms*/,
15980 "ppc64g_dirtyhelper_LVS",
15981 fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
15982 args_be );
15983 else
15984 d = unsafeIRDirty_0_N (
15985 0/*regparms*/,
15986 "ppc64g_dirtyhelper_LVS",
15987 &ppc64g_dirtyhelper_LVS,
15988 args_le );
15989 }
15990 DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
15991 /* declare guest state effects */
15992 d->nFxState = 1;
15993 vex_bzero(&d->fxState, sizeof(d->fxState));
15994 d->fxState[0].fx = Ifx_Write;
15995 d->fxState[0].offset = vD_off;
15996 d->fxState[0].size = sizeof(U128);
15997
15998 /* execute the dirty call, side-effecting guest state */
15999 stmt( IRStmt_Dirty(d) );
16000 break;
16001 }
16002 case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119)
16003 DIP("lvebx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
16004 /* loads addressed byte into vector[EA[0:3]
16005 since all other destination bytes are undefined,
16006 can simply load entire vector from 16-aligned EA */
16007 putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
16008 break;
16009
16010 case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121)
16011 DIP("lvehx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
16012 /* see note for lvebx */
16013 putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
16014 break;
16015
16016 case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122)
16017 DIP("lvewx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
16018 /* see note for lvebx */
16019 putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
16020 break;
16021
16022 case 0x067: // lvx (Load Vector Indexed, AV p127)
16023 DIP("lvx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
16024 putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
16025 break;
16026
16027 case 0x167: // lvxl (Load Vector Indexed LRU, AV p128)
16028 DIP("lvxl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
16029 putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
16030 break;
16031
16032 default:
16033 vex_printf("dis_av_load(ppc)(opc2)\n");
16034 return False;
16035 }
16036 return True;
16037 }
16038
16039 /*
16040 AltiVec Store Instructions
16041 */
dis_av_store(UInt theInstr)16042 static Bool dis_av_store ( UInt theInstr )
16043 {
16044 /* X-Form */
16045 UChar opc1 = ifieldOPC(theInstr);
16046 UChar vS_addr = ifieldRegDS(theInstr);
16047 UChar rA_addr = ifieldRegA(theInstr);
16048 UChar rB_addr = ifieldRegB(theInstr);
16049 UInt opc2 = ifieldOPClo10(theInstr);
16050 UChar b0 = ifieldBIT0(theInstr);
16051
16052 IRType ty = mode64 ? Ity_I64 : Ity_I32;
16053 IRTemp EA = newTemp(ty);
16054 IRTemp addr_aligned = newTemp(ty);
16055 IRTemp vS = newTemp(Ity_V128);
16056 IRTemp eb = newTemp(Ity_I8);
16057 IRTemp idx = newTemp(Ity_I8);
16058
16059 if (opc1 != 0x1F || b0 != 0) {
16060 vex_printf("dis_av_store(ppc)(instr)\n");
16061 return False;
16062 }
16063
16064 assign( vS, getVReg(vS_addr));
16065 assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
16066
16067 switch (opc2) {
16068 case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131)
16069 DIP("stvebx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
16070 assign( eb, binop(Iop_And8, mkU8(0xF),
16071 unop(Iop_32to8,
16072 mkNarrowTo32(ty, mkexpr(EA)) )) );
16073 if (host_endness == VexEndnessLE) {
16074 assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
16075 } else {
16076 assign( idx, binop(Iop_Shl8,
16077 binop(Iop_Sub8, mkU8(15), mkexpr(eb)),
16078 mkU8(3)) );
16079 }
16080 store( mkexpr(EA),
16081 unop( Iop_32to8, unop(Iop_V128to32,
16082 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
16083 break;
16084 }
16085 case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132)
16086 DIP("stvehx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
16087 assign( addr_aligned, addr_align(mkexpr(EA), 2) );
16088 assign( eb, binop(Iop_And8, mkU8(0xF),
16089 mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
16090 if (host_endness == VexEndnessLE) {
16091 assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
16092 } else {
16093 assign( idx, binop(Iop_Shl8,
16094 binop(Iop_Sub8, mkU8(14), mkexpr(eb)),
16095 mkU8(3)) );
16096 }
16097 store( mkexpr(addr_aligned),
16098 unop( Iop_32to16, unop(Iop_V128to32,
16099 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
16100 break;
16101 }
16102 case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133)
16103 DIP("stvewx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
16104 assign( addr_aligned, addr_align(mkexpr(EA), 4) );
16105 assign( eb, binop(Iop_And8, mkU8(0xF),
16106 mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
16107 if (host_endness == VexEndnessLE) {
16108 assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
16109 } else {
16110 assign( idx, binop(Iop_Shl8,
16111 binop(Iop_Sub8, mkU8(12), mkexpr(eb)),
16112 mkU8(3)) );
16113 }
16114 store( mkexpr( addr_aligned),
16115 unop( Iop_V128to32,
16116 binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) );
16117 break;
16118 }
16119
16120 case 0x0E7: // stvx (Store Vector Indexed, AV p134)
16121 DIP("stvx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
16122 store( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
16123 break;
16124
16125 case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135)
16126 DIP("stvxl v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
16127 store( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
16128 break;
16129
16130 default:
16131 vex_printf("dis_av_store(ppc)(opc2)\n");
16132 return False;
16133 }
16134 return True;
16135 }
16136
16137 /*
16138 AltiVec Arithmetic Instructions
16139 */
dis_av_arith(UInt theInstr)16140 static Bool dis_av_arith ( UInt theInstr )
16141 {
16142 /* VX-Form */
16143 UChar opc1 = ifieldOPC(theInstr);
16144 UChar vD_addr = ifieldRegDS(theInstr);
16145 UChar vA_addr = ifieldRegA(theInstr);
16146 UChar vB_addr = ifieldRegB(theInstr);
16147 UInt opc2 = IFIELD( theInstr, 0, 11 );
16148
16149 IRTemp vA = newTemp(Ity_V128);
16150 IRTemp vB = newTemp(Ity_V128);
16151 IRTemp z3 = newTemp(Ity_I64);
16152 IRTemp z2 = newTemp(Ity_I64);
16153 IRTemp z1 = newTemp(Ity_I64);
16154 IRTemp z0 = newTemp(Ity_I64);
16155 IRTemp aEvn, aOdd;
16156 IRTemp a15, a14, a13, a12, a11, a10, a9, a8;
16157 IRTemp a7, a6, a5, a4, a3, a2, a1, a0;
16158 IRTemp b3, b2, b1, b0;
16159
16160 aEvn = aOdd = IRTemp_INVALID;
16161 a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID;
16162 a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID;
16163 b3 = b2 = b1 = b0 = IRTemp_INVALID;
16164
16165 assign( vA, getVReg(vA_addr));
16166 assign( vB, getVReg(vB_addr));
16167
16168 if (opc1 != 0x4) {
16169 vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n");
16170 return False;
16171 }
16172
16173 switch (opc2) {
16174 /* Add */
16175 case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136)
16176 DIP("vaddcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16177 /* unsigned_ov(x+y) = (y >u not(x)) */
16178 putVReg( vD_addr, binop(Iop_ShrN32x4,
16179 binop(Iop_CmpGT32Ux4, mkexpr(vB),
16180 unop(Iop_NotV128, mkexpr(vA))),
16181 mkU8(31)) );
16182 break;
16183 }
16184 case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141)
16185 DIP("vaddubm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16186 putVReg( vD_addr, binop(Iop_Add8x16, mkexpr(vA), mkexpr(vB)) );
16187 break;
16188
16189 case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143)
16190 DIP("vadduhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16191 putVReg( vD_addr, binop(Iop_Add16x8, mkexpr(vA), mkexpr(vB)) );
16192 break;
16193
16194 case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145)
16195 DIP("vadduwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16196 putVReg( vD_addr, binop(Iop_Add32x4, mkexpr(vA), mkexpr(vB)) );
16197 break;
16198
16199 case 0x0C0: // vaddudm (Add Unsigned Double Word Modulo)
16200 DIP("vaddudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16201 putVReg( vD_addr, binop(Iop_Add64x2, mkexpr(vA), mkexpr(vB)) );
16202 break;
16203
16204 case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142)
16205 DIP("vaddubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16206 putVReg( vD_addr, binop(Iop_QAdd8Ux16, mkexpr(vA), mkexpr(vB)) );
16207 // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16
16208 break;
16209
16210 case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144)
16211 DIP("vadduhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16212 putVReg( vD_addr, binop(Iop_QAdd16Ux8, mkexpr(vA), mkexpr(vB)) );
16213 // TODO: set VSCR[SAT]
16214 break;
16215
16216 case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146)
16217 DIP("vadduws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16218 putVReg( vD_addr, binop(Iop_QAdd32Ux4, mkexpr(vA), mkexpr(vB)) );
16219 // TODO: set VSCR[SAT]
16220 break;
16221
16222 case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138)
16223 DIP("vaddsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16224 putVReg( vD_addr, binop(Iop_QAdd8Sx16, mkexpr(vA), mkexpr(vB)) );
16225 // TODO: set VSCR[SAT]
16226 break;
16227
16228 case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139)
16229 DIP("vaddshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16230 putVReg( vD_addr, binop(Iop_QAdd16Sx8, mkexpr(vA), mkexpr(vB)) );
16231 // TODO: set VSCR[SAT]
16232 break;
16233
16234 case 0x380: // vaddsws (Add Signed Word Saturate, AV p140)
16235 DIP("vaddsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16236 putVReg( vD_addr, binop(Iop_QAdd32Sx4, mkexpr(vA), mkexpr(vB)) );
16237 // TODO: set VSCR[SAT]
16238 break;
16239
16240
16241 /* Subtract */
16242 case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260)
16243 DIP("vsubcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16244 /* unsigned_ov(x-y) = (y >u x) */
16245 putVReg( vD_addr, binop(Iop_ShrN32x4,
16246 unop(Iop_NotV128,
16247 binop(Iop_CmpGT32Ux4, mkexpr(vB),
16248 mkexpr(vA))),
16249 mkU8(31)) );
16250 break;
16251 }
16252 case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265)
16253 DIP("vsububm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16254 putVReg( vD_addr, binop(Iop_Sub8x16, mkexpr(vA), mkexpr(vB)) );
16255 break;
16256
16257 case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267)
16258 DIP("vsubuhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16259 putVReg( vD_addr, binop(Iop_Sub16x8, mkexpr(vA), mkexpr(vB)) );
16260 break;
16261
16262 case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269)
16263 DIP("vsubuwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16264 putVReg( vD_addr, binop(Iop_Sub32x4, mkexpr(vA), mkexpr(vB)) );
16265 break;
16266
16267 case 0x4C0: // vsubudm (Subtract Unsigned Double Word Modulo)
16268 DIP("vsubudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16269 putVReg( vD_addr, binop(Iop_Sub64x2, mkexpr(vA), mkexpr(vB)) );
16270 break;
16271
16272 case 0x600: // vsububs (Subtract Unsigned Byte Saturate, AV p266)
16273 DIP("vsububs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16274 putVReg( vD_addr, binop(Iop_QSub8Ux16, mkexpr(vA), mkexpr(vB)) );
16275 // TODO: set VSCR[SAT]
16276 break;
16277
16278 case 0x640: // vsubuhs (Subtract Unsigned HWord Saturate, AV p268)
16279 DIP("vsubuhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16280 putVReg( vD_addr, binop(Iop_QSub16Ux8, mkexpr(vA), mkexpr(vB)) );
16281 // TODO: set VSCR[SAT]
16282 break;
16283
16284 case 0x680: // vsubuws (Subtract Unsigned Word Saturate, AV p270)
16285 DIP("vsubuws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16286 putVReg( vD_addr, binop(Iop_QSub32Ux4, mkexpr(vA), mkexpr(vB)) );
16287 // TODO: set VSCR[SAT]
16288 break;
16289
16290 case 0x700: // vsubsbs (Subtract Signed Byte Saturate, AV p262)
16291 DIP("vsubsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16292 putVReg( vD_addr, binop(Iop_QSub8Sx16, mkexpr(vA), mkexpr(vB)) );
16293 // TODO: set VSCR[SAT]
16294 break;
16295
16296 case 0x740: // vsubshs (Subtract Signed Half Word Saturate, AV p263)
16297 DIP("vsubshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16298 putVReg( vD_addr, binop(Iop_QSub16Sx8, mkexpr(vA), mkexpr(vB)) );
16299 // TODO: set VSCR[SAT]
16300 break;
16301
16302 case 0x780: // vsubsws (Subtract Signed Word Saturate, AV p264)
16303 DIP("vsubsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16304 putVReg( vD_addr, binop(Iop_QSub32Sx4, mkexpr(vA), mkexpr(vB)) );
16305 // TODO: set VSCR[SAT]
16306 break;
16307
16308
16309 /* Maximum */
16310 case 0x002: // vmaxub (Maximum Unsigned Byte, AV p182)
16311 DIP("vmaxub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16312 putVReg( vD_addr, binop(Iop_Max8Ux16, mkexpr(vA), mkexpr(vB)) );
16313 break;
16314
16315 case 0x042: // vmaxuh (Maximum Unsigned Half Word, AV p183)
16316 DIP("vmaxuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16317 putVReg( vD_addr, binop(Iop_Max16Ux8, mkexpr(vA), mkexpr(vB)) );
16318 break;
16319
16320 case 0x082: // vmaxuw (Maximum Unsigned Word, AV p184)
16321 DIP("vmaxuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16322 putVReg( vD_addr, binop(Iop_Max32Ux4, mkexpr(vA), mkexpr(vB)) );
16323 break;
16324
16325 case 0x0C2: // vmaxud (Maximum Unsigned Double word)
16326 DIP("vmaxud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16327 putVReg( vD_addr, binop(Iop_Max64Ux2, mkexpr(vA), mkexpr(vB)) );
16328 break;
16329
16330 case 0x102: // vmaxsb (Maximum Signed Byte, AV p179)
16331 DIP("vmaxsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16332 putVReg( vD_addr, binop(Iop_Max8Sx16, mkexpr(vA), mkexpr(vB)) );
16333 break;
16334
16335 case 0x142: // vmaxsh (Maximum Signed Half Word, AV p180)
16336 DIP("vmaxsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16337 putVReg( vD_addr, binop(Iop_Max16Sx8, mkexpr(vA), mkexpr(vB)) );
16338 break;
16339
16340 case 0x182: // vmaxsw (Maximum Signed Word, AV p181)
16341 DIP("vmaxsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16342 putVReg( vD_addr, binop(Iop_Max32Sx4, mkexpr(vA), mkexpr(vB)) );
16343 break;
16344
16345 case 0x1C2: // vmaxsd (Maximum Signed Double word)
16346 DIP("vmaxsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16347 putVReg( vD_addr, binop(Iop_Max64Sx2, mkexpr(vA), mkexpr(vB)) );
16348 break;
16349
16350 /* Minimum */
16351 case 0x202: // vminub (Minimum Unsigned Byte, AV p191)
16352 DIP("vminub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16353 putVReg( vD_addr, binop(Iop_Min8Ux16, mkexpr(vA), mkexpr(vB)) );
16354 break;
16355
16356 case 0x242: // vminuh (Minimum Unsigned Half Word, AV p192)
16357 DIP("vminuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16358 putVReg( vD_addr, binop(Iop_Min16Ux8, mkexpr(vA), mkexpr(vB)) );
16359 break;
16360
16361 case 0x282: // vminuw (Minimum Unsigned Word, AV p193)
16362 DIP("vminuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16363 putVReg( vD_addr, binop(Iop_Min32Ux4, mkexpr(vA), mkexpr(vB)) );
16364 break;
16365
16366 case 0x2C2: // vminud (Minimum Unsigned Double Word)
16367 DIP("vminud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16368 putVReg( vD_addr, binop(Iop_Min64Ux2, mkexpr(vA), mkexpr(vB)) );
16369 break;
16370
16371 case 0x302: // vminsb (Minimum Signed Byte, AV p188)
16372 DIP("vminsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16373 putVReg( vD_addr, binop(Iop_Min8Sx16, mkexpr(vA), mkexpr(vB)) );
16374 break;
16375
16376 case 0x342: // vminsh (Minimum Signed Half Word, AV p189)
16377 DIP("vminsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16378 putVReg( vD_addr, binop(Iop_Min16Sx8, mkexpr(vA), mkexpr(vB)) );
16379 break;
16380
16381 case 0x382: // vminsw (Minimum Signed Word, AV p190)
16382 DIP("vminsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16383 putVReg( vD_addr, binop(Iop_Min32Sx4, mkexpr(vA), mkexpr(vB)) );
16384 break;
16385
16386 case 0x3C2: // vminsd (Minimum Signed Double Word)
16387 DIP("vminsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16388 putVReg( vD_addr, binop(Iop_Min64Sx2, mkexpr(vA), mkexpr(vB)) );
16389 break;
16390
16391
16392 /* Average */
16393 case 0x402: // vavgub (Average Unsigned Byte, AV p152)
16394 DIP("vavgub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16395 putVReg( vD_addr, binop(Iop_Avg8Ux16, mkexpr(vA), mkexpr(vB)) );
16396 break;
16397
16398 case 0x442: // vavguh (Average Unsigned Half Word, AV p153)
16399 DIP("vavguh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16400 putVReg( vD_addr, binop(Iop_Avg16Ux8, mkexpr(vA), mkexpr(vB)) );
16401 break;
16402
16403 case 0x482: // vavguw (Average Unsigned Word, AV p154)
16404 DIP("vavguw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16405 putVReg( vD_addr, binop(Iop_Avg32Ux4, mkexpr(vA), mkexpr(vB)) );
16406 break;
16407
16408 case 0x502: // vavgsb (Average Signed Byte, AV p149)
16409 DIP("vavgsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16410 putVReg( vD_addr, binop(Iop_Avg8Sx16, mkexpr(vA), mkexpr(vB)) );
16411 break;
16412
16413 case 0x542: // vavgsh (Average Signed Half Word, AV p150)
16414 DIP("vavgsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16415 putVReg( vD_addr, binop(Iop_Avg16Sx8, mkexpr(vA), mkexpr(vB)) );
16416 break;
16417
16418 case 0x582: // vavgsw (Average Signed Word, AV p151)
16419 DIP("vavgsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16420 putVReg( vD_addr, binop(Iop_Avg32Sx4, mkexpr(vA), mkexpr(vB)) );
16421 break;
16422
16423
16424 /* Multiply */
16425 case 0x008: // vmuloub (Multiply Odd Unsigned Byte, AV p213)
16426 DIP("vmuloub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16427 putVReg( vD_addr,
16428 binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)));
16429 break;
16430
16431 case 0x048: // vmulouh (Multiply Odd Unsigned Half Word, AV p214)
16432 DIP("vmulouh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16433 putVReg( vD_addr,
16434 binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)));
16435 break;
16436
16437 case 0x088: // vmulouw (Multiply Odd Unsigned Word)
16438 DIP("vmulouw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16439 putVReg( vD_addr, binop( Iop_MullEven32Ux4, mkexpr(vA), mkexpr(vB) ) );
16440 break;
16441
16442 case 0x089: // vmuluwm (Multiply Unsigned Word Modulo)
16443 DIP("vmuluwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16444 putVReg( vD_addr, binop( Iop_Mul32x4, mkexpr(vA), mkexpr(vB) ) );
16445 break;
16446
16447 case 0x108: // vmulosb (Multiply Odd Signed Byte, AV p211)
16448 DIP("vmulosb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16449 putVReg( vD_addr,
16450 binop(Iop_MullEven8Sx16, mkexpr(vA), mkexpr(vB)));
16451 break;
16452
16453 case 0x148: // vmulosh (Multiply Odd Signed Half Word, AV p212)
16454 DIP("vmulosh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16455 putVReg( vD_addr,
16456 binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)));
16457 break;
16458
16459 case 0x188: // vmulosw (Multiply Odd Signed Word)
16460 DIP("vmulosw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16461 putVReg( vD_addr, binop( Iop_MullEven32Sx4, mkexpr(vA), mkexpr(vB) ) );
16462 break;
16463
16464 case 0x208: // vmuleub (Multiply Even Unsigned Byte, AV p209)
16465 DIP("vmuleub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16466 putVReg( vD_addr, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
16467 break;
16468
16469 case 0x248: // vmuleuh (Multiply Even Unsigned Half Word, AV p210)
16470 DIP("vmuleuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16471 putVReg( vD_addr, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
16472 break;
16473
16474 case 0x288: // vmuleuw (Multiply Even Unsigned Word)
16475 DIP("vmuleuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16476 putVReg( vD_addr, MK_Iop_MullOdd32Ux4( mkexpr(vA), mkexpr(vB) ) );
16477 break;
16478
16479 case 0x308: // vmulesb (Multiply Even Signed Byte, AV p207)
16480 DIP("vmulesb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16481 putVReg( vD_addr, MK_Iop_MullOdd8Sx16( mkexpr(vA), mkexpr(vB) ));
16482 break;
16483
16484 case 0x348: // vmulesh (Multiply Even Signed Half Word, AV p208)
16485 DIP("vmulesh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16486 putVReg( vD_addr, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
16487 break;
16488
16489 case 0x388: // vmulesw (Multiply Even Signed Word)
16490 DIP("vmulesw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16491 putVReg( vD_addr, MK_Iop_MullOdd32Sx4( mkexpr(vA), mkexpr(vB) ) );
16492 break;
16493
16494 /* Sum Across Partial */
16495 case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275)
16496 IRTemp aEE, aEO, aOE, aOO;
16497 aEE = aEO = aOE = aOO = IRTemp_INVALID;
16498 DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16499
16500 /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */
16501 expand8Ux16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
16502 expand16Ux8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
16503 expand16Ux8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
16504
16505 /* break V128 to 4xI32's, zero-extending to I64's */
16506 breakV128to4x64U( mkexpr(aEE), &a15, &a11, &a7, &a3 );
16507 breakV128to4x64U( mkexpr(aOE), &a14, &a10, &a6, &a2 );
16508 breakV128to4x64U( mkexpr(aEO), &a13, &a9, &a5, &a1 );
16509 breakV128to4x64U( mkexpr(aOO), &a12, &a8, &a4, &a0 );
16510 breakV128to4x64U( mkexpr(vB), &b3, &b2, &b1, &b0 );
16511
16512 /* add lanes */
16513 assign( z3, binop(Iop_Add64, mkexpr(b3),
16514 binop(Iop_Add64,
16515 binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
16516 binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
16517 assign( z2, binop(Iop_Add64, mkexpr(b2),
16518 binop(Iop_Add64,
16519 binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
16520 binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
16521 assign( z1, binop(Iop_Add64, mkexpr(b1),
16522 binop(Iop_Add64,
16523 binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
16524 binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
16525 assign( z0, binop(Iop_Add64, mkexpr(b0),
16526 binop(Iop_Add64,
16527 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
16528 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
16529
16530 /* saturate-narrow to 32bit, and combine to V128 */
16531 putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
16532 mkexpr(z1), mkexpr(z0)) );
16533 break;
16534 }
16535 case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273)
16536 IRTemp aEE, aEO, aOE, aOO;
16537 aEE = aEO = aOE = aOO = IRTemp_INVALID;
16538 DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16539
16540 /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */
16541 expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
16542 expand16Sx8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
16543 expand16Sx8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
16544
16545 /* break V128 to 4xI32's, sign-extending to I64's */
16546 breakV128to4x64S( mkexpr(aEE), &a15, &a11, &a7, &a3 );
16547 breakV128to4x64S( mkexpr(aOE), &a14, &a10, &a6, &a2 );
16548 breakV128to4x64S( mkexpr(aEO), &a13, &a9, &a5, &a1 );
16549 breakV128to4x64S( mkexpr(aOO), &a12, &a8, &a4, &a0 );
16550 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
16551
16552 /* add lanes */
16553 assign( z3, binop(Iop_Add64, mkexpr(b3),
16554 binop(Iop_Add64,
16555 binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
16556 binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
16557 assign( z2, binop(Iop_Add64, mkexpr(b2),
16558 binop(Iop_Add64,
16559 binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
16560 binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
16561 assign( z1, binop(Iop_Add64, mkexpr(b1),
16562 binop(Iop_Add64,
16563 binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
16564 binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
16565 assign( z0, binop(Iop_Add64, mkexpr(b0),
16566 binop(Iop_Add64,
16567 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
16568 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
16569
16570 /* saturate-narrow to 32bit, and combine to V128 */
16571 putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
16572 mkexpr(z1), mkexpr(z0)) );
16573 break;
16574 }
16575 case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274)
16576 DIP("vsum4shs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16577
16578 /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */
16579 expand16Sx8( mkexpr(vA), &aEvn, &aOdd ); // (7,5...),(6,4...)
16580
16581 /* break V128 to 4xI32's, sign-extending to I64's */
16582 breakV128to4x64S( mkexpr(aEvn), &a7, &a5, &a3, &a1 );
16583 breakV128to4x64S( mkexpr(aOdd), &a6, &a4, &a2, &a0 );
16584 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
16585
16586 /* add lanes */
16587 assign( z3, binop(Iop_Add64, mkexpr(b3),
16588 binop(Iop_Add64, mkexpr(a7), mkexpr(a6))));
16589 assign( z2, binop(Iop_Add64, mkexpr(b2),
16590 binop(Iop_Add64, mkexpr(a5), mkexpr(a4))));
16591 assign( z1, binop(Iop_Add64, mkexpr(b1),
16592 binop(Iop_Add64, mkexpr(a3), mkexpr(a2))));
16593 assign( z0, binop(Iop_Add64, mkexpr(b0),
16594 binop(Iop_Add64, mkexpr(a1), mkexpr(a0))));
16595
16596 /* saturate-narrow to 32bit, and combine to V128 */
16597 putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
16598 mkexpr(z1), mkexpr(z0)) );
16599 break;
16600 }
16601 case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272)
16602 DIP("vsum2sws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16603
16604 /* break V128 to 4xI32's, sign-extending to I64's */
16605 breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
16606 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
16607
16608 /* add lanes */
16609 assign( z2, binop(Iop_Add64, mkexpr(b2),
16610 binop(Iop_Add64, mkexpr(a3), mkexpr(a2))) );
16611 assign( z0, binop(Iop_Add64, mkexpr(b0),
16612 binop(Iop_Add64, mkexpr(a1), mkexpr(a0))) );
16613
16614 /* saturate-narrow to 32bit, and combine to V128 */
16615 putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkexpr(z2),
16616 mkU64(0), mkexpr(z0)) );
16617 break;
16618 }
16619 case 0x788: { // vsumsws (Sum SW Saturate, AV p271)
16620 DIP("vsumsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16621
16622 /* break V128 to 4xI32's, sign-extending to I64's */
16623 breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
16624 breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
16625
16626 /* add lanes */
16627 assign( z0, binop(Iop_Add64, mkexpr(b0),
16628 binop(Iop_Add64,
16629 binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
16630 binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
16631
16632 /* saturate-narrow to 32bit, and combine to V128 */
16633 putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkU64(0),
16634 mkU64(0), mkexpr(z0)) );
16635 break;
16636 }
16637 default:
16638 vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2);
16639 return False;
16640 }
16641 return True;
16642 }
16643
16644 /*
16645 AltiVec Logic Instructions
16646 */
dis_av_logic(UInt theInstr)16647 static Bool dis_av_logic ( UInt theInstr )
16648 {
16649 /* VX-Form */
16650 UChar opc1 = ifieldOPC(theInstr);
16651 UChar vD_addr = ifieldRegDS(theInstr);
16652 UChar vA_addr = ifieldRegA(theInstr);
16653 UChar vB_addr = ifieldRegB(theInstr);
16654 UInt opc2 = IFIELD( theInstr, 0, 11 );
16655
16656 IRTemp vA = newTemp(Ity_V128);
16657 IRTemp vB = newTemp(Ity_V128);
16658 assign( vA, getVReg(vA_addr));
16659 assign( vB, getVReg(vB_addr));
16660
16661 if (opc1 != 0x4) {
16662 vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n");
16663 return False;
16664 }
16665
16666 switch (opc2) {
16667 case 0x404: // vand (And, AV p147)
16668 DIP("vand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16669 putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), mkexpr(vB)) );
16670 break;
16671
16672 case 0x444: // vandc (And, AV p148)
16673 DIP("vandc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16674 putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA),
16675 unop(Iop_NotV128, mkexpr(vB))) );
16676 break;
16677
16678 case 0x484: // vor (Or, AV p217)
16679 DIP("vor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16680 putVReg( vD_addr, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB)) );
16681 break;
16682
16683 case 0x4C4: // vxor (Xor, AV p282)
16684 DIP("vxor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16685 putVReg( vD_addr, binop(Iop_XorV128, mkexpr(vA), mkexpr(vB)) );
16686 break;
16687
16688 case 0x504: // vnor (Nor, AV p216)
16689 DIP("vnor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16690 putVReg( vD_addr,
16691 unop(Iop_NotV128, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB))) );
16692 break;
16693
16694 case 0x544: // vorc (vA Or'd with complement of vb)
16695 DIP("vorc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16696 putVReg( vD_addr, binop( Iop_OrV128,
16697 mkexpr( vA ),
16698 unop( Iop_NotV128, mkexpr( vB ) ) ) );
16699 break;
16700
16701 case 0x584: // vnand (Nand)
16702 DIP("vnand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16703 putVReg( vD_addr, unop( Iop_NotV128,
16704 binop(Iop_AndV128, mkexpr( vA ),
16705 mkexpr( vB ) ) ) );
16706 break;
16707
16708 case 0x684: // veqv (complemented XOr)
16709 DIP("veqv v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16710 putVReg( vD_addr, unop( Iop_NotV128,
16711 binop( Iop_XorV128, mkexpr( vA ),
16712 mkexpr( vB ) ) ) );
16713 break;
16714
16715 default:
16716 vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2);
16717 return False;
16718 }
16719 return True;
16720 }
16721
16722 /*
16723 AltiVec Compare Instructions
16724 */
dis_av_cmp(UInt theInstr)16725 static Bool dis_av_cmp ( UInt theInstr )
16726 {
16727 /* VXR-Form */
16728 UChar opc1 = ifieldOPC(theInstr);
16729 UChar vD_addr = ifieldRegDS(theInstr);
16730 UChar vA_addr = ifieldRegA(theInstr);
16731 UChar vB_addr = ifieldRegB(theInstr);
16732 UChar flag_rC = ifieldBIT10(theInstr);
16733 UInt opc2 = IFIELD( theInstr, 0, 10 );
16734
16735 IRTemp vA = newTemp(Ity_V128);
16736 IRTemp vB = newTemp(Ity_V128);
16737 IRTemp vD = newTemp(Ity_V128);
16738 assign( vA, getVReg(vA_addr));
16739 assign( vB, getVReg(vB_addr));
16740
16741 if (opc1 != 0x4) {
16742 vex_printf("dis_av_cmp(ppc)(instr)\n");
16743 return False;
16744 }
16745
16746 switch (opc2) {
16747 case 0x006: // vcmpequb (Compare Equal-to Unsigned B, AV p160)
16748 DIP("vcmpequb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16749 vD_addr, vA_addr, vB_addr);
16750 assign( vD, binop(Iop_CmpEQ8x16, mkexpr(vA), mkexpr(vB)) );
16751 break;
16752
16753 case 0x046: // vcmpequh (Compare Equal-to Unsigned HW, AV p161)
16754 DIP("vcmpequh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16755 vD_addr, vA_addr, vB_addr);
16756 assign( vD, binop(Iop_CmpEQ16x8, mkexpr(vA), mkexpr(vB)) );
16757 break;
16758
16759 case 0x086: // vcmpequw (Compare Equal-to Unsigned W, AV p162)
16760 DIP("vcmpequw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16761 vD_addr, vA_addr, vB_addr);
16762 assign( vD, binop(Iop_CmpEQ32x4, mkexpr(vA), mkexpr(vB)) );
16763 break;
16764
16765 case 0x0C7: // vcmpequd (Compare Equal-to Unsigned Doubleword)
16766 DIP("vcmpequd%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16767 vD_addr, vA_addr, vB_addr);
16768 assign( vD, binop(Iop_CmpEQ64x2, mkexpr(vA), mkexpr(vB)) );
16769 break;
16770
16771 case 0x206: // vcmpgtub (Compare Greater-than Unsigned B, AV p168)
16772 DIP("vcmpgtub%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16773 vD_addr, vA_addr, vB_addr);
16774 assign( vD, binop(Iop_CmpGT8Ux16, mkexpr(vA), mkexpr(vB)) );
16775 break;
16776
16777 case 0x246: // vcmpgtuh (Compare Greater-than Unsigned HW, AV p169)
16778 DIP("vcmpgtuh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16779 vD_addr, vA_addr, vB_addr);
16780 assign( vD, binop(Iop_CmpGT16Ux8, mkexpr(vA), mkexpr(vB)) );
16781 break;
16782
16783 case 0x286: // vcmpgtuw (Compare Greater-than Unsigned W, AV p170)
16784 DIP("vcmpgtuw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16785 vD_addr, vA_addr, vB_addr);
16786 assign( vD, binop(Iop_CmpGT32Ux4, mkexpr(vA), mkexpr(vB)) );
16787 break;
16788
16789 case 0x2C7: // vcmpgtud (Compare Greater-than Unsigned double)
16790 DIP("vcmpgtud%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16791 vD_addr, vA_addr, vB_addr);
16792 assign( vD, binop(Iop_CmpGT64Ux2, mkexpr(vA), mkexpr(vB)) );
16793 break;
16794
16795 case 0x306: // vcmpgtsb (Compare Greater-than Signed B, AV p165)
16796 DIP("vcmpgtsb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16797 vD_addr, vA_addr, vB_addr);
16798 assign( vD, binop(Iop_CmpGT8Sx16, mkexpr(vA), mkexpr(vB)) );
16799 break;
16800
16801 case 0x346: // vcmpgtsh (Compare Greater-than Signed HW, AV p166)
16802 DIP("vcmpgtsh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16803 vD_addr, vA_addr, vB_addr);
16804 assign( vD, binop(Iop_CmpGT16Sx8, mkexpr(vA), mkexpr(vB)) );
16805 break;
16806
16807 case 0x386: // vcmpgtsw (Compare Greater-than Signed W, AV p167)
16808 DIP("vcmpgtsw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16809 vD_addr, vA_addr, vB_addr);
16810 assign( vD, binop(Iop_CmpGT32Sx4, mkexpr(vA), mkexpr(vB)) );
16811 break;
16812
16813 case 0x3C7: // vcmpgtsd (Compare Greater-than Signed double)
16814 DIP("vcmpgtsd%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16815 vD_addr, vA_addr, vB_addr);
16816 assign( vD, binop(Iop_CmpGT64Sx2, mkexpr(vA), mkexpr(vB)) );
16817 break;
16818
16819 default:
16820 vex_printf("dis_av_cmp(ppc)(opc2)\n");
16821 return False;
16822 }
16823
16824 putVReg( vD_addr, mkexpr(vD) );
16825
16826 if (flag_rC) {
16827 set_AV_CR6( mkexpr(vD), True );
16828 }
16829 return True;
16830 }
16831
16832 /*
16833 AltiVec Multiply-Sum Instructions
16834 */
dis_av_multarith(UInt theInstr)16835 static Bool dis_av_multarith ( UInt theInstr )
16836 {
16837 /* VA-Form */
16838 UChar opc1 = ifieldOPC(theInstr);
16839 UChar vD_addr = ifieldRegDS(theInstr);
16840 UChar vA_addr = ifieldRegA(theInstr);
16841 UChar vB_addr = ifieldRegB(theInstr);
16842 UChar vC_addr = ifieldRegC(theInstr);
16843 UChar opc2 = toUChar( IFIELD( theInstr, 0, 6 ) );
16844
16845 IRTemp vA = newTemp(Ity_V128);
16846 IRTemp vB = newTemp(Ity_V128);
16847 IRTemp vC = newTemp(Ity_V128);
16848 IRTemp zeros = newTemp(Ity_V128);
16849 IRTemp aLo = newTemp(Ity_V128);
16850 IRTemp bLo = newTemp(Ity_V128);
16851 IRTemp cLo = newTemp(Ity_V128);
16852 IRTemp zLo = newTemp(Ity_V128);
16853 IRTemp aHi = newTemp(Ity_V128);
16854 IRTemp bHi = newTemp(Ity_V128);
16855 IRTemp cHi = newTemp(Ity_V128);
16856 IRTemp zHi = newTemp(Ity_V128);
16857 IRTemp abEvn = newTemp(Ity_V128);
16858 IRTemp abOdd = newTemp(Ity_V128);
16859 IRTemp z3 = newTemp(Ity_I64);
16860 IRTemp z2 = newTemp(Ity_I64);
16861 IRTemp z1 = newTemp(Ity_I64);
16862 IRTemp z0 = newTemp(Ity_I64);
16863 IRTemp ab7, ab6, ab5, ab4, ab3, ab2, ab1, ab0;
16864 IRTemp c3, c2, c1, c0;
16865
16866 ab7 = ab6 = ab5 = ab4 = ab3 = ab2 = ab1 = ab0 = IRTemp_INVALID;
16867 c3 = c2 = c1 = c0 = IRTemp_INVALID;
16868
16869 assign( vA, getVReg(vA_addr));
16870 assign( vB, getVReg(vB_addr));
16871 assign( vC, getVReg(vC_addr));
16872 assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
16873
16874 if (opc1 != 0x4) {
16875 vex_printf("dis_av_multarith(ppc)(instr)\n");
16876 return False;
16877 }
16878
16879 switch (opc2) {
16880 /* Multiply-Add */
16881 case 0x20: { // vmhaddshs (Mult Hi, Add Signed HW Saturate, AV p185)
16882 IRTemp cSigns = newTemp(Ity_V128);
16883 DIP("vmhaddshs v%d,v%d,v%d,v%d\n",
16884 vD_addr, vA_addr, vB_addr, vC_addr);
16885 assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)));
16886 assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
16887 assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
16888 assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
16889 assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
16890 assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
16891 assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
16892
16893 assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
16894 binop(Iop_SarN32x4,
16895 binop(Iop_MullEven16Sx8,
16896 mkexpr(aLo), mkexpr(bLo)),
16897 mkU8(15))) );
16898
16899 assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
16900 binop(Iop_SarN32x4,
16901 binop(Iop_MullEven16Sx8,
16902 mkexpr(aHi), mkexpr(bHi)),
16903 mkU8(15))) );
16904
16905 putVReg( vD_addr,
16906 binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
16907 break;
16908 }
16909 case 0x21: { // vmhraddshs (Mult High Round, Add Signed HW Saturate, AV p186)
16910 IRTemp zKonst = newTemp(Ity_V128);
16911 IRTemp cSigns = newTemp(Ity_V128);
16912 DIP("vmhraddshs v%d,v%d,v%d,v%d\n",
16913 vD_addr, vA_addr, vB_addr, vC_addr);
16914 assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)) );
16915 assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
16916 assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
16917 assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
16918 assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
16919 assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
16920 assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
16921
16922 /* shifting our const avoids store/load version of Dup */
16923 assign( zKonst, binop(Iop_ShlN32x4, unop(Iop_Dup32x4, mkU32(0x1)),
16924 mkU8(14)) );
16925
16926 assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
16927 binop(Iop_SarN32x4,
16928 binop(Iop_Add32x4, mkexpr(zKonst),
16929 binop(Iop_MullEven16Sx8,
16930 mkexpr(aLo), mkexpr(bLo))),
16931 mkU8(15))) );
16932
16933 assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
16934 binop(Iop_SarN32x4,
16935 binop(Iop_Add32x4, mkexpr(zKonst),
16936 binop(Iop_MullEven16Sx8,
16937 mkexpr(aHi), mkexpr(bHi))),
16938 mkU8(15))) );
16939
16940 putVReg( vD_addr,
16941 binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
16942 break;
16943 }
16944 case 0x22: { // vmladduhm (Mult Low, Add Unsigned HW Modulo, AV p194)
16945 DIP("vmladduhm v%d,v%d,v%d,v%d\n",
16946 vD_addr, vA_addr, vB_addr, vC_addr);
16947 assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
16948 assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
16949 assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vC)));
16950 assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
16951 assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
16952 assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vC)));
16953 assign(zLo, binop(Iop_Add32x4,
16954 binop(Iop_MullEven16Ux8, mkexpr(aLo), mkexpr(bLo)),
16955 mkexpr(cLo)) );
16956 assign(zHi, binop(Iop_Add32x4,
16957 binop(Iop_MullEven16Ux8, mkexpr(aHi), mkexpr(bHi)),
16958 mkexpr(cHi)));
16959 putVReg( vD_addr,
16960 binop(Iop_NarrowBin32to16x8, mkexpr(zHi), mkexpr(zLo)) );
16961 break;
16962 }
16963
16964
16965 /* Multiply-Sum */
16966 case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204)
16967 IRTemp abEE, abEO, abOE, abOO;
16968 abEE = abEO = abOE = abOO = IRTemp_INVALID;
16969 DIP("vmsumubm v%d,v%d,v%d,v%d\n",
16970 vD_addr, vA_addr, vB_addr, vC_addr);
16971
16972 /* multiply vA,vB (unsigned, widening) */
16973 assign( abEvn, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
16974 assign( abOdd, binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)) );
16975
16976 /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */
16977 expand16Ux8( mkexpr(abEvn), &abEE, &abEO );
16978 expand16Ux8( mkexpr(abOdd), &abOE, &abOO );
16979
16980 putVReg( vD_addr,
16981 binop(Iop_Add32x4, mkexpr(vC),
16982 binop(Iop_Add32x4,
16983 binop(Iop_Add32x4, mkexpr(abEE), mkexpr(abEO)),
16984 binop(Iop_Add32x4, mkexpr(abOE), mkexpr(abOO)))) );
16985 break;
16986 }
16987 case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201)
16988 IRTemp aEvn, aOdd, bEvn, bOdd;
16989 IRTemp abEE = newTemp(Ity_V128);
16990 IRTemp abEO = newTemp(Ity_V128);
16991 IRTemp abOE = newTemp(Ity_V128);
16992 IRTemp abOO = newTemp(Ity_V128);
16993 aEvn = aOdd = bEvn = bOdd = IRTemp_INVALID;
16994 DIP("vmsummbm v%d,v%d,v%d,v%d\n",
16995 vD_addr, vA_addr, vB_addr, vC_addr);
16996
16997 /* sign-extend vA, zero-extend vB, for mixed-sign multiply
16998 (separating out adjacent lanes to different vectors) */
16999 expand8Sx16( mkexpr(vA), &aEvn, &aOdd );
17000 expand8Ux16( mkexpr(vB), &bEvn, &bOdd );
17001
17002 /* multiply vA, vB, again separating adjacent lanes */
17003 assign( abEE, MK_Iop_MullOdd16Sx8( mkexpr(aEvn), mkexpr(bEvn) ));
17004 assign( abEO, binop(Iop_MullEven16Sx8, mkexpr(aEvn), mkexpr(bEvn)) );
17005 assign( abOE, MK_Iop_MullOdd16Sx8( mkexpr(aOdd), mkexpr(bOdd) ));
17006 assign( abOO, binop(Iop_MullEven16Sx8, mkexpr(aOdd), mkexpr(bOdd)) );
17007
17008 /* add results together, + vC */
17009 putVReg( vD_addr,
17010 binop(Iop_QAdd32Sx4, mkexpr(vC),
17011 binop(Iop_QAdd32Sx4,
17012 binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)),
17013 binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)))) );
17014 break;
17015 }
17016 case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205)
17017 DIP("vmsumuhm v%d,v%d,v%d,v%d\n",
17018 vD_addr, vA_addr, vB_addr, vC_addr);
17019 assign( abEvn, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
17020 assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
17021 putVReg( vD_addr,
17022 binop(Iop_Add32x4, mkexpr(vC),
17023 binop(Iop_Add32x4, mkexpr(abEvn), mkexpr(abOdd))) );
17024 break;
17025 }
17026 case 0x27: { // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206)
17027 DIP("vmsumuhs v%d,v%d,v%d,v%d\n",
17028 vD_addr, vA_addr, vB_addr, vC_addr);
17029 /* widening multiply, separating lanes */
17030 assign( abEvn, MK_Iop_MullOdd16Ux8(mkexpr(vA), mkexpr(vB) ));
17031 assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
17032
17033 /* break V128 to 4xI32's, zero-extending to I64's */
17034 breakV128to4x64U( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
17035 breakV128to4x64U( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
17036 breakV128to4x64U( mkexpr(vC), &c3, &c2, &c1, &c0 );
17037
17038 /* add lanes */
17039 assign( z3, binop(Iop_Add64, mkexpr(c3),
17040 binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
17041 assign( z2, binop(Iop_Add64, mkexpr(c2),
17042 binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
17043 assign( z1, binop(Iop_Add64, mkexpr(c1),
17044 binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
17045 assign( z0, binop(Iop_Add64, mkexpr(c0),
17046 binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
17047
17048 /* saturate-narrow to 32bit, and combine to V128 */
17049 putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
17050 mkexpr(z1), mkexpr(z0)) );
17051
17052 break;
17053 }
17054 case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202)
17055 DIP("vmsumshm v%d,v%d,v%d,v%d\n",
17056 vD_addr, vA_addr, vB_addr, vC_addr);
17057 assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
17058 assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
17059 putVReg( vD_addr,
17060 binop(Iop_Add32x4, mkexpr(vC),
17061 binop(Iop_Add32x4, mkexpr(abOdd), mkexpr(abEvn))) );
17062 break;
17063 }
17064 case 0x29: { // vmsumshs (Multiply Sum Signed HW Saturate, AV p203)
17065 DIP("vmsumshs v%d,v%d,v%d,v%d\n",
17066 vD_addr, vA_addr, vB_addr, vC_addr);
17067 /* widening multiply, separating lanes */
17068 assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
17069 assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
17070
17071 /* break V128 to 4xI32's, sign-extending to I64's */
17072 breakV128to4x64S( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
17073 breakV128to4x64S( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
17074 breakV128to4x64S( mkexpr(vC), &c3, &c2, &c1, &c0 );
17075
17076 /* add lanes */
17077 assign( z3, binop(Iop_Add64, mkexpr(c3),
17078 binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
17079 assign( z2, binop(Iop_Add64, mkexpr(c2),
17080 binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
17081 assign( z1, binop(Iop_Add64, mkexpr(c1),
17082 binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
17083 assign( z0, binop(Iop_Add64, mkexpr(c0),
17084 binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
17085
17086 /* saturate-narrow to 32bit, and combine to V128 */
17087 putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
17088 mkexpr(z1), mkexpr(z0)) );
17089 break;
17090 }
17091 default:
17092 vex_printf("dis_av_multarith(ppc)(opc2)\n");
17093 return False;
17094 }
17095 return True;
17096 }
17097
17098 /*
17099 AltiVec Polynomial Multiply-Sum Instructions
17100 */
dis_av_polymultarith(UInt theInstr)17101 static Bool dis_av_polymultarith ( UInt theInstr )
17102 {
17103 /* VA-Form */
17104 UChar opc1 = ifieldOPC(theInstr);
17105 UChar vD_addr = ifieldRegDS(theInstr);
17106 UChar vA_addr = ifieldRegA(theInstr);
17107 UChar vB_addr = ifieldRegB(theInstr);
17108 UChar vC_addr = ifieldRegC(theInstr);
17109 UInt opc2 = IFIELD(theInstr, 0, 11);
17110 IRTemp vA = newTemp(Ity_V128);
17111 IRTemp vB = newTemp(Ity_V128);
17112 IRTemp vC = newTemp(Ity_V128);
17113
17114 assign( vA, getVReg(vA_addr));
17115 assign( vB, getVReg(vB_addr));
17116 assign( vC, getVReg(vC_addr));
17117
17118 if (opc1 != 0x4) {
17119 vex_printf("dis_av_polymultarith(ppc)(instr)\n");
17120 return False;
17121 }
17122
17123 switch (opc2) {
17124 /* Polynomial Multiply-Add */
17125 case 0x408: // vpmsumb Vector Polynomial Multipy-sum Byte
17126 DIP("vpmsumb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17127 putVReg( vD_addr, binop(Iop_PolynomialMulAdd8x16,
17128 mkexpr(vA), mkexpr(vB)) );
17129 break;
17130 case 0x448: // vpmsumd Vector Polynomial Multipy-sum Double Word
17131 DIP("vpmsumd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17132 putVReg( vD_addr, binop(Iop_PolynomialMulAdd64x2,
17133 mkexpr(vA), mkexpr(vB)) );
17134 break;
17135 case 0x488: // vpmsumw Vector Polynomial Multipy-sum Word
17136 DIP("vpmsumw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17137 putVReg( vD_addr, binop(Iop_PolynomialMulAdd32x4,
17138 mkexpr(vA), mkexpr(vB)) );
17139 break;
17140 case 0x4C8: // vpmsumh Vector Polynomial Multipy-sum Half Word
17141 DIP("vpmsumh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17142 putVReg( vD_addr, binop(Iop_PolynomialMulAdd16x8,
17143 mkexpr(vA), mkexpr(vB)) );
17144 break;
17145 default:
17146 vex_printf("dis_av_polymultarith(ppc)(opc2=0x%x)\n", opc2);
17147 return False;
17148 }
17149 return True;
17150 }
17151
17152 /*
17153 AltiVec Shift/Rotate Instructions
17154 */
dis_av_shift(UInt theInstr)17155 static Bool dis_av_shift ( UInt theInstr )
17156 {
17157 /* VX-Form */
17158 UChar opc1 = ifieldOPC(theInstr);
17159 UChar vD_addr = ifieldRegDS(theInstr);
17160 UChar vA_addr = ifieldRegA(theInstr);
17161 UChar vB_addr = ifieldRegB(theInstr);
17162 UInt opc2 = IFIELD( theInstr, 0, 11 );
17163
17164 IRTemp vA = newTemp(Ity_V128);
17165 IRTemp vB = newTemp(Ity_V128);
17166 assign( vA, getVReg(vA_addr));
17167 assign( vB, getVReg(vB_addr));
17168
17169 if (opc1 != 0x4){
17170 vex_printf("dis_av_shift(ppc)(instr)\n");
17171 return False;
17172 }
17173
17174 switch (opc2) {
17175 /* Rotate */
17176 case 0x004: // vrlb (Rotate Left Integer B, AV p234)
17177 DIP("vrlb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17178 putVReg( vD_addr, binop(Iop_Rol8x16, mkexpr(vA), mkexpr(vB)) );
17179 break;
17180
17181 case 0x044: // vrlh (Rotate Left Integer HW, AV p235)
17182 DIP("vrlh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17183 putVReg( vD_addr, binop(Iop_Rol16x8, mkexpr(vA), mkexpr(vB)) );
17184 break;
17185
17186 case 0x084: // vrlw (Rotate Left Integer W, AV p236)
17187 DIP("vrlw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17188 putVReg( vD_addr, binop(Iop_Rol32x4, mkexpr(vA), mkexpr(vB)) );
17189 break;
17190
17191 case 0x0C4: // vrld (Rotate Left Integer Double Word)
17192 DIP("vrld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17193 putVReg( vD_addr, binop(Iop_Rol64x2, mkexpr(vA), mkexpr(vB)) );
17194 break;
17195
17196
17197 /* Shift Left */
17198 case 0x104: // vslb (Shift Left Integer B, AV p240)
17199 DIP("vslb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17200 putVReg( vD_addr, binop(Iop_Shl8x16, mkexpr(vA), mkexpr(vB)) );
17201 break;
17202
17203 case 0x144: // vslh (Shift Left Integer HW, AV p242)
17204 DIP("vslh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17205 putVReg( vD_addr, binop(Iop_Shl16x8, mkexpr(vA), mkexpr(vB)) );
17206 break;
17207
17208 case 0x184: // vslw (Shift Left Integer W, AV p244)
17209 DIP("vslw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17210 putVReg( vD_addr, binop(Iop_Shl32x4, mkexpr(vA), mkexpr(vB)) );
17211 break;
17212
17213 case 0x5C4: // vsld (Shift Left Integer Double Word)
17214 DIP("vsld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17215 putVReg( vD_addr, binop(Iop_Shl64x2, mkexpr(vA), mkexpr(vB)) );
17216 break;
17217
17218 case 0x1C4: { // vsl (Shift Left, AV p239)
17219 IRTemp sh = newTemp(Ity_I8);
17220 DIP("vsl v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17221 assign( sh, binop(Iop_And8, mkU8(0x7),
17222 unop(Iop_32to8,
17223 unop(Iop_V128to32, mkexpr(vB)))) );
17224 putVReg( vD_addr,
17225 binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
17226 break;
17227 }
17228 case 0x40C: { // vslo (Shift Left by Octet, AV p243)
17229 IRTemp sh = newTemp(Ity_I8);
17230 DIP("vslo v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17231 assign( sh, binop(Iop_And8, mkU8(0x78),
17232 unop(Iop_32to8,
17233 unop(Iop_V128to32, mkexpr(vB)))) );
17234 putVReg( vD_addr,
17235 binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
17236 break;
17237 }
17238
17239
17240 /* Shift Right */
17241 case 0x204: // vsrb (Shift Right B, AV p256)
17242 DIP("vsrb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17243 putVReg( vD_addr, binop(Iop_Shr8x16, mkexpr(vA), mkexpr(vB)) );
17244 break;
17245
17246 case 0x244: // vsrh (Shift Right HW, AV p257)
17247 DIP("vsrh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17248 putVReg( vD_addr, binop(Iop_Shr16x8, mkexpr(vA), mkexpr(vB)) );
17249 break;
17250
17251 case 0x284: // vsrw (Shift Right W, AV p259)
17252 DIP("vsrw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17253 putVReg( vD_addr, binop(Iop_Shr32x4, mkexpr(vA), mkexpr(vB)) );
17254 break;
17255
17256 case 0x2C4: { // vsr (Shift Right, AV p251)
17257 IRTemp sh = newTemp(Ity_I8);
17258 DIP("vsr v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17259 assign( sh, binop(Iop_And8, mkU8(0x7),
17260 unop(Iop_32to8,
17261 unop(Iop_V128to32, mkexpr(vB)))) );
17262 putVReg( vD_addr,
17263 binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
17264 break;
17265 }
17266 case 0x304: // vsrab (Shift Right Alg B, AV p253)
17267 DIP("vsrab v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17268 putVReg( vD_addr, binop(Iop_Sar8x16, mkexpr(vA), mkexpr(vB)) );
17269 break;
17270
17271 case 0x344: // vsrah (Shift Right Alg HW, AV p254)
17272 DIP("vsrah v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17273 putVReg( vD_addr, binop(Iop_Sar16x8, mkexpr(vA), mkexpr(vB)) );
17274 break;
17275
17276 case 0x384: // vsraw (Shift Right Alg W, AV p255)
17277 DIP("vsraw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17278 putVReg( vD_addr, binop(Iop_Sar32x4, mkexpr(vA), mkexpr(vB)) );
17279 break;
17280
17281 case 0x3C4: // vsrad (Shift Right Alg Double Word)
17282 DIP("vsrad v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17283 putVReg( vD_addr, binop(Iop_Sar64x2, mkexpr(vA), mkexpr(vB)) );
17284 break;
17285
17286 case 0x44C: { // vsro (Shift Right by Octet, AV p258)
17287 IRTemp sh = newTemp(Ity_I8);
17288 DIP("vsro v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17289 assign( sh, binop(Iop_And8, mkU8(0x78),
17290 unop(Iop_32to8,
17291 unop(Iop_V128to32, mkexpr(vB)))) );
17292 putVReg( vD_addr,
17293 binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
17294 break;
17295 }
17296
17297 case 0x6C4: // vsrd (Shift Right Double Word)
17298 DIP("vsrd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17299 putVReg( vD_addr, binop(Iop_Shr64x2, mkexpr(vA), mkexpr(vB)) );
17300 break;
17301
17302
17303 default:
17304 vex_printf("dis_av_shift(ppc)(opc2)\n");
17305 return False;
17306 }
17307 return True;
17308 }
17309
17310 /*
17311 AltiVec Permute Instructions
17312 */
dis_av_permute(UInt theInstr)17313 static Bool dis_av_permute ( UInt theInstr )
17314 {
17315 /* VA-Form, VX-Form */
17316 UChar opc1 = ifieldOPC(theInstr);
17317 UChar vD_addr = ifieldRegDS(theInstr);
17318 UChar vA_addr = ifieldRegA(theInstr);
17319 UChar UIMM_5 = vA_addr;
17320 UChar vB_addr = ifieldRegB(theInstr);
17321 UChar vC_addr = ifieldRegC(theInstr);
17322 UChar b10 = ifieldBIT10(theInstr);
17323 UChar SHB_uimm4 = toUChar( IFIELD( theInstr, 6, 4 ) );
17324 UInt opc2 = toUChar( IFIELD( theInstr, 0, 6 ) );
17325
17326 UChar SIMM_8 = extend_s_5to8(UIMM_5);
17327
17328 IRTemp vA = newTemp(Ity_V128);
17329 IRTemp vB = newTemp(Ity_V128);
17330 IRTemp vC = newTemp(Ity_V128);
17331 assign( vA, getVReg(vA_addr));
17332 assign( vB, getVReg(vB_addr));
17333 assign( vC, getVReg(vC_addr));
17334
17335 if (opc1 != 0x4) {
17336 vex_printf("dis_av_permute(ppc)(instr)\n");
17337 return False;
17338 }
17339
17340 switch (opc2) {
17341 case 0x2A: // vsel (Conditional Select, AV p238)
17342 DIP("vsel v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
17343 /* vD = (vA & ~vC) | (vB & vC) */
17344 putVReg( vD_addr, binop(Iop_OrV128,
17345 binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
17346 binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
17347 return True;
17348
17349 case 0x2B: { // vperm (Permute, AV p218)
17350 /* limited to two args for IR, so have to play games... */
17351 IRTemp a_perm = newTemp(Ity_V128);
17352 IRTemp b_perm = newTemp(Ity_V128);
17353 IRTemp mask = newTemp(Ity_V128);
17354 IRTemp vC_andF = newTemp(Ity_V128);
17355 DIP("vperm v%d,v%d,v%d,v%d\n",
17356 vD_addr, vA_addr, vB_addr, vC_addr);
17357 /* Limit the Perm8x16 steering values to 0 .. 15 as that is what
17358 IR specifies, and also to hide irrelevant bits from
17359 memcheck */
17360 assign( vC_andF,
17361 binop(Iop_AndV128, mkexpr(vC),
17362 unop(Iop_Dup8x16, mkU8(0xF))) );
17363 assign( a_perm,
17364 binop(Iop_Perm8x16, mkexpr(vA), mkexpr(vC_andF)) );
17365 assign( b_perm,
17366 binop(Iop_Perm8x16, mkexpr(vB), mkexpr(vC_andF)) );
17367 // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0
17368 assign( mask, binop(Iop_SarN8x16,
17369 binop(Iop_ShlN8x16, mkexpr(vC), mkU8(3)),
17370 mkU8(7)) );
17371 // dst = (a & ~mask) | (b & mask)
17372 putVReg( vD_addr, binop(Iop_OrV128,
17373 binop(Iop_AndV128, mkexpr(a_perm),
17374 unop(Iop_NotV128, mkexpr(mask))),
17375 binop(Iop_AndV128, mkexpr(b_perm),
17376 mkexpr(mask))) );
17377 return True;
17378 }
17379 case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241)
17380 if (b10 != 0) {
17381 vex_printf("dis_av_permute(ppc)(vsldoi)\n");
17382 return False;
17383 }
17384 DIP("vsldoi v%d,v%d,v%d,%d\n",
17385 vD_addr, vA_addr, vB_addr, SHB_uimm4);
17386 if (SHB_uimm4 == 0)
17387 putVReg( vD_addr, mkexpr(vA) );
17388 else
17389 putVReg( vD_addr,
17390 binop(Iop_OrV128,
17391 binop(Iop_ShlV128, mkexpr(vA), mkU8(SHB_uimm4*8)),
17392 binop(Iop_ShrV128, mkexpr(vB), mkU8((16-SHB_uimm4)*8))) );
17393 return True;
17394 case 0x2D: { // vpermxor (Vector Permute and Exclusive-OR)
17395 IRTemp a_perm = newTemp(Ity_V128);
17396 IRTemp b_perm = newTemp(Ity_V128);
17397 IRTemp vrc_a = newTemp(Ity_V128);
17398 IRTemp vrc_b = newTemp(Ity_V128);
17399
17400 /* IBM index is 0:7, Change index value to index 7:0 */
17401 assign( vrc_b, binop( Iop_AndV128, mkexpr( vC ),
17402 unop( Iop_Dup8x16, mkU8( 0xF ) ) ) );
17403 assign( vrc_a, binop( Iop_ShrV128,
17404 binop( Iop_AndV128, mkexpr( vC ),
17405 unop( Iop_Dup8x16, mkU8( 0xF0 ) ) ),
17406 mkU8 ( 4 ) ) );
17407 assign( a_perm, binop( Iop_Perm8x16, mkexpr( vA ), mkexpr( vrc_a ) ) );
17408 assign( b_perm, binop( Iop_Perm8x16, mkexpr( vB ), mkexpr( vrc_b ) ) );
17409 putVReg( vD_addr, binop( Iop_XorV128,
17410 mkexpr( a_perm ), mkexpr( b_perm) ) );
17411 return True;
17412 }
17413 default:
17414 break; // Fall through...
17415 }
17416
17417 opc2 = IFIELD( theInstr, 0, 11 );
17418 switch (opc2) {
17419
17420 /* Merge */
17421 case 0x00C: // vmrghb (Merge High B, AV p195)
17422 DIP("vmrghb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17423 putVReg( vD_addr,
17424 binop(Iop_InterleaveHI8x16, mkexpr(vA), mkexpr(vB)) );
17425 break;
17426
17427 case 0x04C: // vmrghh (Merge High HW, AV p196)
17428 DIP("vmrghh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17429 putVReg( vD_addr,
17430 binop(Iop_InterleaveHI16x8, mkexpr(vA), mkexpr(vB)) );
17431 break;
17432
17433 case 0x08C: // vmrghw (Merge High W, AV p197)
17434 DIP("vmrghw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17435 putVReg( vD_addr,
17436 binop(Iop_InterleaveHI32x4, mkexpr(vA), mkexpr(vB)) );
17437 break;
17438
17439 case 0x10C: // vmrglb (Merge Low B, AV p198)
17440 DIP("vmrglb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17441 putVReg( vD_addr,
17442 binop(Iop_InterleaveLO8x16, mkexpr(vA), mkexpr(vB)) );
17443 break;
17444
17445 case 0x14C: // vmrglh (Merge Low HW, AV p199)
17446 DIP("vmrglh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17447 putVReg( vD_addr,
17448 binop(Iop_InterleaveLO16x8, mkexpr(vA), mkexpr(vB)) );
17449 break;
17450
17451 case 0x18C: // vmrglw (Merge Low W, AV p200)
17452 DIP("vmrglw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17453 putVReg( vD_addr,
17454 binop(Iop_InterleaveLO32x4, mkexpr(vA), mkexpr(vB)) );
17455 break;
17456
17457
17458 /* Splat */
17459 case 0x20C: { // vspltb (Splat Byte, AV p245)
17460 /* vD = Dup8x16( vB[UIMM_5] ) */
17461 UChar sh_uimm = (15 - (UIMM_5 & 15)) * 8;
17462 DIP("vspltb v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
17463 putVReg( vD_addr, unop(Iop_Dup8x16,
17464 unop(Iop_32to8, unop(Iop_V128to32,
17465 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
17466 break;
17467 }
17468 case 0x24C: { // vsplth (Splat Half Word, AV p246)
17469 UChar sh_uimm = (7 - (UIMM_5 & 7)) * 16;
17470 DIP("vsplth v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
17471 putVReg( vD_addr, unop(Iop_Dup16x8,
17472 unop(Iop_32to16, unop(Iop_V128to32,
17473 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
17474 break;
17475 }
17476 case 0x28C: { // vspltw (Splat Word, AV p250)
17477 /* vD = Dup32x4( vB[UIMM_5] ) */
17478 UChar sh_uimm = (3 - (UIMM_5 & 3)) * 32;
17479 DIP("vspltw v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
17480 putVReg( vD_addr, unop(Iop_Dup32x4,
17481 unop(Iop_V128to32,
17482 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm)))) );
17483 break;
17484 }
17485 case 0x30C: // vspltisb (Splat Immediate Signed B, AV p247)
17486 DIP("vspltisb v%d,%d\n", vD_addr, (Char)SIMM_8);
17487 putVReg( vD_addr, unop(Iop_Dup8x16, mkU8(SIMM_8)) );
17488 break;
17489
17490 case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248)
17491 DIP("vspltish v%d,%d\n", vD_addr, (Char)SIMM_8);
17492 putVReg( vD_addr,
17493 unop(Iop_Dup16x8, mkU16(extend_s_8to32(SIMM_8))) );
17494 break;
17495
17496 case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249)
17497 DIP("vspltisw v%d,%d\n", vD_addr, (Char)SIMM_8);
17498 putVReg( vD_addr,
17499 unop(Iop_Dup32x4, mkU32(extend_s_8to32(SIMM_8))) );
17500 break;
17501
17502 case 0x68C: // vmrgow (Merge Odd Word)
17503 DIP("vmrgow v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17504 /* VD[0] <- VA[1]
17505 VD[1] <- VB[1]
17506 VD[2] <- VA[3]
17507 VD[3] <- VB[3]
17508 */
17509 putVReg( vD_addr,
17510 binop(Iop_CatOddLanes32x4, mkexpr(vA), mkexpr(vB) ) );
17511 break;
17512
17513 case 0x78C: // vmrgew (Merge Even Word)
17514 DIP("vmrgew v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17515 /* VD[0] <- VA[0]
17516 VD[1] <- VB[0]
17517 VD[2] <- VA[2]
17518 VD[3] <- VB[2]
17519 */
17520 putVReg( vD_addr,
17521 binop(Iop_CatEvenLanes32x4, mkexpr(vA), mkexpr(vB) ) );
17522 break;
17523
17524 default:
17525 vex_printf("dis_av_permute(ppc)(opc2)\n");
17526 return False;
17527 }
17528 return True;
17529 }
17530
17531 /*
17532 AltiVec Pack/Unpack Instructions
17533 */
dis_av_pack(UInt theInstr)17534 static Bool dis_av_pack ( UInt theInstr )
17535 {
17536 /* VX-Form */
17537 UChar opc1 = ifieldOPC(theInstr);
17538 UChar vD_addr = ifieldRegDS(theInstr);
17539 UChar vA_addr = ifieldRegA(theInstr);
17540 UChar vB_addr = ifieldRegB(theInstr);
17541 UInt opc2 = IFIELD( theInstr, 0, 11 );
17542
17543 IRTemp signs = IRTemp_INVALID;
17544 IRTemp zeros = IRTemp_INVALID;
17545 IRTemp vA = newTemp(Ity_V128);
17546 IRTemp vB = newTemp(Ity_V128);
17547 assign( vA, getVReg(vA_addr));
17548 assign( vB, getVReg(vB_addr));
17549
17550 if (opc1 != 0x4) {
17551 vex_printf("dis_av_pack(ppc)(instr)\n");
17552 return False;
17553 }
17554 switch (opc2) {
17555 /* Packing */
17556 case 0x00E: // vpkuhum (Pack Unsigned HW Unsigned Modulo, AV p224)
17557 DIP("vpkuhum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17558 putVReg( vD_addr,
17559 binop(Iop_NarrowBin16to8x16, mkexpr(vA), mkexpr(vB)) );
17560 return True;
17561
17562 case 0x04E: // vpkuwum (Pack Unsigned W Unsigned Modulo, AV p226)
17563 DIP("vpkuwum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17564 putVReg( vD_addr,
17565 binop(Iop_NarrowBin32to16x8, mkexpr(vA), mkexpr(vB)) );
17566 return True;
17567
17568 case 0x08E: // vpkuhus (Pack Unsigned HW Unsigned Saturate, AV p225)
17569 DIP("vpkuhus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17570 putVReg( vD_addr,
17571 binop(Iop_QNarrowBin16Uto8Ux16, mkexpr(vA), mkexpr(vB)) );
17572 // TODO: set VSCR[SAT]
17573 return True;
17574
17575 case 0x0CE: // vpkuwus (Pack Unsigned W Unsigned Saturate, AV p227)
17576 DIP("vpkuwus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17577 putVReg( vD_addr,
17578 binop(Iop_QNarrowBin32Uto16Ux8, mkexpr(vA), mkexpr(vB)) );
17579 // TODO: set VSCR[SAT]
17580 return True;
17581
17582 case 0x10E: { // vpkshus (Pack Signed HW Unsigned Saturate, AV p221)
17583 // This insn does a signed->unsigned saturating conversion.
17584 // Conversion done here, then uses unsigned->unsigned vpk insn:
17585 // => UnsignedSaturatingNarrow( x & ~ (x >>s 15) )
17586 IRTemp vA_tmp = newTemp(Ity_V128);
17587 IRTemp vB_tmp = newTemp(Ity_V128);
17588 DIP("vpkshus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17589 assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
17590 unop(Iop_NotV128,
17591 binop(Iop_SarN16x8,
17592 mkexpr(vA), mkU8(15)))) );
17593 assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
17594 unop(Iop_NotV128,
17595 binop(Iop_SarN16x8,
17596 mkexpr(vB), mkU8(15)))) );
17597 putVReg( vD_addr, binop(Iop_QNarrowBin16Uto8Ux16,
17598 mkexpr(vA_tmp), mkexpr(vB_tmp)) );
17599 // TODO: set VSCR[SAT]
17600 return True;
17601 }
17602 case 0x14E: { // vpkswus (Pack Signed W Unsigned Saturate, AV p223)
17603 // This insn does a signed->unsigned saturating conversion.
17604 // Conversion done here, then uses unsigned->unsigned vpk insn:
17605 // => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
17606 IRTemp vA_tmp = newTemp(Ity_V128);
17607 IRTemp vB_tmp = newTemp(Ity_V128);
17608 DIP("vpkswus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17609 assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
17610 unop(Iop_NotV128,
17611 binop(Iop_SarN32x4,
17612 mkexpr(vA), mkU8(31)))) );
17613 assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
17614 unop(Iop_NotV128,
17615 binop(Iop_SarN32x4,
17616 mkexpr(vB), mkU8(31)))) );
17617 putVReg( vD_addr, binop(Iop_QNarrowBin32Uto16Ux8,
17618 mkexpr(vA_tmp), mkexpr(vB_tmp)) );
17619 // TODO: set VSCR[SAT]
17620 return True;
17621 }
17622 case 0x18E: // vpkshss (Pack Signed HW Signed Saturate, AV p220)
17623 DIP("vpkshss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17624 putVReg( vD_addr,
17625 binop(Iop_QNarrowBin16Sto8Sx16, mkexpr(vA), mkexpr(vB)) );
17626 // TODO: set VSCR[SAT]
17627 return True;
17628
17629 case 0x1CE: // vpkswss (Pack Signed W Signed Saturate, AV p222)
17630 DIP("vpkswss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17631 putVReg( vD_addr,
17632 binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(vA), mkexpr(vB)) );
17633 // TODO: set VSCR[SAT]
17634 return True;
17635
17636 case 0x30E: { // vpkpx (Pack Pixel, AV p219)
17637 /* CAB: Worth a new primop? */
17638 /* Using shifts to compact pixel elements, then packing them */
17639 IRTemp a1 = newTemp(Ity_V128);
17640 IRTemp a2 = newTemp(Ity_V128);
17641 IRTemp a3 = newTemp(Ity_V128);
17642 IRTemp a_tmp = newTemp(Ity_V128);
17643 IRTemp b1 = newTemp(Ity_V128);
17644 IRTemp b2 = newTemp(Ity_V128);
17645 IRTemp b3 = newTemp(Ity_V128);
17646 IRTemp b_tmp = newTemp(Ity_V128);
17647 DIP("vpkpx v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17648 assign( a1, binop(Iop_ShlN16x8,
17649 binop(Iop_ShrN32x4, mkexpr(vA), mkU8(19)),
17650 mkU8(10)) );
17651 assign( a2, binop(Iop_ShlN16x8,
17652 binop(Iop_ShrN16x8, mkexpr(vA), mkU8(11)),
17653 mkU8(5)) );
17654 assign( a3, binop(Iop_ShrN16x8,
17655 binop(Iop_ShlN16x8, mkexpr(vA), mkU8(8)),
17656 mkU8(11)) );
17657 assign( a_tmp, binop(Iop_OrV128, mkexpr(a1),
17658 binop(Iop_OrV128, mkexpr(a2), mkexpr(a3))) );
17659
17660 assign( b1, binop(Iop_ShlN16x8,
17661 binop(Iop_ShrN32x4, mkexpr(vB), mkU8(19)),
17662 mkU8(10)) );
17663 assign( b2, binop(Iop_ShlN16x8,
17664 binop(Iop_ShrN16x8, mkexpr(vB), mkU8(11)),
17665 mkU8(5)) );
17666 assign( b3, binop(Iop_ShrN16x8,
17667 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(8)),
17668 mkU8(11)) );
17669 assign( b_tmp, binop(Iop_OrV128, mkexpr(b1),
17670 binop(Iop_OrV128, mkexpr(b2), mkexpr(b3))) );
17671
17672 putVReg( vD_addr, binop(Iop_NarrowBin32to16x8,
17673 mkexpr(a_tmp), mkexpr(b_tmp)) );
17674 return True;
17675 }
17676
17677 case 0x44E: // vpkudum (Pack Unsigned Double Word Unsigned Modulo)
17678 DIP("vpkudum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17679 putVReg( vD_addr,
17680 binop(Iop_NarrowBin64to32x4, mkexpr(vA), mkexpr(vB)) );
17681 return True;
17682
17683 case 0x4CE: // vpkudus (Pack Unsigned Double Word Unsigned Saturate)
17684 DIP("vpkudus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17685 putVReg( vD_addr,
17686 binop(Iop_QNarrowBin64Uto32Ux4, mkexpr(vA), mkexpr(vB)) );
17687 // TODO: set VSCR[SAT]
17688 return True;
17689
17690 case 0x54E: { // vpksdus (Pack Signed Double Word Unsigned Saturate)
17691 // This insn does a doubled signed->double unsigned saturating conversion
17692 // Conversion done here, then uses unsigned->unsigned vpk insn:
17693 // => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
17694 // This is similar to the technique used for vpkswus, except done
17695 // with double word integers versus word integers.
17696 IRTemp vA_tmp = newTemp(Ity_V128);
17697 IRTemp vB_tmp = newTemp(Ity_V128);
17698 DIP("vpksdus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17699 assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
17700 unop(Iop_NotV128,
17701 binop(Iop_SarN64x2,
17702 mkexpr(vA), mkU8(63)))) );
17703 assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
17704 unop(Iop_NotV128,
17705 binop(Iop_SarN64x2,
17706 mkexpr(vB), mkU8(63)))) );
17707 putVReg( vD_addr, binop(Iop_QNarrowBin64Uto32Ux4,
17708 mkexpr(vA_tmp), mkexpr(vB_tmp)) );
17709 // TODO: set VSCR[SAT]
17710 return True;
17711 }
17712
17713 case 0x5CE: // vpksdss (Pack Signed double word Signed Saturate)
17714 DIP("vpksdss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17715 putVReg( vD_addr,
17716 binop(Iop_QNarrowBin64Sto32Sx4, mkexpr(vA), mkexpr(vB)) );
17717 // TODO: set VSCR[SAT]
17718 return True;
17719 default:
17720 break; // Fall through...
17721 }
17722
17723
17724 if (vA_addr != 0) {
17725 vex_printf("dis_av_pack(ppc)(vA_addr)\n");
17726 return False;
17727 }
17728
17729 signs = newTemp(Ity_V128);
17730 zeros = newTemp(Ity_V128);
17731 assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
17732
17733 switch (opc2) {
17734 /* Unpacking */
17735 case 0x20E: { // vupkhsb (Unpack High Signed B, AV p277)
17736 DIP("vupkhsb v%d,v%d\n", vD_addr, vB_addr);
17737 assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
17738 putVReg( vD_addr,
17739 binop(Iop_InterleaveHI8x16, mkexpr(signs), mkexpr(vB)) );
17740 break;
17741 }
17742 case 0x24E: { // vupkhsh (Unpack High Signed HW, AV p278)
17743 DIP("vupkhsh v%d,v%d\n", vD_addr, vB_addr);
17744 assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
17745 putVReg( vD_addr,
17746 binop(Iop_InterleaveHI16x8, mkexpr(signs), mkexpr(vB)) );
17747 break;
17748 }
17749 case 0x28E: { // vupklsb (Unpack Low Signed B, AV p280)
17750 DIP("vupklsb v%d,v%d\n", vD_addr, vB_addr);
17751 assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
17752 putVReg( vD_addr,
17753 binop(Iop_InterleaveLO8x16, mkexpr(signs), mkexpr(vB)) );
17754 break;
17755 }
17756 case 0x2CE: { // vupklsh (Unpack Low Signed HW, AV p281)
17757 DIP("vupklsh v%d,v%d\n", vD_addr, vB_addr);
17758 assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
17759 putVReg( vD_addr,
17760 binop(Iop_InterleaveLO16x8, mkexpr(signs), mkexpr(vB)) );
17761 break;
17762 }
17763 case 0x34E: { // vupkhpx (Unpack High Pixel16, AV p276)
17764 /* CAB: Worth a new primop? */
17765 /* Using shifts to isolate pixel elements, then expanding them */
17766 IRTemp z0 = newTemp(Ity_V128);
17767 IRTemp z1 = newTemp(Ity_V128);
17768 IRTemp z01 = newTemp(Ity_V128);
17769 IRTemp z2 = newTemp(Ity_V128);
17770 IRTemp z3 = newTemp(Ity_V128);
17771 IRTemp z23 = newTemp(Ity_V128);
17772 DIP("vupkhpx v%d,v%d\n", vD_addr, vB_addr);
17773 assign( z0, binop(Iop_ShlN16x8,
17774 binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
17775 mkU8(8)) );
17776 assign( z1, binop(Iop_ShrN16x8,
17777 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
17778 mkU8(11)) );
17779 assign( z01, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
17780 binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
17781 assign( z2, binop(Iop_ShrN16x8,
17782 binop(Iop_ShlN16x8,
17783 binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
17784 mkU8(11)),
17785 mkU8(3)) );
17786 assign( z3, binop(Iop_ShrN16x8,
17787 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
17788 mkU8(11)) );
17789 assign( z23, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
17790 binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
17791 putVReg( vD_addr,
17792 binop(Iop_OrV128,
17793 binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
17794 mkexpr(z23)) );
17795 break;
17796 }
17797 case 0x3CE: { // vupklpx (Unpack Low Pixel16, AV p279)
17798 /* identical to vupkhpx, except interleaving LO */
17799 IRTemp z0 = newTemp(Ity_V128);
17800 IRTemp z1 = newTemp(Ity_V128);
17801 IRTemp z01 = newTemp(Ity_V128);
17802 IRTemp z2 = newTemp(Ity_V128);
17803 IRTemp z3 = newTemp(Ity_V128);
17804 IRTemp z23 = newTemp(Ity_V128);
17805 DIP("vupklpx v%d,v%d\n", vD_addr, vB_addr);
17806 assign( z0, binop(Iop_ShlN16x8,
17807 binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
17808 mkU8(8)) );
17809 assign( z1, binop(Iop_ShrN16x8,
17810 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
17811 mkU8(11)) );
17812 assign( z01, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
17813 binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
17814 assign( z2, binop(Iop_ShrN16x8,
17815 binop(Iop_ShlN16x8,
17816 binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
17817 mkU8(11)),
17818 mkU8(3)) );
17819 assign( z3, binop(Iop_ShrN16x8,
17820 binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
17821 mkU8(11)) );
17822 assign( z23, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
17823 binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
17824 putVReg( vD_addr,
17825 binop(Iop_OrV128,
17826 binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
17827 mkexpr(z23)) );
17828 break;
17829 }
17830 case 0x64E: { // vupkhsw (Unpack High Signed Word)
17831 DIP("vupkhsw v%d,v%d\n", vD_addr, vB_addr);
17832 assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) );
17833 putVReg( vD_addr,
17834 binop(Iop_InterleaveHI32x4, mkexpr(signs), mkexpr(vB)) );
17835 break;
17836 }
17837 case 0x6CE: { // vupklsw (Unpack Low Signed Word)
17838 DIP("vupklsw v%d,v%d\n", vD_addr, vB_addr);
17839 assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) );
17840 putVReg( vD_addr,
17841 binop(Iop_InterleaveLO32x4, mkexpr(signs), mkexpr(vB)) );
17842 break;
17843 }
17844 default:
17845 vex_printf("dis_av_pack(ppc)(opc2)\n");
17846 return False;
17847 }
17848 return True;
17849 }
17850
17851 /*
17852 AltiVec Cipher Instructions
17853 */
dis_av_cipher(UInt theInstr)17854 static Bool dis_av_cipher ( UInt theInstr )
17855 {
17856 /* VX-Form */
17857 UChar opc1 = ifieldOPC(theInstr);
17858 UChar vD_addr = ifieldRegDS(theInstr);
17859 UChar vA_addr = ifieldRegA(theInstr);
17860 UChar vB_addr = ifieldRegB(theInstr);
17861 UInt opc2 = IFIELD( theInstr, 0, 11 );
17862
17863 IRTemp vA = newTemp(Ity_V128);
17864 IRTemp vB = newTemp(Ity_V128);
17865 assign( vA, getVReg(vA_addr));
17866 assign( vB, getVReg(vB_addr));
17867
17868 if (opc1 != 0x4) {
17869 vex_printf("dis_av_cipher(ppc)(instr)\n");
17870 return False;
17871 }
17872 switch (opc2) {
17873 case 0x508: // vcipher (Vector Inverser Cipher)
17874 DIP("vcipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17875 putVReg( vD_addr,
17876 binop(Iop_CipherV128, mkexpr(vA), mkexpr(vB)) );
17877 return True;
17878
17879 case 0x509: // vcipherlast (Vector Inverser Cipher Last)
17880 DIP("vcipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17881 putVReg( vD_addr,
17882 binop(Iop_CipherLV128, mkexpr(vA), mkexpr(vB)) );
17883 return True;
17884
17885 case 0x548: // vncipher (Vector Inverser Cipher)
17886 DIP("vncipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17887 putVReg( vD_addr,
17888 binop(Iop_NCipherV128, mkexpr(vA), mkexpr(vB)) );
17889 return True;
17890
17891 case 0x549: // vncipherlast (Vector Inverser Cipher Last)
17892 DIP("vncipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17893 putVReg( vD_addr,
17894 binop(Iop_NCipherLV128, mkexpr(vA), mkexpr(vB)) );
17895 return True;
17896
17897 case 0x5C8: /* vsbox (Vector SubBytes, this does the cipher
17898 * subBytes transform)
17899 */
17900 DIP("vsbox v%d,v%d\n", vD_addr, vA_addr);
17901 putVReg( vD_addr,
17902 unop(Iop_CipherSV128, mkexpr(vA) ) );
17903 return True;
17904
17905 default:
17906 vex_printf("dis_av_cipher(ppc)(opc2)\n");
17907 return False;
17908 }
17909 return True;
17910 }
17911
17912 /*
17913 AltiVec Secure Hash Instructions
17914 */
dis_av_hash(UInt theInstr)17915 static Bool dis_av_hash ( UInt theInstr )
17916 {
17917 /* VX-Form */
17918 UChar opc1 = ifieldOPC(theInstr);
17919 UChar vRT_addr = ifieldRegDS(theInstr);
17920 UChar vRA_addr = ifieldRegA(theInstr);
17921 UChar s_field = IFIELD( theInstr, 11, 5 ); // st and six field
17922 UChar st = IFIELD( theInstr, 15, 1 ); // st
17923 UChar six = IFIELD( theInstr, 11, 4 ); // six field
17924 UInt opc2 = IFIELD( theInstr, 0, 11 );
17925
17926 IRTemp vA = newTemp(Ity_V128);
17927 IRTemp dst = newTemp(Ity_V128);
17928 assign( vA, getVReg(vRA_addr));
17929
17930 if (opc1 != 0x4) {
17931 vex_printf("dis_av_hash(ppc)(instr)\n");
17932 return False;
17933 }
17934
17935 switch (opc2) {
17936 case 0x682: // vshasigmaw
17937 DIP("vshasigmaw v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six);
17938 assign( dst, binop( Iop_SHA256, mkexpr( vA ), mkU8( s_field) ) );
17939 putVReg( vRT_addr, mkexpr(dst));
17940 return True;
17941
17942 case 0x6C2: // vshasigmad,
17943 DIP("vshasigmad v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six);
17944 putVReg( vRT_addr, binop( Iop_SHA512, mkexpr( vA ), mkU8( s_field) ) );
17945 return True;
17946
17947 default:
17948 vex_printf("dis_av_hash(ppc)(opc2)\n");
17949 return False;
17950 }
17951 return True;
17952 }
17953
17954 /*
17955 * This function is used by the Vector add/subtract [extended] modulo/carry
17956 * instructions.
17957 * - For the non-extended add instructions, the cin arg is set to zero.
17958 * - For the extended add instructions, cin is the integer value of
17959 * src3.bit[127].
17960 * - For the non-extended subtract instructions, src1 is added to the one's
17961 * complement of src2 + 1. We re-use the cin argument to hold the '1'
17962 * value for this operation.
17963 * - For the extended subtract instructions, cin is the integer value of src3.bit[127].
17964 */
_get_quad_modulo_or_carry(IRExpr * vecA,IRExpr * vecB,IRExpr * cin,Bool modulo)17965 static IRTemp _get_quad_modulo_or_carry(IRExpr * vecA, IRExpr * vecB,
17966 IRExpr * cin, Bool modulo)
17967 {
17968 IRTemp _vecA_32 = IRTemp_INVALID;
17969 IRTemp _vecB_32 = IRTemp_INVALID;
17970 IRTemp res_32 = IRTemp_INVALID;
17971 IRTemp result = IRTemp_INVALID;
17972 IRTemp tmp_result = IRTemp_INVALID;
17973 IRTemp carry = IRTemp_INVALID;
17974 Int i;
17975 IRExpr * _vecA_low64 = unop( Iop_V128to64, vecA );
17976 IRExpr * _vecB_low64 = unop( Iop_V128to64, vecB );
17977 IRExpr * _vecA_high64 = unop( Iop_V128HIto64, vecA );
17978 IRExpr * _vecB_high64 = unop( Iop_V128HIto64, vecB );
17979
17980 for (i = 0; i < 4; i++) {
17981 _vecA_32 = newTemp(Ity_I32);
17982 _vecB_32 = newTemp(Ity_I32);
17983 res_32 = newTemp(Ity_I32);
17984 switch (i) {
17985 case 0:
17986 assign(_vecA_32, unop( Iop_64to32, _vecA_low64 ) );
17987 assign(_vecB_32, unop( Iop_64to32, _vecB_low64 ) );
17988 break;
17989 case 1:
17990 assign(_vecA_32, unop( Iop_64HIto32, _vecA_low64 ) );
17991 assign(_vecB_32, unop( Iop_64HIto32, _vecB_low64 ) );
17992 break;
17993 case 2:
17994 assign(_vecA_32, unop( Iop_64to32, _vecA_high64 ) );
17995 assign(_vecB_32, unop( Iop_64to32, _vecB_high64 ) );
17996 break;
17997 case 3:
17998 assign(_vecA_32, unop( Iop_64HIto32, _vecA_high64 ) );
17999 assign(_vecB_32, unop( Iop_64HIto32, _vecB_high64 ) );
18000 break;
18001 }
18002
18003 assign(res_32, binop( Iop_Add32,
18004 binop( Iop_Add32,
18005 binop ( Iop_Add32,
18006 mkexpr(_vecA_32),
18007 mkexpr(_vecB_32) ),
18008 (i == 0) ? mkU32(0) : mkexpr(carry) ),
18009 (i == 0) ? cin : mkU32(0) ) );
18010 if (modulo) {
18011 result = newTemp(Ity_V128);
18012 assign(result, binop( Iop_OrV128,
18013 (i == 0) ? binop( Iop_64HLtoV128,
18014 mkU64(0),
18015 mkU64(0) ) : mkexpr(tmp_result),
18016 binop( Iop_ShlV128,
18017 binop( Iop_64HLtoV128,
18018 mkU64(0),
18019 binop( Iop_32HLto64,
18020 mkU32(0),
18021 mkexpr(res_32) ) ),
18022 mkU8(i * 32) ) ) );
18023 tmp_result = newTemp(Ity_V128);
18024 assign(tmp_result, mkexpr(result));
18025 }
18026 carry = newTemp(Ity_I32);
18027 assign(carry, unop(Iop_1Uto32, binop( Iop_CmpLT32U,
18028 mkexpr(res_32),
18029 mkexpr(_vecA_32 ) ) ) );
18030 }
18031 if (modulo)
18032 return result;
18033 else
18034 return carry;
18035 }
18036
18037
dis_av_quad(UInt theInstr)18038 static Bool dis_av_quad ( UInt theInstr )
18039 {
18040 /* VX-Form */
18041 UChar opc1 = ifieldOPC(theInstr);
18042 UChar vRT_addr = ifieldRegDS(theInstr);
18043 UChar vRA_addr = ifieldRegA(theInstr);
18044 UChar vRB_addr = ifieldRegB(theInstr);
18045 UChar vRC_addr;
18046 UInt opc2 = IFIELD( theInstr, 0, 11 );
18047
18048 IRTemp vA = newTemp(Ity_V128);
18049 IRTemp vB = newTemp(Ity_V128);
18050 IRTemp vC = IRTemp_INVALID;
18051 IRTemp cin = IRTemp_INVALID;
18052 assign( vA, getVReg(vRA_addr));
18053 assign( vB, getVReg(vRB_addr));
18054
18055 if (opc1 != 0x4) {
18056 vex_printf("dis_av_quad(ppc)(instr)\n");
18057 return False;
18058 }
18059
18060 switch (opc2) {
18061 case 0x140: // vaddcuq
18062 DIP("vaddcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
18063 putVReg( vRT_addr, unop( Iop_32UtoV128,
18064 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
18065 mkexpr(vB),
18066 mkU32(0), False) ) ) );
18067 return True;
18068 case 0x100: // vadduqm
18069 DIP("vadduqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
18070 putVReg( vRT_addr, mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
18071 mkexpr(vB), mkU32(0), True) ) );
18072 return True;
18073 case 0x540: // vsubcuq
18074 DIP("vsubcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
18075 putVReg( vRT_addr,
18076 unop( Iop_32UtoV128,
18077 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
18078 unop( Iop_NotV128,
18079 mkexpr(vB) ),
18080 mkU32(1), False) ) ) );
18081 return True;
18082 case 0x500: // vsubuqm
18083 DIP("vsubuqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
18084 putVReg( vRT_addr,
18085 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
18086 unop( Iop_NotV128, mkexpr(vB) ),
18087 mkU32(1), True) ) );
18088 return True;
18089 case 0x054C: // vbpermq
18090 {
18091 #define BPERMD_IDX_MASK 0x00000000000000FFULL
18092 #define BPERMD_BIT_MASK 0x8000000000000000ULL
18093 int i;
18094 IRExpr * vB_expr = mkexpr(vB);
18095 IRExpr * res = binop(Iop_AndV128, mkV128(0), mkV128(0));
18096 DIP("vbpermq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
18097 for (i = 0; i < 16; i++) {
18098 IRTemp idx_tmp = newTemp( Ity_V128 );
18099 IRTemp perm_bit = newTemp( Ity_V128 );
18100 IRTemp idx = newTemp( Ity_I8 );
18101 IRTemp idx_LT127 = newTemp( Ity_I1 );
18102 IRTemp idx_LT127_ity128 = newTemp( Ity_V128 );
18103
18104 assign( idx_tmp,
18105 binop( Iop_AndV128,
18106 binop( Iop_64HLtoV128,
18107 mkU64(0),
18108 mkU64(BPERMD_IDX_MASK) ),
18109 vB_expr ) );
18110 assign( idx_LT127,
18111 binop( Iop_CmpEQ32,
18112 unop ( Iop_64to32,
18113 unop( Iop_V128to64, binop( Iop_ShrV128,
18114 mkexpr(idx_tmp),
18115 mkU8(7) ) ) ),
18116 mkU32(0) ) );
18117
18118 /* Below, we set idx to determine which bit of vA to use for the
18119 * perm bit. If idx_LT127 is 0, the perm bit is forced to '0'.
18120 */
18121 assign( idx,
18122 binop( Iop_And8,
18123 unop( Iop_1Sto8,
18124 mkexpr(idx_LT127) ),
18125 unop( Iop_32to8,
18126 unop( Iop_V128to32, mkexpr( idx_tmp ) ) ) ) );
18127
18128 assign( idx_LT127_ity128,
18129 binop( Iop_64HLtoV128,
18130 mkU64(0),
18131 unop( Iop_32Uto64,
18132 unop( Iop_1Uto32, mkexpr(idx_LT127 ) ) ) ) );
18133 assign( perm_bit,
18134 binop( Iop_AndV128,
18135 mkexpr( idx_LT127_ity128 ),
18136 binop( Iop_ShrV128,
18137 binop( Iop_AndV128,
18138 binop (Iop_64HLtoV128,
18139 mkU64( BPERMD_BIT_MASK ),
18140 mkU64(0)),
18141 binop( Iop_ShlV128,
18142 mkexpr( vA ),
18143 mkexpr( idx ) ) ),
18144 mkU8( 127 ) ) ) );
18145 res = binop( Iop_OrV128,
18146 res,
18147 binop( Iop_ShlV128,
18148 mkexpr( perm_bit ),
18149 mkU8( i + 64 ) ) );
18150 vB_expr = binop( Iop_ShrV128, vB_expr, mkU8( 8 ) );
18151 }
18152 putVReg( vRT_addr, res);
18153 return True;
18154 #undef BPERMD_IDX_MASK
18155 #undef BPERMD_BIT_MASK
18156 }
18157
18158 default:
18159 break; // fall through
18160 }
18161
18162 opc2 = IFIELD( theInstr, 0, 6 );
18163 vRC_addr = ifieldRegC(theInstr);
18164 vC = newTemp(Ity_V128);
18165 cin = newTemp(Ity_I32);
18166 switch (opc2) {
18167 case 0x3D: // vaddecuq
18168 assign( vC, getVReg(vRC_addr));
18169 DIP("vaddecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
18170 vRC_addr);
18171 assign(cin, binop( Iop_And32,
18172 unop( Iop_64to32,
18173 unop( Iop_V128to64, mkexpr(vC) ) ),
18174 mkU32(1) ) );
18175 putVReg( vRT_addr,
18176 unop( Iop_32UtoV128,
18177 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB),
18178 mkexpr(cin),
18179 False) ) ) );
18180 return True;
18181 case 0x3C: // vaddeuqm
18182 assign( vC, getVReg(vRC_addr));
18183 DIP("vaddeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
18184 vRC_addr);
18185 assign(cin, binop( Iop_And32,
18186 unop( Iop_64to32,
18187 unop( Iop_V128to64, mkexpr(vC) ) ),
18188 mkU32(1) ) );
18189 putVReg( vRT_addr,
18190 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB),
18191 mkexpr(cin),
18192 True) ) );
18193 return True;
18194 case 0x3F: // vsubecuq
18195 assign( vC, getVReg(vRC_addr));
18196 DIP("vsubecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
18197 vRC_addr);
18198 assign(cin, binop( Iop_And32,
18199 unop( Iop_64to32,
18200 unop( Iop_V128to64, mkexpr(vC) ) ),
18201 mkU32(1) ) );
18202 putVReg( vRT_addr,
18203 unop( Iop_32UtoV128,
18204 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
18205 unop( Iop_NotV128,
18206 mkexpr(vB) ),
18207 mkexpr(cin),
18208 False) ) ) );
18209 return True;
18210 case 0x3E: // vsubeuqm
18211 assign( vC, getVReg(vRC_addr));
18212 DIP("vsubeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
18213 vRC_addr);
18214 assign(cin, binop( Iop_And32,
18215 unop( Iop_64to32,
18216 unop( Iop_V128to64, mkexpr(vC) ) ),
18217 mkU32(1) ) );
18218 putVReg( vRT_addr,
18219 mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
18220 unop( Iop_NotV128, mkexpr(vB) ),
18221 mkexpr(cin),
18222 True) ) );
18223 return True;
18224 default:
18225 vex_printf("dis_av_quad(ppc)(opc2.2)\n");
18226 return False;
18227 }
18228
18229 return True;
18230 }
18231
18232
18233 /*
18234 AltiVec BCD Arithmetic instructions.
18235 These instructions modify CR6 for various conditions in the result,
18236 including when an overflow occurs. We could easily detect all conditions
18237 except when an overflow occurs. But since we can't be 100% accurate
18238 in our emulation of CR6, it seems best to just not support it all.
18239 */
dis_av_bcd(UInt theInstr)18240 static Bool dis_av_bcd ( UInt theInstr )
18241 {
18242 /* VX-Form */
18243 UChar opc1 = ifieldOPC(theInstr);
18244 UChar vRT_addr = ifieldRegDS(theInstr);
18245 UChar vRA_addr = ifieldRegA(theInstr);
18246 UChar vRB_addr = ifieldRegB(theInstr);
18247 UChar ps = IFIELD( theInstr, 9, 1 );
18248 UInt opc2 = IFIELD( theInstr, 0, 9 );
18249
18250 IRTemp vA = newTemp(Ity_V128);
18251 IRTemp vB = newTemp(Ity_V128);
18252 IRTemp dst = newTemp(Ity_V128);
18253 assign( vA, getVReg(vRA_addr));
18254 assign( vB, getVReg(vRB_addr));
18255
18256 if (opc1 != 0x4) {
18257 vex_printf("dis_av_bcd(ppc)(instr)\n");
18258 return False;
18259 }
18260
18261 switch (opc2) {
18262 case 0x1: // bcdadd
18263 DIP("bcdadd. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps);
18264 assign( dst, triop( Iop_BCDAdd, mkexpr( vA ),
18265 mkexpr( vB ), mkU8( ps ) ) );
18266 putVReg( vRT_addr, mkexpr(dst));
18267 return True;
18268
18269 case 0x41: // bcdsub
18270 DIP("bcdsub. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps);
18271 assign( dst, triop( Iop_BCDSub, mkexpr( vA ),
18272 mkexpr( vB ), mkU8( ps ) ) );
18273 putVReg( vRT_addr, mkexpr(dst));
18274 return True;
18275
18276 default:
18277 vex_printf("dis_av_bcd(ppc)(opc2)\n");
18278 return False;
18279 }
18280 return True;
18281 }
18282
18283 /*
18284 AltiVec Floating Point Arithmetic Instructions
18285 */
dis_av_fp_arith(UInt theInstr)18286 static Bool dis_av_fp_arith ( UInt theInstr )
18287 {
18288 /* VA-Form */
18289 UChar opc1 = ifieldOPC(theInstr);
18290 UChar vD_addr = ifieldRegDS(theInstr);
18291 UChar vA_addr = ifieldRegA(theInstr);
18292 UChar vB_addr = ifieldRegB(theInstr);
18293 UChar vC_addr = ifieldRegC(theInstr);
18294 UInt opc2=0;
18295
18296 IRTemp vA = newTemp(Ity_V128);
18297 IRTemp vB = newTemp(Ity_V128);
18298 IRTemp vC = newTemp(Ity_V128);
18299 assign( vA, getVReg(vA_addr));
18300 assign( vB, getVReg(vB_addr));
18301 assign( vC, getVReg(vC_addr));
18302
18303 if (opc1 != 0x4) {
18304 vex_printf("dis_av_fp_arith(ppc)(instr)\n");
18305 return False;
18306 }
18307
18308 IRTemp rm = newTemp(Ity_I32);
18309 assign(rm, get_IR_roundingmode());
18310
18311 opc2 = IFIELD( theInstr, 0, 6 );
18312 switch (opc2) {
18313 case 0x2E: // vmaddfp (Multiply Add FP, AV p177)
18314 DIP("vmaddfp v%d,v%d,v%d,v%d\n",
18315 vD_addr, vA_addr, vC_addr, vB_addr);
18316 putVReg( vD_addr,
18317 triop(Iop_Add32Fx4, mkU32(Irrm_NEAREST),
18318 mkexpr(vB),
18319 triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
18320 mkexpr(vA), mkexpr(vC))) );
18321 return True;
18322
18323 case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215)
18324 DIP("vnmsubfp v%d,v%d,v%d,v%d\n",
18325 vD_addr, vA_addr, vC_addr, vB_addr);
18326 putVReg( vD_addr,
18327 triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST),
18328 mkexpr(vB),
18329 triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
18330 mkexpr(vA), mkexpr(vC))) );
18331 return True;
18332 }
18333
18334 default:
18335 break; // Fall through...
18336 }
18337
18338 opc2 = IFIELD( theInstr, 0, 11 );
18339 switch (opc2) {
18340 case 0x00A: // vaddfp (Add FP, AV p137)
18341 DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
18342 putVReg( vD_addr, triop(Iop_Add32Fx4,
18343 mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) );
18344 return True;
18345
18346 case 0x04A: // vsubfp (Subtract FP, AV p261)
18347 DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
18348 putVReg( vD_addr, triop(Iop_Sub32Fx4,
18349 mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) );
18350 return True;
18351
18352 case 0x40A: // vmaxfp (Maximum FP, AV p178)
18353 DIP("vmaxfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
18354 putVReg( vD_addr, binop(Iop_Max32Fx4, mkexpr(vA), mkexpr(vB)) );
18355 return True;
18356
18357 case 0x44A: // vminfp (Minimum FP, AV p187)
18358 DIP("vminfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
18359 putVReg( vD_addr, binop(Iop_Min32Fx4, mkexpr(vA), mkexpr(vB)) );
18360 return True;
18361
18362 default:
18363 break; // Fall through...
18364 }
18365
18366
18367 if (vA_addr != 0) {
18368 vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n");
18369 return False;
18370 }
18371
18372 switch (opc2) {
18373 case 0x10A: // vrefp (Reciprocal Esimate FP, AV p228)
18374 DIP("vrefp v%d,v%d\n", vD_addr, vB_addr);
18375 putVReg( vD_addr, unop(Iop_RecipEst32Fx4, mkexpr(vB)) );
18376 return True;
18377
18378 case 0x14A: // vrsqrtefp (Reciprocal Sqrt Estimate FP, AV p237)
18379 DIP("vrsqrtefp v%d,v%d\n", vD_addr, vB_addr);
18380 putVReg( vD_addr, unop(Iop_RSqrtEst32Fx4, mkexpr(vB)) );
18381 return True;
18382
18383 case 0x18A: // vexptefp (2 Raised to the Exp Est FP, AV p173)
18384 DIP("vexptefp v%d,v%d\n", vD_addr, vB_addr);
18385 DIP(" => not implemented\n");
18386 return False;
18387
18388 case 0x1CA: // vlogefp (Log2 Estimate FP, AV p175)
18389 DIP("vlogefp v%d,v%d\n", vD_addr, vB_addr);
18390 DIP(" => not implemented\n");
18391 return False;
18392
18393 default:
18394 vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2);
18395 return False;
18396 }
18397 return True;
18398 }
18399
18400 /*
18401 AltiVec Floating Point Compare Instructions
18402 */
dis_av_fp_cmp(UInt theInstr)18403 static Bool dis_av_fp_cmp ( UInt theInstr )
18404 {
18405 /* VXR-Form */
18406 UChar opc1 = ifieldOPC(theInstr);
18407 UChar vD_addr = ifieldRegDS(theInstr);
18408 UChar vA_addr = ifieldRegA(theInstr);
18409 UChar vB_addr = ifieldRegB(theInstr);
18410 UChar flag_rC = ifieldBIT10(theInstr);
18411 UInt opc2 = IFIELD( theInstr, 0, 10 );
18412
18413 Bool cmp_bounds = False;
18414
18415 IRTemp vA = newTemp(Ity_V128);
18416 IRTemp vB = newTemp(Ity_V128);
18417 IRTemp vD = newTemp(Ity_V128);
18418 assign( vA, getVReg(vA_addr));
18419 assign( vB, getVReg(vB_addr));
18420
18421 if (opc1 != 0x4) {
18422 vex_printf("dis_av_fp_cmp(ppc)(instr)\n");
18423 return False;
18424 }
18425
18426 switch (opc2) {
18427 case 0x0C6: // vcmpeqfp (Compare Equal-to FP, AV p159)
18428 DIP("vcmpeqfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
18429 vD_addr, vA_addr, vB_addr);
18430 assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
18431 break;
18432
18433 case 0x1C6: // vcmpgefp (Compare Greater-than-or-Equal-to, AV p163)
18434 DIP("vcmpgefp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
18435 vD_addr, vA_addr, vB_addr);
18436 assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
18437 break;
18438
18439 case 0x2C6: // vcmpgtfp (Compare Greater-than FP, AV p164)
18440 DIP("vcmpgtfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
18441 vD_addr, vA_addr, vB_addr);
18442 assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
18443 break;
18444
18445 case 0x3C6: { // vcmpbfp (Compare Bounds FP, AV p157)
18446 IRTemp gt = newTemp(Ity_V128);
18447 IRTemp lt = newTemp(Ity_V128);
18448 IRTemp zeros = newTemp(Ity_V128);
18449 DIP("vcmpbfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
18450 vD_addr, vA_addr, vB_addr);
18451 cmp_bounds = True;
18452 assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
18453
18454 /* Note: making use of fact that the ppc backend for compare insns
18455 return zero'd lanes if either of the corresponding arg lanes is
18456 a nan.
18457
18458 Perhaps better to have an irop Iop_isNan32Fx4, but then we'd
18459 need this for the other compares too (vcmpeqfp etc)...
18460 Better still, tighten down the spec for compare irops.
18461 */
18462 assign( gt, unop(Iop_NotV128,
18463 binop(Iop_CmpLE32Fx4, mkexpr(vA), mkexpr(vB))) );
18464 assign( lt, unop(Iop_NotV128,
18465 binop(Iop_CmpGE32Fx4, mkexpr(vA),
18466 triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST),
18467 mkexpr(zeros),
18468 mkexpr(vB)))) );
18469
18470 // finally, just shift gt,lt to correct position
18471 assign( vD, binop(Iop_ShlN32x4,
18472 binop(Iop_OrV128,
18473 binop(Iop_AndV128, mkexpr(gt),
18474 unop(Iop_Dup32x4, mkU32(0x2))),
18475 binop(Iop_AndV128, mkexpr(lt),
18476 unop(Iop_Dup32x4, mkU32(0x1)))),
18477 mkU8(30)) );
18478 break;
18479 }
18480
18481 default:
18482 vex_printf("dis_av_fp_cmp(ppc)(opc2)\n");
18483 return False;
18484 }
18485
18486 putVReg( vD_addr, mkexpr(vD) );
18487
18488 if (flag_rC) {
18489 set_AV_CR6( mkexpr(vD), !cmp_bounds );
18490 }
18491 return True;
18492 }
18493
18494 /*
18495 AltiVec Floating Point Convert/Round Instructions
18496 */
dis_av_fp_convert(UInt theInstr)18497 static Bool dis_av_fp_convert ( UInt theInstr )
18498 {
18499 /* VX-Form */
18500 UChar opc1 = ifieldOPC(theInstr);
18501 UChar vD_addr = ifieldRegDS(theInstr);
18502 UChar UIMM_5 = ifieldRegA(theInstr);
18503 UChar vB_addr = ifieldRegB(theInstr);
18504 UInt opc2 = IFIELD( theInstr, 0, 11 );
18505
18506 IRTemp vB = newTemp(Ity_V128);
18507 IRTemp vScale = newTemp(Ity_V128);
18508 IRTemp vInvScale = newTemp(Ity_V128);
18509
18510 float scale, inv_scale;
18511
18512 assign( vB, getVReg(vB_addr));
18513
18514 /* scale = 2^UIMM, cast to float, reinterpreted as uint */
18515 scale = (float)( (unsigned int) 1<<UIMM_5 );
18516 assign( vScale, unop(Iop_Dup32x4, mkU32( float_to_bits(scale) )) );
18517 inv_scale = 1/scale;
18518 assign( vInvScale,
18519 unop(Iop_Dup32x4, mkU32( float_to_bits(inv_scale) )) );
18520
18521 if (opc1 != 0x4) {
18522 vex_printf("dis_av_fp_convert(ppc)(instr)\n");
18523 return False;
18524 }
18525
18526 switch (opc2) {
18527 case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156)
18528 DIP("vcfux v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
18529 putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
18530 unop(Iop_I32UtoFx4, mkexpr(vB)),
18531 mkexpr(vInvScale)) );
18532 return True;
18533
18534 case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155)
18535 DIP("vcfsx v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
18536
18537 putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
18538 unop(Iop_I32StoFx4, mkexpr(vB)),
18539 mkexpr(vInvScale)) );
18540 return True;
18541
18542 case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172)
18543 DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
18544 putVReg( vD_addr,
18545 unop(Iop_QFtoI32Ux4_RZ,
18546 triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
18547 mkexpr(vB), mkexpr(vScale))) );
18548 return True;
18549
18550 case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171)
18551 DIP("vctsxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
18552 putVReg( vD_addr,
18553 unop(Iop_QFtoI32Sx4_RZ,
18554 triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
18555 mkexpr(vB), mkexpr(vScale))) );
18556 return True;
18557
18558 default:
18559 break; // Fall through...
18560 }
18561
18562 if (UIMM_5 != 0) {
18563 vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n");
18564 return False;
18565 }
18566
18567 switch (opc2) {
18568 case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231)
18569 DIP("vrfin v%d,v%d\n", vD_addr, vB_addr);
18570 putVReg( vD_addr, unop(Iop_RoundF32x4_RN, mkexpr(vB)) );
18571 break;
18572
18573 case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233)
18574 DIP("vrfiz v%d,v%d\n", vD_addr, vB_addr);
18575 putVReg( vD_addr, unop(Iop_RoundF32x4_RZ, mkexpr(vB)) );
18576 break;
18577
18578 case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232)
18579 DIP("vrfip v%d,v%d\n", vD_addr, vB_addr);
18580 putVReg( vD_addr, unop(Iop_RoundF32x4_RP, mkexpr(vB)) );
18581 break;
18582
18583 case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230)
18584 DIP("vrfim v%d,v%d\n", vD_addr, vB_addr);
18585 putVReg( vD_addr, unop(Iop_RoundF32x4_RM, mkexpr(vB)) );
18586 break;
18587
18588 default:
18589 vex_printf("dis_av_fp_convert(ppc)(opc2)\n");
18590 return False;
18591 }
18592 return True;
18593 }
18594
dis_transactional_memory(UInt theInstr,UInt nextInstr,const VexAbiInfo * vbi,DisResult * dres,Bool (* resteerOkFn)(void *,Addr),void * callback_opaque)18595 static Bool dis_transactional_memory ( UInt theInstr, UInt nextInstr,
18596 const VexAbiInfo* vbi,
18597 /*OUT*/DisResult* dres,
18598 Bool (*resteerOkFn)(void*,Addr),
18599 void* callback_opaque )
18600 {
18601 UInt opc2 = IFIELD( theInstr, 1, 10 );
18602
18603 switch (opc2) {
18604 case 0x28E: { //tbegin.
18605 /* The current implementation is to just fail the tbegin and execute
18606 * the failure path. The failure path is assumed to be functionaly
18607 * equivalent to the transactional path with the needed data locking
18608 * to ensure correctness. The tend is just a noop and shouldn't
18609 * actually get executed.
18610 * 1) set cr0 to 0x2
18611 * 2) Initialize TFHAR to CIA+4
18612 * 3) Initialize TEXASR
18613 * 4) Initialize TFIAR (probably to CIA, ie, the address of tbegin.)
18614 * 5) Continue executing at the next instruction.
18615 */
18616 UInt R = IFIELD( theInstr, 21, 1 );
18617
18618 ULong tm_reason;
18619 UInt failure_code = 0; /* Forcing failure, will not be due to tabort
18620 * or treclaim.
18621 */
18622 UInt persistant = 1; /* set persistant since we are always failing
18623 * the tbegin.
18624 */
18625 UInt nest_overflow = 1; /* Alowed nesting depth overflow, we use this
18626 as the reason for failing the trasaction */
18627 UInt tm_exact = 1; /* have exact address for failure */
18628
18629 DIP("tbegin. %u\n", R);
18630
18631 /* Set the CR0 field to indicate the tbegin failed. Then let
18632 * the code do the branch to the failure path.
18633 *
18634 * 000 || 0 Transaction initiation successful,
18635 * unnested (Transaction state of
18636 * Non-transactional prior to tbegin.)
18637 * 010 || 0 Transaction initiation successful, nested
18638 * (Transaction state of Transactional
18639 * prior to tbegin.)
18640 * 001 || 0 Transaction initiation unsuccessful,
18641 * (Transaction state of Suspended prior
18642 * to tbegin.)
18643 */
18644 putCR321( 0, mkU8( 0x2 ) );
18645
18646 tm_reason = generate_TMreason( failure_code, persistant,
18647 nest_overflow, tm_exact );
18648
18649 storeTMfailure( guest_CIA_curr_instr, tm_reason,
18650 guest_CIA_curr_instr+4 );
18651
18652 return True;
18653
18654 break;
18655 }
18656
18657 case 0x2AE: { //tend.
18658 /* The tend. is just a noop. Do nothing */
18659 UInt A = IFIELD( theInstr, 25, 1 );
18660
18661 DIP("tend. %u\n", A);
18662 break;
18663 }
18664
18665 case 0x2EE: { //tsr.
18666 /* The tsr. is just a noop. Do nothing */
18667 UInt L = IFIELD( theInstr, 21, 1 );
18668
18669 DIP("tsr. %u\n", L);
18670 break;
18671 }
18672
18673 case 0x2CE: { //tcheck.
18674 /* The tcheck. is just a noop. Do nothing */
18675 UInt BF = IFIELD( theInstr, 25, 1 );
18676
18677 DIP("tcheck. %u\n", BF);
18678 break;
18679 }
18680
18681 case 0x30E: { //tbortwc.
18682 /* The tabortwc. is just a noop. Do nothing */
18683 UInt TO = IFIELD( theInstr, 25, 1 );
18684 UInt RA = IFIELD( theInstr, 16, 5 );
18685 UInt RB = IFIELD( theInstr, 11, 5 );
18686
18687 DIP("tabortwc. %u,%u,%u\n", TO, RA, RB);
18688 break;
18689 }
18690
18691 case 0x32E: { //tbortdc.
18692 /* The tabortdc. is just a noop. Do nothing */
18693 UInt TO = IFIELD( theInstr, 25, 1 );
18694 UInt RA = IFIELD( theInstr, 16, 5 );
18695 UInt RB = IFIELD( theInstr, 11, 5 );
18696
18697 DIP("tabortdc. %u,%u,%u\n", TO, RA, RB);
18698 break;
18699 }
18700
18701 case 0x34E: { //tbortwci.
18702 /* The tabortwci. is just a noop. Do nothing */
18703 UInt TO = IFIELD( theInstr, 25, 1 );
18704 UInt RA = IFIELD( theInstr, 16, 5 );
18705 UInt SI = IFIELD( theInstr, 11, 5 );
18706
18707 DIP("tabortwci. %u,%u,%u\n", TO, RA, SI);
18708 break;
18709 }
18710
18711 case 0x36E: { //tbortdci.
18712 /* The tabortdci. is just a noop. Do nothing */
18713 UInt TO = IFIELD( theInstr, 25, 1 );
18714 UInt RA = IFIELD( theInstr, 16, 5 );
18715 UInt SI = IFIELD( theInstr, 11, 5 );
18716
18717 DIP("tabortdci. %u,%u,%u\n", TO, RA, SI);
18718 break;
18719 }
18720
18721 case 0x38E: { //tbort.
18722 /* The tabort. is just a noop. Do nothing */
18723 UInt RA = IFIELD( theInstr, 16, 5 );
18724
18725 DIP("tabort. %u\n", RA);
18726 break;
18727 }
18728
18729 case 0x3AE: { //treclaim.
18730 /* The treclaim. is just a noop. Do nothing */
18731 UInt RA = IFIELD( theInstr, 16, 5 );
18732
18733 DIP("treclaim. %u\n", RA);
18734 break;
18735 }
18736
18737 case 0x3EE: { //trechkpt.
18738 /* The trechkpt. is just a noop. Do nothing */
18739 DIP("trechkpt.\n");
18740 break;
18741 }
18742
18743 default:
18744 vex_printf("dis_transactional_memory(ppc): unrecognized instruction\n");
18745 return False;
18746 }
18747
18748 return True;
18749 }
18750
18751
18752 /* The 0x3C primary opcode (VSX category) uses several different forms of
18753 * extended opcodes:
18754 * o XX2-form:
18755 * - [10:2] (IBM notation [21:29])
18756 * o XX3-form variants:
18757 * - variant 1: [10:3] (IBM notation [21:28])
18758 * - variant 2: [9:3] (IBM notation [22:28])
18759 * - variant 3: [7:3] (IBM notation [24:28])
18760 * o XX-4 form:
18761 * - [10:6] (IBM notation [21:25])
18762 *
18763 * The XX2-form needs bit 0 masked from the standard extended opcode
18764 * as returned by ifieldOPClo10; the XX3-form needs bits 0 and 1 masked;
18765 * and the XX4-form needs bits 0, 1, and 2 masked. Additionally, the
18766 * XX4 and XX3 (variants 2 and 3) forms need certain bits masked on the
18767 * front end since their encoding does not begin at bit 21 like the standard
18768 * format.
18769 *
18770 * The get_VSX60_opc2() function uses the vsx_insn array below to obtain the
18771 * secondary opcode for such VSX instructions.
18772 *
18773 */
18774
18775
18776 struct vsx_insn {
18777 UInt opcode;
18778 const HChar * name;
18779 };
18780
18781 // ATTENTION: Keep this array sorted on the opcocde!!!
18782 static struct vsx_insn vsx_all[] = {
18783 { 0x0, "xsaddsp" },
18784 { 0x4, "xsmaddasp" },
18785 { 0x8, "xxsldwi" },
18786 { 0x14, "xsrsqrtesp" },
18787 { 0x16, "xssqrtsp" },
18788 { 0x18, "xxsel" },
18789 { 0x20, "xssubsp" },
18790 { 0x24, "xsmaddmsp" },
18791 { 0x28, "xxpermdi" },
18792 { 0x34, "xsresp" },
18793 { 0x40, "xsmulsp" },
18794 { 0x44, "xsmsubasp" },
18795 { 0x48, "xxmrghw" },
18796 { 0x60, "xsdivsp" },
18797 { 0x64, "xsmsubmsp" },
18798 { 0x80, "xsadddp" },
18799 { 0x84, "xsmaddadp" },
18800 { 0x8c, "xscmpudp" },
18801 { 0x90, "xscvdpuxws" },
18802 { 0x92, "xsrdpi" },
18803 { 0x94, "xsrsqrtedp" },
18804 { 0x96, "xssqrtdp" },
18805 { 0xa0, "xssubdp" },
18806 { 0xa4, "xsmaddmdp" },
18807 { 0xac, "xscmpodp" },
18808 { 0xb0, "xscvdpsxws" },
18809 { 0xb2, "xsrdpiz" },
18810 { 0xb4, "xsredp" },
18811 { 0xc0, "xsmuldp" },
18812 { 0xc4, "xsmsubadp" },
18813 { 0xc8, "xxmrglw" },
18814 { 0xd2, "xsrdpip" },
18815 { 0xd4, "xstsqrtdp" },
18816 { 0xd6, "xsrdpic" },
18817 { 0xe0, "xsdivdp" },
18818 { 0xe4, "xsmsubmdp" },
18819 { 0xf2, "xsrdpim" },
18820 { 0xf4, "xstdivdp" },
18821 { 0x100, "xvaddsp" },
18822 { 0x104, "xvmaddasp" },
18823 { 0x10c, "xvcmpeqsp" },
18824 { 0x110, "xvcvspuxws" },
18825 { 0x112, "xvrspi" },
18826 { 0x114, "xvrsqrtesp" },
18827 { 0x116, "xvsqrtsp" },
18828 { 0x120, "xvsubsp" },
18829 { 0x124, "xvmaddmsp" },
18830 { 0x12c, "xvcmpgtsp" },
18831 { 0x130, "xvcvspsxws" },
18832 { 0x132, "xvrspiz" },
18833 { 0x134, "xvresp" },
18834 { 0x140, "xvmulsp" },
18835 { 0x144, "xvmsubasp" },
18836 { 0x148, "xxspltw" },
18837 { 0x14c, "xvcmpgesp" },
18838 { 0x150, "xvcvuxwsp" },
18839 { 0x152, "xvrspip" },
18840 { 0x154, "xvtsqrtsp" },
18841 { 0x156, "xvrspic" },
18842 { 0x160, "xvdivsp" },
18843 { 0x164, "xvmsubmsp" },
18844 { 0x170, "xvcvsxwsp" },
18845 { 0x172, "xvrspim" },
18846 { 0x174, "xvtdivsp" },
18847 { 0x180, "xvadddp" },
18848 { 0x184, "xvmaddadp" },
18849 { 0x18c, "xvcmpeqdp" },
18850 { 0x190, "xvcvdpuxws" },
18851 { 0x192, "xvrdpi" },
18852 { 0x194, "xvrsqrtedp" },
18853 { 0x196, "xvsqrtdp" },
18854 { 0x1a0, "xvsubdp" },
18855 { 0x1a4, "xvmaddmdp" },
18856 { 0x1ac, "xvcmpgtdp" },
18857 { 0x1b0, "xvcvdpsxws" },
18858 { 0x1b2, "xvrdpiz" },
18859 { 0x1b4, "xvredp" },
18860 { 0x1c0, "xvmuldp" },
18861 { 0x1c4, "xvmsubadp" },
18862 { 0x1cc, "xvcmpgedp" },
18863 { 0x1d0, "xvcvuxwdp" },
18864 { 0x1d2, "xvrdpip" },
18865 { 0x1d4, "xvtsqrtdp" },
18866 { 0x1d6, "xvrdpic" },
18867 { 0x1e0, "xvdivdp" },
18868 { 0x1e4, "xvmsubmdp" },
18869 { 0x1f0, "xvcvsxwdp" },
18870 { 0x1f2, "xvrdpim" },
18871 { 0x1f4, "xvtdivdp" },
18872 { 0x204, "xsnmaddasp" },
18873 { 0x208, "xxland" },
18874 { 0x212, "xscvdpsp" },
18875 { 0x216, "xscvdpspn" },
18876 { 0x224, "xsnmaddmsp" },
18877 { 0x228, "xxlandc" },
18878 { 0x232, "xxrsp" },
18879 { 0x244, "xsnmsubasp" },
18880 { 0x248, "xxlor" },
18881 { 0x250, "xscvuxdsp" },
18882 { 0x264, "xsnmsubmsp" },
18883 { 0x268, "xxlxor" },
18884 { 0x270, "xscvsxdsp" },
18885 { 0x280, "xsmaxdp" },
18886 { 0x284, "xsnmaddadp" },
18887 { 0x288, "xxlnor" },
18888 { 0x290, "xscvdpuxds" },
18889 { 0x292, "xscvspdp" },
18890 { 0x296, "xscvspdpn" },
18891 { 0x2a0, "xsmindp" },
18892 { 0x2a4, "xsnmaddmdp" },
18893 { 0x2a8, "xxlorc" },
18894 { 0x2b0, "xscvdpsxds" },
18895 { 0x2b2, "xsabsdp" },
18896 { 0x2c0, "xscpsgndp" },
18897 { 0x2c4, "xsnmsubadp" },
18898 { 0x2c8, "xxlnand" },
18899 { 0x2d0, "xscvuxddp" },
18900 { 0x2d2, "xsnabsdp" },
18901 { 0x2e4, "xsnmsubmdp" },
18902 { 0x2e8, "xxleqv" },
18903 { 0x2f0, "xscvsxddp" },
18904 { 0x2f2, "xsnegdp" },
18905 { 0x300, "xvmaxsp" },
18906 { 0x304, "xvnmaddasp" },
18907 { 0x30c, "xvcmpeqsp." },
18908 { 0x310, "xvcvspuxds" },
18909 { 0x312, "xvcvdpsp" },
18910 { 0x320, "xvminsp" },
18911 { 0x324, "xvnmaddmsp" },
18912 { 0x32c, "xvcmpgtsp." },
18913 { 0x330, "xvcvspsxds" },
18914 { 0x332, "xvabssp" },
18915 { 0x340, "xvcpsgnsp" },
18916 { 0x344, "xvnmsubasp" },
18917 { 0x34c, "xvcmpgesp." },
18918 { 0x350, "xvcvuxdsp" },
18919 { 0x352, "xvnabssp" },
18920 { 0x364, "xvnmsubmsp" },
18921 { 0x370, "xvcvsxdsp" },
18922 { 0x372, "xvnegsp" },
18923 { 0x380, "xvmaxdp" },
18924 { 0x384, "xvnmaddadp" },
18925 { 0x38c, "xvcmpeqdp." },
18926 { 0x390, "xvcvdpuxds" },
18927 { 0x392, "xvcvspdp" },
18928 { 0x3a0, "xvmindp" },
18929 { 0x3a4, "xvnmaddmdp" },
18930 { 0x3ac, "xvcmpgtdp." },
18931 { 0x3b0, "xvcvdpsxds" },
18932 { 0x3b2, "xvabsdp" },
18933 { 0x3c0, "xvcpsgndp" },
18934 { 0x3c4, "xvnmsubadp" },
18935 { 0x3cc, "xvcmpgedp." },
18936 { 0x3d0, "xvcvuxddp" },
18937 { 0x3d2, "xvnabsdp" },
18938 { 0x3e4, "xvnmsubmdp" },
18939 { 0x3f0, "xvcvsxddp" },
18940 { 0x3f2, "xvnegdp" }
18941 };
18942 #define VSX_ALL_LEN (sizeof vsx_all / sizeof *vsx_all)
18943
18944
18945 // ATTENTION: This search function assumes vsx_all array is sorted.
findVSXextOpCode(UInt opcode)18946 static Int findVSXextOpCode(UInt opcode)
18947 {
18948 Int low, mid, high;
18949 low = 0;
18950 high = VSX_ALL_LEN - 1;
18951 while (low <= high) {
18952 mid = (low + high)/2;
18953 if (opcode < vsx_all[mid].opcode)
18954 high = mid - 1;
18955 else if (opcode > vsx_all[mid].opcode)
18956 low = mid + 1;
18957 else
18958 return mid;
18959 }
18960 return -1;
18961 }
18962
18963
18964 /* The full 10-bit extended opcode retrieved via ifieldOPClo10 is
18965 * passed, and we then try to match it up with one of the VSX forms
18966 * below.
18967 */
get_VSX60_opc2(UInt opc2_full)18968 static UInt get_VSX60_opc2(UInt opc2_full)
18969 {
18970 #define XX2_MASK 0x000003FE
18971 #define XX3_1_MASK 0x000003FC
18972 #define XX3_2_MASK 0x000001FC
18973 #define XX3_3_MASK 0x0000007C
18974 #define XX4_MASK 0x00000018
18975 Int ret;
18976 UInt vsxExtOpcode = 0;
18977
18978 if (( ret = findVSXextOpCode(opc2_full & XX2_MASK)) >= 0)
18979 vsxExtOpcode = vsx_all[ret].opcode;
18980 else if (( ret = findVSXextOpCode(opc2_full & XX3_1_MASK)) >= 0)
18981 vsxExtOpcode = vsx_all[ret].opcode;
18982 else if (( ret = findVSXextOpCode(opc2_full & XX3_2_MASK)) >= 0)
18983 vsxExtOpcode = vsx_all[ret].opcode;
18984 else if (( ret = findVSXextOpCode(opc2_full & XX3_3_MASK)) >= 0)
18985 vsxExtOpcode = vsx_all[ret].opcode;
18986 else if (( ret = findVSXextOpCode(opc2_full & XX4_MASK)) >= 0)
18987 vsxExtOpcode = vsx_all[ret].opcode;
18988
18989 return vsxExtOpcode;
18990 }
18991
18992 /*------------------------------------------------------------*/
18993 /*--- Disassemble a single instruction ---*/
18994 /*------------------------------------------------------------*/
18995
18996 /* Disassemble a single instruction into IR. The instruction
18997 is located in host memory at &guest_code[delta]. */
18998
18999 static
disInstr_PPC_WRK(Bool (* resteerOkFn)(void *,Addr),Bool resteerCisOk,void * callback_opaque,Long delta64,const VexArchInfo * archinfo,const VexAbiInfo * abiinfo,Bool sigill_diag)19000 DisResult disInstr_PPC_WRK (
19001 Bool (*resteerOkFn) ( /*opaque*/void*, Addr ),
19002 Bool resteerCisOk,
19003 void* callback_opaque,
19004 Long delta64,
19005 const VexArchInfo* archinfo,
19006 const VexAbiInfo* abiinfo,
19007 Bool sigill_diag
19008 )
19009 {
19010 UChar opc1;
19011 UInt opc2;
19012 DisResult dres;
19013 UInt theInstr;
19014 IRType ty = mode64 ? Ity_I64 : Ity_I32;
19015 Bool allow_F = False;
19016 Bool allow_V = False;
19017 Bool allow_FX = False;
19018 Bool allow_GX = False;
19019 Bool allow_VX = False; // Equates to "supports Power ISA 2.06
19020 Bool allow_DFP = False;
19021 Bool allow_isa_2_07 = False;
19022 UInt hwcaps = archinfo->hwcaps;
19023 Long delta;
19024
19025 /* What insn variants are we supporting today? */
19026 if (mode64) {
19027 allow_F = True;
19028 allow_V = (0 != (hwcaps & VEX_HWCAPS_PPC64_V));
19029 allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC64_FX));
19030 allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC64_GX));
19031 allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC64_VX));
19032 allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC64_DFP));
19033 allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC64_ISA2_07));
19034 } else {
19035 allow_F = (0 != (hwcaps & VEX_HWCAPS_PPC32_F));
19036 allow_V = (0 != (hwcaps & VEX_HWCAPS_PPC32_V));
19037 allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC32_FX));
19038 allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC32_GX));
19039 allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC32_VX));
19040 allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC32_DFP));
19041 allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC32_ISA2_07));
19042 }
19043
19044 /* The running delta */
19045 delta = (Long)mkSzAddr(ty, (ULong)delta64);
19046
19047 /* Set result defaults. */
19048 dres.whatNext = Dis_Continue;
19049 dres.len = 0;
19050 dres.continueAt = 0;
19051 dres.jk_StopHere = Ijk_INVALID;
19052
19053 /* At least this is simple on PPC32: insns are all 4 bytes long, and
19054 4-aligned. So just fish the whole thing out of memory right now
19055 and have done. */
19056 theInstr = getUIntPPCendianly( &guest_code[delta] );
19057
19058 if (0) vex_printf("insn: 0x%x\n", theInstr);
19059
19060 DIP("\t0x%llx: ", (ULong)guest_CIA_curr_instr);
19061
19062 /* Spot "Special" instructions (see comment at top of file). */
19063 {
19064 const UChar* code = guest_code + delta;
19065 /* Spot the 16-byte preamble:
19066 32-bit mode:
19067 5400183E rlwinm 0,0,3,0,31
19068 5400683E rlwinm 0,0,13,0,31
19069 5400E83E rlwinm 0,0,29,0,31
19070 5400983E rlwinm 0,0,19,0,31
19071 64-bit mode:
19072 78001800 rotldi 0,0,3
19073 78006800 rotldi 0,0,13
19074 7800E802 rotldi 0,0,61
19075 78009802 rotldi 0,0,51
19076 */
19077 UInt word1 = mode64 ? 0x78001800 : 0x5400183E;
19078 UInt word2 = mode64 ? 0x78006800 : 0x5400683E;
19079 UInt word3 = mode64 ? 0x7800E802 : 0x5400E83E;
19080 UInt word4 = mode64 ? 0x78009802 : 0x5400983E;
19081 Bool is_special_preamble = False;
19082 if (getUIntPPCendianly(code+ 0) == word1 &&
19083 getUIntPPCendianly(code+ 4) == word2 &&
19084 getUIntPPCendianly(code+ 8) == word3 &&
19085 getUIntPPCendianly(code+12) == word4) {
19086 is_special_preamble = True;
19087 } else if (! mode64 &&
19088 getUIntPPCendianly(code+ 0) == 0x54001800 &&
19089 getUIntPPCendianly(code+ 4) == 0x54006800 &&
19090 getUIntPPCendianly(code+ 8) == 0x5400E800 &&
19091 getUIntPPCendianly(code+12) == 0x54009800) {
19092 static Bool reported = False;
19093 if (!reported) {
19094 vex_printf("disInstr(ppc): old ppc32 instruction magic detected. Code might clobber r0.\n");
19095 vex_printf("disInstr(ppc): source needs to be recompiled against latest valgrind.h.\n");
19096 reported = True;
19097 }
19098 is_special_preamble = True;
19099 }
19100 if (is_special_preamble) {
19101 /* Got a "Special" instruction preamble. Which one is it? */
19102 if (getUIntPPCendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) {
19103 /* %R3 = client_request ( %R4 ) */
19104 DIP("r3 = client_request ( %%r4 )\n");
19105 delta += 20;
19106 putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta ));
19107 dres.jk_StopHere = Ijk_ClientReq;
19108 dres.whatNext = Dis_StopHere;
19109 goto decode_success;
19110 }
19111 else
19112 if (getUIntPPCendianly(code+16) == 0x7C421378 /* or 2,2,2 */) {
19113 /* %R3 = guest_NRADDR */
19114 DIP("r3 = guest_NRADDR\n");
19115 delta += 20;
19116 dres.len = 20;
19117 putIReg(3, IRExpr_Get( OFFB_NRADDR, ty ));
19118 goto decode_success;
19119 }
19120 else
19121 if (getUIntPPCendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) {
19122 delta += 20;
19123 if (host_endness == VexEndnessLE) {
19124 /* branch-and-link-to-noredir %R12 */
19125 DIP("branch-and-link-to-noredir r12\n");
19126 putGST( PPC_GST_LR,
19127 mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
19128 putGST( PPC_GST_CIA, getIReg(12));
19129 } else {
19130 /* branch-and-link-to-noredir %R11 */
19131 DIP("branch-and-link-to-noredir r11\n");
19132 putGST( PPC_GST_LR,
19133 mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
19134 putGST( PPC_GST_CIA, getIReg(11));
19135 }
19136 dres.jk_StopHere = Ijk_NoRedir;
19137 dres.whatNext = Dis_StopHere;
19138 goto decode_success;
19139 }
19140 else
19141 if (getUIntPPCendianly(code+16) == 0x7C842378 /* or 4,4,4 */) {
19142 /* %R3 = guest_NRADDR_GPR2 */
19143 DIP("r3 = guest_NRADDR_GPR2\n");
19144 delta += 20;
19145 dres.len = 20;
19146 putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty ));
19147 goto decode_success;
19148 }
19149 else
19150 if (getUIntPPCendianly(code+16) == 0x7CA52B78 /* or 5,5,5 */) {
19151 DIP("IR injection\n");
19152 if (host_endness == VexEndnessBE)
19153 vex_inject_ir(irsb, Iend_BE);
19154 else
19155 vex_inject_ir(irsb, Iend_LE);
19156
19157 delta += 20;
19158 dres.len = 20;
19159
19160 // Invalidate the current insn. The reason is that the IRop we're
19161 // injecting here can change. In which case the translation has to
19162 // be redone. For ease of handling, we simply invalidate all the
19163 // time.
19164
19165 stmt(IRStmt_Put(OFFB_CMSTART, mkSzImm(ty, guest_CIA_curr_instr)));
19166 stmt(IRStmt_Put(OFFB_CMLEN, mkSzImm(ty, 20)));
19167
19168 putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta ));
19169 dres.whatNext = Dis_StopHere;
19170 dres.jk_StopHere = Ijk_InvalICache;
19171 goto decode_success;
19172 }
19173 /* We don't know what it is. Set opc1/opc2 so decode_failure
19174 can print the insn following the Special-insn preamble. */
19175 theInstr = getUIntPPCendianly(code+16);
19176 opc1 = ifieldOPC(theInstr);
19177 opc2 = ifieldOPClo10(theInstr);
19178 goto decode_failure;
19179 /*NOTREACHED*/
19180 }
19181 }
19182
19183 opc1 = ifieldOPC(theInstr);
19184 opc2 = ifieldOPClo10(theInstr);
19185
19186 // Note: all 'reserved' bits must be cleared, else invalid
19187 switch (opc1) {
19188
19189 /* Integer Arithmetic Instructions */
19190 case 0x0C: case 0x0D: case 0x0E: // addic, addic., addi
19191 case 0x0F: case 0x07: case 0x08: // addis, mulli, subfic
19192 if (dis_int_arith( theInstr )) goto decode_success;
19193 goto decode_failure;
19194
19195 /* Integer Compare Instructions */
19196 case 0x0B: case 0x0A: // cmpi, cmpli
19197 if (dis_int_cmp( theInstr )) goto decode_success;
19198 goto decode_failure;
19199
19200 /* Integer Logical Instructions */
19201 case 0x1C: case 0x1D: case 0x18: // andi., andis., ori
19202 case 0x19: case 0x1A: case 0x1B: // oris, xori, xoris
19203 if (dis_int_logic( theInstr )) goto decode_success;
19204 goto decode_failure;
19205
19206 /* Integer Rotate Instructions */
19207 case 0x14: case 0x15: case 0x17: // rlwimi, rlwinm, rlwnm
19208 if (dis_int_rot( theInstr )) goto decode_success;
19209 goto decode_failure;
19210
19211 /* 64bit Integer Rotate Instructions */
19212 case 0x1E: // rldcl, rldcr, rldic, rldicl, rldicr, rldimi
19213 if (!mode64) goto decode_failure;
19214 if (dis_int_rot( theInstr )) goto decode_success;
19215 goto decode_failure;
19216
19217 /* Integer Load Instructions */
19218 case 0x22: case 0x23: case 0x2A: // lbz, lbzu, lha
19219 case 0x2B: case 0x28: case 0x29: // lhau, lhz, lhzu
19220 case 0x20: case 0x21: // lwz, lwzu
19221 if (dis_int_load( theInstr )) goto decode_success;
19222 goto decode_failure;
19223
19224 /* Integer Store Instructions */
19225 case 0x26: case 0x27: case 0x2C: // stb, stbu, sth
19226 case 0x2D: case 0x24: case 0x25: // sthu, stw, stwu
19227 if (dis_int_store( theInstr, abiinfo )) goto decode_success;
19228 goto decode_failure;
19229
19230 /* Integer Load and Store Multiple Instructions */
19231 case 0x2E: case 0x2F: // lmw, stmw
19232 if (dis_int_ldst_mult( theInstr )) goto decode_success;
19233 goto decode_failure;
19234
19235 /* Branch Instructions */
19236 case 0x12: case 0x10: // b, bc
19237 if (dis_branch(theInstr, abiinfo, &dres,
19238 resteerOkFn, callback_opaque))
19239 goto decode_success;
19240 goto decode_failure;
19241
19242 /* System Linkage Instructions */
19243 case 0x11: // sc
19244 if (dis_syslink(theInstr, abiinfo, &dres)) goto decode_success;
19245 goto decode_failure;
19246
19247 /* Trap Instructions */
19248 case 0x02: // tdi
19249 if (!mode64) goto decode_failure;
19250 if (dis_trapi(theInstr, &dres)) goto decode_success;
19251 goto decode_failure;
19252
19253 case 0x03: // twi
19254 if (dis_trapi(theInstr, &dres)) goto decode_success;
19255 goto decode_failure;
19256
19257 /* Floating Point Load Instructions */
19258 case 0x30: case 0x31: case 0x32: // lfs, lfsu, lfd
19259 case 0x33: // lfdu
19260 if (!allow_F) goto decode_noF;
19261 if (dis_fp_load( theInstr )) goto decode_success;
19262 goto decode_failure;
19263
19264 /* Floating Point Store Instructions */
19265 case 0x34: case 0x35: case 0x36: // stfsx, stfsux, stfdx
19266 case 0x37: // stfdux
19267 if (!allow_F) goto decode_noF;
19268 if (dis_fp_store( theInstr )) goto decode_success;
19269 goto decode_failure;
19270
19271 /* Floating Point Load Double Pair Instructions */
19272 case 0x39: case 0x3D:
19273 if (!allow_F) goto decode_noF;
19274 if (dis_fp_pair( theInstr )) goto decode_success;
19275 goto decode_failure;
19276
19277 /* 128-bit Integer Load */
19278 case 0x38: // lq
19279 if (dis_int_load( theInstr )) goto decode_success;
19280 goto decode_failure;
19281
19282 /* 64bit Integer Loads */
19283 case 0x3A: // ld, ldu, lwa
19284 if (!mode64) goto decode_failure;
19285 if (dis_int_load( theInstr )) goto decode_success;
19286 goto decode_failure;
19287
19288 case 0x3B:
19289 if (!allow_F) goto decode_noF;
19290 opc2 = ifieldOPClo10(theInstr);
19291
19292 switch (opc2) {
19293 case 0x2: // dadd - DFP Add
19294 case 0x202: // dsub - DFP Subtract
19295 case 0x22: // dmul - DFP Mult
19296 case 0x222: // ddiv - DFP Divide
19297 if (!allow_DFP) goto decode_noDFP;
19298 if (dis_dfp_arith( theInstr ))
19299 goto decode_success;
19300 case 0x82: // dcmpo, DFP comparison ordered instruction
19301 case 0x282: // dcmpu, DFP comparison unordered instruction
19302 if (!allow_DFP) goto decode_noDFP;
19303 if (dis_dfp_compare( theInstr ) )
19304 goto decode_success;
19305 goto decode_failure;
19306 case 0x102: // dctdp - DFP convert to DFP long
19307 case 0x302: // drsp - DFP round to dfp short
19308 case 0x122: // dctfix - DFP convert to fixed
19309 if (!allow_DFP) goto decode_noDFP;
19310 if (dis_dfp_fmt_conv( theInstr ))
19311 goto decode_success;
19312 goto decode_failure;
19313 case 0x322: // POWER 7 inst, dcffix - DFP convert from fixed
19314 if (!allow_VX)
19315 goto decode_failure;
19316 if (!allow_DFP) goto decode_noDFP;
19317 if (dis_dfp_fmt_conv( theInstr ))
19318 goto decode_success;
19319 goto decode_failure;
19320 case 0x2A2: // dtstsf - DFP number of significant digits
19321 if (!allow_DFP) goto decode_noDFP;
19322 if (dis_dfp_significant_digits(theInstr))
19323 goto decode_success;
19324 goto decode_failure;
19325 case 0x142: // ddedpd DFP Decode DPD to BCD
19326 case 0x342: // denbcd DFP Encode BCD to DPD
19327 if (!allow_DFP) goto decode_noDFP;
19328 if (dis_dfp_bcd(theInstr))
19329 goto decode_success;
19330 goto decode_failure;
19331 case 0x162: // dxex - Extract exponent
19332 case 0x362: // diex - Insert exponent
19333 if (!allow_DFP) goto decode_noDFP;
19334 if (dis_dfp_extract_insert( theInstr ) )
19335 goto decode_success;
19336 goto decode_failure;
19337 case 0x3CE: // fcfidus (implemented as native insn)
19338 if (!allow_VX)
19339 goto decode_noVX;
19340 if (dis_fp_round( theInstr ))
19341 goto decode_success;
19342 goto decode_failure;
19343 case 0x34E: // fcfids
19344 if (dis_fp_round( theInstr ))
19345 goto decode_success;
19346 goto decode_failure;
19347 }
19348
19349 opc2 = ifieldOPClo9( theInstr );
19350 switch (opc2) {
19351 case 0x42: // dscli, DFP shift left
19352 case 0x62: // dscri, DFP shift right
19353 if (!allow_DFP) goto decode_noDFP;
19354 if (dis_dfp_shift( theInstr ))
19355 goto decode_success;
19356 goto decode_failure;
19357 case 0xc2: // dtstdc, DFP test data class
19358 case 0xe2: // dtstdg, DFP test data group
19359 if (!allow_DFP) goto decode_noDFP;
19360 if (dis_dfp_class_test( theInstr ))
19361 goto decode_success;
19362 goto decode_failure;
19363 }
19364
19365 opc2 = ifieldOPClo8( theInstr );
19366 switch (opc2) {
19367 case 0x3: // dqua - DFP Quantize
19368 case 0x23: // drrnd - DFP Reround
19369 case 0x43: // dquai - DFP Quantize immediate
19370 if (!allow_DFP) goto decode_noDFP;
19371 if (dis_dfp_quantize_sig_rrnd( theInstr ) )
19372 goto decode_success;
19373 goto decode_failure;
19374 case 0xA2: // dtstex - DFP Test exponent
19375 if (!allow_DFP) goto decode_noDFP;
19376 if (dis_dfp_exponent_test( theInstr ) )
19377 goto decode_success;
19378 goto decode_failure;
19379 case 0x63: // drintx - Round to an integer value
19380 case 0xE3: // drintn - Round to an integer value
19381 if (!allow_DFP) goto decode_noDFP;
19382 if (dis_dfp_round( theInstr ) ) {
19383 goto decode_success;
19384 }
19385 goto decode_failure;
19386 default:
19387 break; /* fall through to next opc2 check */
19388 }
19389
19390 opc2 = IFIELD(theInstr, 1, 5);
19391 switch (opc2) {
19392 /* Floating Point Arith Instructions */
19393 case 0x12: case 0x14: case 0x15: // fdivs, fsubs, fadds
19394 case 0x19: // fmuls
19395 if (dis_fp_arith(theInstr)) goto decode_success;
19396 goto decode_failure;
19397 case 0x16: // fsqrts
19398 if (!allow_FX) goto decode_noFX;
19399 if (dis_fp_arith(theInstr)) goto decode_success;
19400 goto decode_failure;
19401 case 0x18: // fres
19402 if (!allow_GX) goto decode_noGX;
19403 if (dis_fp_arith(theInstr)) goto decode_success;
19404 goto decode_failure;
19405
19406 /* Floating Point Mult-Add Instructions */
19407 case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs
19408 case 0x1F: // fnmadds
19409 if (dis_fp_multadd(theInstr)) goto decode_success;
19410 goto decode_failure;
19411
19412 case 0x1A: // frsqrtes
19413 if (!allow_GX) goto decode_noGX;
19414 if (dis_fp_arith(theInstr)) goto decode_success;
19415 goto decode_failure;
19416
19417 default:
19418 goto decode_failure;
19419 }
19420 break;
19421
19422 case 0x3C: // VSX instructions (except load/store)
19423 {
19424 // All of these VSX instructions use some VMX facilities, so
19425 // if allow_V is not set, we'll skip trying to decode.
19426 if (!allow_V) goto decode_noVX;
19427
19428 UInt vsxOpc2 = get_VSX60_opc2(opc2);
19429 /* The vsxOpc2 returned is the "normalized" value, representing the
19430 * instructions secondary opcode as taken from the standard secondary
19431 * opcode field [21:30] (IBM notatition), even if the actual field
19432 * is non-standard. These normalized values are given in the opcode
19433 * appendices of the ISA 2.06 document.
19434 */
19435
19436 switch (vsxOpc2) {
19437 case 0x8: case 0x28: case 0x48: case 0xc8: // xxsldwi, xxpermdi, xxmrghw, xxmrglw
19438 case 0x018: case 0x148: // xxsel, xxspltw
19439 if (dis_vx_permute_misc(theInstr, vsxOpc2)) goto decode_success;
19440 goto decode_failure;
19441 case 0x268: case 0x248: case 0x288: // xxlxor, xxlor, xxlnor,
19442 case 0x208: case 0x228: case 0x2A8: // xxland, xxlandc, xxlorc
19443 case 0x2C8: case 0x2E8: // xxlnand, xxleqv
19444 if (dis_vx_logic(theInstr, vsxOpc2)) goto decode_success;
19445 goto decode_failure;
19446 case 0x2B2: case 0x2C0: // xsabsdp, xscpsgndp
19447 case 0x2D2: case 0x2F2: // xsnabsdp, xsnegdp
19448 case 0x280: case 0x2A0: // xsmaxdp, xsmindp
19449 case 0x0F2: case 0x0D2: // xsrdpim, xsrdpip
19450 case 0x034: case 0x014: // xsresp, xsrsqrtesp
19451 case 0x0B4: case 0x094: // xsredp, xsrsqrtedp
19452 case 0x0D6: case 0x0B2: // xsrdpic, xsrdpiz
19453 case 0x092: case 0x232: // xsrdpi, xsrsp
19454 if (dis_vxs_misc(theInstr, vsxOpc2)) goto decode_success;
19455 goto decode_failure;
19456 case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
19457 if (dis_vx_cmp(theInstr, vsxOpc2)) goto decode_success;
19458 goto decode_failure;
19459 case 0x0: case 0x020: // xsaddsp, xssubsp
19460 case 0x080: // xsadddp
19461 case 0x060: case 0x0E0: // xsdivsp, xsdivdp
19462 case 0x004: case 0x024: // xsmaddasp, xsmaddmsp
19463 case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp
19464 case 0x044: case 0x064: // xsmsubasp, xsmsubmsp
19465 case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp
19466 case 0x204: case 0x224: // xsnmaddasp, xsnmaddmsp
19467 case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp
19468 case 0x244: case 0x264: // xsnmsubasp, xsnmsubmsp
19469 case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp
19470 case 0x040: case 0x0C0: // xsmulsp, xsmuldp
19471 case 0x0A0: // xssubdp
19472 case 0x016: case 0x096: // xssqrtsp,xssqrtdp
19473 case 0x0F4: case 0x0D4: // xstdivdp, xstsqrtdp
19474 if (dis_vxs_arith(theInstr, vsxOpc2)) goto decode_success;
19475 goto decode_failure;
19476 case 0x180: // xvadddp
19477 case 0x1E0: // xvdivdp
19478 case 0x1C0: // xvmuldp
19479 case 0x1A0: // xvsubdp
19480 case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp
19481 case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp
19482 case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp
19483 case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp
19484 case 0x1D4: case 0x1F4: // xvtsqrtdp, xvtdivdp
19485 case 0x196: // xvsqrtdp
19486 if (dis_vxv_dp_arith(theInstr, vsxOpc2)) goto decode_success;
19487 goto decode_failure;
19488 case 0x100: // xvaddsp
19489 case 0x160: // xvdivsp
19490 case 0x140: // xvmulsp
19491 case 0x120: // xvsubsp
19492 case 0x104: case 0x124: // xvmaddasp, xvmaddmsp
19493 case 0x144: case 0x164: // xvmsubasp, xvmsubmsp
19494 case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp
19495 case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp
19496 case 0x154: case 0x174: // xvtsqrtsp, xvtdivsp
19497 case 0x116: // xvsqrtsp
19498 if (dis_vxv_sp_arith(theInstr, vsxOpc2)) goto decode_success;
19499 goto decode_failure;
19500
19501 case 0x250: // xscvuxdsp
19502 case 0x2D0: case 0x3d0: // xscvuxddp, xvcvuxddp
19503 case 0x350: case 0x1d0: // xvcvuxdsp, xvcvuxwdp
19504 case 0x090: // xscvdpuxws
19505 // The above VSX conversion instructions employ some ISA 2.06
19506 // floating point conversion instructions under the covers,
19507 // so if allow_VX (which means "supports ISA 2.06") is not set,
19508 // we'll skip the decode.
19509 if (!allow_VX) goto decode_noVX;
19510 if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
19511 goto decode_failure;
19512
19513 case 0x2B0: // xscvdpsxds
19514 case 0x270: case 0x2F0: // xscvsxdsp, xscvsxddp
19515 case 0x1b0: case 0x130: // xvcvdpsxws, xvcvspsxws
19516 case 0x0b0: case 0x290: // xscvdpsxws, xscvdpuxds
19517 case 0x212: case 0x216: // xscvdpsp, xscvdpspn
19518 case 0x292: case 0x296: // xscvspdp, xscvspdpn
19519 case 0x312: // xvcvdpsp
19520 case 0x390: case 0x190: // xvcvdpuxds, xvcvdpuxws
19521 case 0x3B0: case 0x310: // xvcvdpsxds, xvcvspuxds
19522 case 0x392: case 0x330: // xvcvspdp, xvcvspsxds
19523 case 0x110: case 0x3f0: // xvcvspuxws, xvcvsxddp
19524 case 0x370: case 0x1f0: // xvcvsxdsp, xvcvsxwdp
19525 case 0x170: case 0x150: // xvcvsxwsp, xvcvuxwsp
19526 if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
19527 goto decode_failure;
19528
19529 case 0x18C: case 0x38C: // xvcmpeqdp[.]
19530 case 0x10C: case 0x30C: // xvcmpeqsp[.]
19531 case 0x14C: case 0x34C: // xvcmpgesp[.]
19532 case 0x12C: case 0x32C: // xvcmpgtsp[.]
19533 case 0x1CC: case 0x3CC: // xvcmpgedp[.]
19534 case 0x1AC: case 0x3AC: // xvcmpgtdp[.]
19535 if (dis_vvec_cmp(theInstr, vsxOpc2)) goto decode_success;
19536 goto decode_failure;
19537
19538 case 0x134: // xvresp
19539 case 0x1B4: // xvredp
19540 case 0x194: case 0x114: // xvrsqrtedp, xvrsqrtesp
19541 case 0x380: case 0x3A0: // xvmaxdp, xvmindp
19542 case 0x300: case 0x320: // xvmaxsp, xvminsp
19543 case 0x3C0: case 0x340: // xvcpsgndp, xvcpsgnsp
19544 case 0x3B2: case 0x332: // xvabsdp, xvabssp
19545 case 0x3D2: case 0x352: // xvnabsdp, xvnabssp
19546 case 0x192: case 0x1D6: // xvrdpi, xvrdpic
19547 case 0x1F2: case 0x1D2: // xvrdpim, xvrdpip
19548 case 0x1B2: case 0x3F2: // xvrdpiz, xvnegdp
19549 case 0x112: case 0x156: // xvrspi, xvrspic
19550 case 0x172: case 0x152: // xvrspim, xvrspip
19551 case 0x132: // xvrspiz
19552 if (dis_vxv_misc(theInstr, vsxOpc2)) goto decode_success;
19553 goto decode_failure;
19554
19555 default:
19556 goto decode_failure;
19557 }
19558 break;
19559 }
19560
19561 /* 64bit Integer Stores */
19562 case 0x3E: // std, stdu, stq
19563 if (dis_int_store( theInstr, abiinfo )) goto decode_success;
19564 goto decode_failure;
19565
19566 case 0x3F:
19567 if (!allow_F) goto decode_noF;
19568 /* Instrs using opc[1:5] never overlap instrs using opc[1:10],
19569 so we can simply fall through the first switch statement */
19570
19571 opc2 = IFIELD(theInstr, 1, 5);
19572 switch (opc2) {
19573 /* Floating Point Arith Instructions */
19574 case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd
19575 case 0x19: // fmul
19576 if (dis_fp_arith(theInstr)) goto decode_success;
19577 goto decode_failure;
19578 case 0x16: // fsqrt
19579 if (!allow_FX) goto decode_noFX;
19580 if (dis_fp_arith(theInstr)) goto decode_success;
19581 goto decode_failure;
19582 case 0x17: case 0x1A: // fsel, frsqrte
19583 if (!allow_GX) goto decode_noGX;
19584 if (dis_fp_arith(theInstr)) goto decode_success;
19585 goto decode_failure;
19586
19587 /* Floating Point Mult-Add Instructions */
19588 case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub
19589 case 0x1F: // fnmadd
19590 if (dis_fp_multadd(theInstr)) goto decode_success;
19591 goto decode_failure;
19592
19593 case 0x18: // fre
19594 if (!allow_GX) goto decode_noGX;
19595 if (dis_fp_arith(theInstr)) goto decode_success;
19596 goto decode_failure;
19597
19598 default:
19599 break; // Fall through
19600 }
19601
19602 opc2 = IFIELD(theInstr, 1, 10);
19603 switch (opc2) {
19604 /* 128-bit DFP instructions */
19605 case 0x2: // daddq - DFP Add
19606 case 0x202: // dsubq - DFP Subtract
19607 case 0x22: // dmulq - DFP Mult
19608 case 0x222: // ddivq - DFP Divide
19609 if (!allow_DFP) goto decode_noDFP;
19610 if (dis_dfp_arithq( theInstr ))
19611 goto decode_success;
19612 goto decode_failure;
19613 case 0x162: // dxexq - DFP Extract exponent
19614 case 0x362: // diexq - DFP Insert exponent
19615 if (!allow_DFP) goto decode_noDFP;
19616 if (dis_dfp_extract_insertq( theInstr ))
19617 goto decode_success;
19618 goto decode_failure;
19619
19620 case 0x82: // dcmpoq, DFP comparison ordered instruction
19621 case 0x282: // dcmpuq, DFP comparison unordered instruction
19622 if (!allow_DFP) goto decode_noDFP;
19623 if (dis_dfp_compare( theInstr ) )
19624 goto decode_success;
19625 goto decode_failure;
19626
19627 case 0x102: // dctqpq - DFP convert to DFP extended
19628 case 0x302: // drdpq - DFP round to dfp Long
19629 case 0x122: // dctfixq - DFP convert to fixed quad
19630 case 0x322: // dcffixq - DFP convert from fixed quad
19631 if (!allow_DFP) goto decode_noDFP;
19632 if (dis_dfp_fmt_convq( theInstr ))
19633 goto decode_success;
19634 goto decode_failure;
19635
19636 case 0x2A2: // dtstsfq - DFP number of significant digits
19637 if (!allow_DFP) goto decode_noDFP;
19638 if (dis_dfp_significant_digits(theInstr))
19639 goto decode_success;
19640 goto decode_failure;
19641
19642 case 0x142: // ddedpdq DFP Decode DPD to BCD
19643 case 0x342: // denbcdq DFP Encode BCD to DPD
19644 if (!allow_DFP) goto decode_noDFP;
19645 if (dis_dfp_bcdq(theInstr))
19646 goto decode_success;
19647 goto decode_failure;
19648
19649 /* Floating Point Compare Instructions */
19650 case 0x000: // fcmpu
19651 case 0x020: // fcmpo
19652 if (dis_fp_cmp(theInstr)) goto decode_success;
19653 goto decode_failure;
19654
19655 case 0x080: // ftdiv
19656 case 0x0A0: // ftsqrt
19657 if (dis_fp_tests(theInstr)) goto decode_success;
19658 goto decode_failure;
19659
19660 /* Floating Point Rounding/Conversion Instructions */
19661 case 0x00C: // frsp
19662 case 0x00E: // fctiw
19663 case 0x00F: // fctiwz
19664 case 0x32E: // fctid
19665 case 0x32F: // fctidz
19666 case 0x34E: // fcfid
19667 if (dis_fp_round(theInstr)) goto decode_success;
19668 goto decode_failure;
19669 case 0x3CE: case 0x3AE: case 0x3AF: // fcfidu, fctidu[z] (implemented as native insns)
19670 case 0x08F: case 0x08E: // fctiwu[z] (implemented as native insns)
19671 if (!allow_VX) goto decode_noVX;
19672 if (dis_fp_round(theInstr)) goto decode_success;
19673 goto decode_failure;
19674
19675 /* Power6 rounding stuff */
19676 case 0x1E8: // frim
19677 case 0x1C8: // frip
19678 case 0x188: // frin
19679 case 0x1A8: // friz
19680 /* A hack to check for P6 capability . . . */
19681 if ((allow_F && allow_V && allow_FX && allow_GX) &&
19682 (dis_fp_round(theInstr)))
19683 goto decode_success;
19684 goto decode_failure;
19685
19686 /* Floating Point Move Instructions */
19687 case 0x008: // fcpsgn
19688 case 0x028: // fneg
19689 case 0x048: // fmr
19690 case 0x088: // fnabs
19691 case 0x108: // fabs
19692 if (dis_fp_move( theInstr )) goto decode_success;
19693 goto decode_failure;
19694
19695 case 0x3c6: case 0x346: // fmrgew, fmrgow
19696 if (dis_fp_merge( theInstr )) goto decode_success;
19697 goto decode_failure;
19698
19699 /* Floating Point Status/Control Register Instructions */
19700 case 0x026: // mtfsb1
19701 case 0x040: // mcrfs
19702 case 0x046: // mtfsb0
19703 case 0x086: // mtfsfi
19704 case 0x247: // mffs
19705 case 0x2C7: // mtfsf
19706 // Some of the above instructions need to know more about the
19707 // ISA level supported by the host.
19708 if (dis_fp_scr( theInstr, allow_GX )) goto decode_success;
19709 goto decode_failure;
19710
19711 default:
19712 break; // Fall through...
19713 }
19714
19715 opc2 = ifieldOPClo9( theInstr );
19716 switch (opc2) {
19717 case 0x42: // dscli, DFP shift left
19718 case 0x62: // dscri, DFP shift right
19719 if (!allow_DFP) goto decode_noDFP;
19720 if (dis_dfp_shiftq( theInstr ))
19721 goto decode_success;
19722 goto decode_failure;
19723 case 0xc2: // dtstdc, DFP test data class
19724 case 0xe2: // dtstdg, DFP test data group
19725 if (!allow_DFP) goto decode_noDFP;
19726 if (dis_dfp_class_test( theInstr ))
19727 goto decode_success;
19728 goto decode_failure;
19729 default:
19730 break;
19731 }
19732
19733 opc2 = ifieldOPClo8( theInstr );
19734 switch (opc2) {
19735 case 0x3: // dquaq - DFP Quantize Quad
19736 case 0x23: // drrndq - DFP Reround Quad
19737 case 0x43: // dquaiq - DFP Quantize immediate Quad
19738 if (!allow_DFP) goto decode_noDFP;
19739 if (dis_dfp_quantize_sig_rrndq( theInstr ))
19740 goto decode_success;
19741 goto decode_failure;
19742 case 0xA2: // dtstexq - DFP Test exponent Quad
19743 if (!allow_DFP) goto decode_noDFP;
19744 if (dis_dfp_exponent_test( theInstr ) )
19745 goto decode_success;
19746 goto decode_failure;
19747 case 0x63: // drintxq - DFP Round to an integer value
19748 case 0xE3: // drintnq - DFP Round to an integer value
19749 if (!allow_DFP) goto decode_noDFP;
19750 if (dis_dfp_roundq( theInstr ))
19751 goto decode_success;
19752 goto decode_failure;
19753
19754 default:
19755 goto decode_failure;
19756 }
19757 break;
19758
19759 case 0x13:
19760 switch (opc2) {
19761
19762 /* Condition Register Logical Instructions */
19763 case 0x101: case 0x081: case 0x121: // crand, crandc, creqv
19764 case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor, cror
19765 case 0x1A1: case 0x0C1: case 0x000: // crorc, crxor, mcrf
19766 if (dis_cond_logic( theInstr )) goto decode_success;
19767 goto decode_failure;
19768
19769 /* Branch Instructions */
19770 case 0x210: case 0x010: // bcctr, bclr
19771 if (dis_branch(theInstr, abiinfo, &dres,
19772 resteerOkFn, callback_opaque))
19773 goto decode_success;
19774 goto decode_failure;
19775
19776 /* Memory Synchronization Instructions */
19777 case 0x096: // isync
19778 if (dis_memsync( theInstr )) goto decode_success;
19779 goto decode_failure;
19780
19781 default:
19782 goto decode_failure;
19783 }
19784 break;
19785
19786
19787 case 0x1F:
19788
19789 /* For arith instns, bit10 is the OE flag (overflow enable) */
19790
19791 opc2 = IFIELD(theInstr, 1, 9);
19792 switch (opc2) {
19793 /* Integer Arithmetic Instructions */
19794 case 0x10A: case 0x00A: case 0x08A: // add, addc, adde
19795 case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw
19796 case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu
19797 case 0x0EB: case 0x068: case 0x028: // mullw, neg, subf
19798 case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme
19799 case 0x0C8: // subfze
19800 if (dis_int_arith( theInstr )) goto decode_success;
19801 goto decode_failure;
19802
19803 case 0x18B: // divweu (implemented as native insn)
19804 case 0x1AB: // divwe (implemented as native insn)
19805 if (!allow_VX) goto decode_noVX;
19806 if (dis_int_arith( theInstr )) goto decode_success;
19807 goto decode_failure;
19808
19809 /* 64bit Integer Arithmetic */
19810 case 0x009: case 0x049: case 0x0E9: // mulhdu, mulhd, mulld
19811 case 0x1C9: case 0x1E9: // divdu, divd
19812 if (!mode64) goto decode_failure;
19813 if (dis_int_arith( theInstr )) goto decode_success;
19814 goto decode_failure;
19815
19816 case 0x1A9: // divde (implemented as native insn)
19817 case 0x189: // divdeuo (implemented as native insn)
19818 if (!allow_VX) goto decode_noVX;
19819 if (!mode64) goto decode_failure;
19820 if (dis_int_arith( theInstr )) goto decode_success;
19821 goto decode_failure;
19822
19823 case 0x1FC: // cmpb
19824 if (dis_int_logic( theInstr )) goto decode_success;
19825 goto decode_failure;
19826
19827 default:
19828 break; // Fall through...
19829 }
19830
19831 /* All remaining opcodes use full 10 bits. */
19832
19833 opc2 = IFIELD(theInstr, 1, 10);
19834 switch (opc2) {
19835 /* Integer Compare Instructions */
19836 case 0x000: case 0x020: // cmp, cmpl
19837 if (dis_int_cmp( theInstr )) goto decode_success;
19838 goto decode_failure;
19839
19840 /* Integer Logical Instructions */
19841 case 0x01C: case 0x03C: case 0x01A: // and, andc, cntlzw
19842 case 0x11C: case 0x3BA: case 0x39A: // eqv, extsb, extsh
19843 case 0x1DC: case 0x07C: case 0x1BC: // nand, nor, or
19844 case 0x19C: case 0x13C: // orc, xor
19845 case 0x2DF: case 0x25F: // mftgpr, mffgpr
19846 if (dis_int_logic( theInstr )) goto decode_success;
19847 goto decode_failure;
19848
19849 case 0x28E: case 0x2AE: // tbegin., tend.
19850 case 0x2EE: case 0x2CE: case 0x30E: // tsr., tcheck., tabortwc.
19851 case 0x32E: case 0x34E: case 0x36E: // tabortdc., tabortwci., tabortdci.
19852 case 0x38E: case 0x3AE: case 0x3EE: // tabort., treclaim., trechkpt.
19853 if (dis_transactional_memory( theInstr,
19854 getUIntPPCendianly( &guest_code[delta + 4]),
19855 abiinfo, &dres,
19856 resteerOkFn, callback_opaque))
19857 goto decode_success;
19858 goto decode_failure;
19859
19860 /* 64bit Integer Logical Instructions */
19861 case 0x3DA: case 0x03A: // extsw, cntlzd
19862 if (!mode64) goto decode_failure;
19863 if (dis_int_logic( theInstr )) goto decode_success;
19864 goto decode_failure;
19865
19866 /* 64bit Integer Parity Instructions */
19867 case 0xba: // prtyd
19868 if (!mode64) goto decode_failure;
19869 if (dis_int_parity( theInstr )) goto decode_success;
19870 goto decode_failure;
19871
19872 case 0x9a: // prtyw
19873 if (dis_int_parity( theInstr )) goto decode_success;
19874 goto decode_failure;
19875
19876 /* Integer Shift Instructions */
19877 case 0x018: case 0x318: case 0x338: // slw, sraw, srawi
19878 case 0x218: // srw
19879 if (dis_int_shift( theInstr )) goto decode_success;
19880 goto decode_failure;
19881
19882 /* 64bit Integer Shift Instructions */
19883 case 0x01B: case 0x31A: // sld, srad
19884 case 0x33A: case 0x33B: // sradi
19885 case 0x21B: // srd
19886 if (!mode64) goto decode_failure;
19887 if (dis_int_shift( theInstr )) goto decode_success;
19888 goto decode_failure;
19889
19890 /* Integer Load Instructions */
19891 case 0x057: case 0x077: case 0x157: // lbzx, lbzux, lhax
19892 case 0x177: case 0x117: case 0x137: // lhaux, lhzx, lhzux
19893 case 0x017: case 0x037: // lwzx, lwzux
19894 if (dis_int_load( theInstr )) goto decode_success;
19895 goto decode_failure;
19896
19897 /* 64bit Integer Load Instructions */
19898 case 0x035: case 0x015: // ldux, ldx
19899 case 0x175: case 0x155: // lwaux, lwax
19900 if (!mode64) goto decode_failure;
19901 if (dis_int_load( theInstr )) goto decode_success;
19902 goto decode_failure;
19903
19904 /* Integer Store Instructions */
19905 case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx, sthux
19906 case 0x197: case 0x0B7: case 0x097: // sthx, stwux, stwx
19907 if (dis_int_store( theInstr, abiinfo )) goto decode_success;
19908 goto decode_failure;
19909
19910 /* 64bit Integer Store Instructions */
19911 case 0x0B5: case 0x095: // stdux, stdx
19912 if (!mode64) goto decode_failure;
19913 if (dis_int_store( theInstr, abiinfo )) goto decode_success;
19914 goto decode_failure;
19915
19916 /* Integer Load and Store with Byte Reverse Instructions */
19917 case 0x214: case 0x294: // ldbrx, stdbrx
19918 if (!mode64) goto decode_failure;
19919 if (dis_int_ldst_rev( theInstr )) goto decode_success;
19920 goto decode_failure;
19921
19922 case 0x216: case 0x316: case 0x296: // lwbrx, lhbrx, stwbrx
19923 case 0x396: // sthbrx
19924 if (dis_int_ldst_rev( theInstr )) goto decode_success;
19925 goto decode_failure;
19926
19927 /* Integer Load and Store String Instructions */
19928 case 0x255: case 0x215: case 0x2D5: // lswi, lswx, stswi
19929 case 0x295: { // stswx
19930 Bool stopHere = False;
19931 Bool ok = dis_int_ldst_str( theInstr, &stopHere );
19932 if (!ok) goto decode_failure;
19933 if (stopHere) {
19934 putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()) );
19935 dres.jk_StopHere = Ijk_Boring;
19936 dres.whatNext = Dis_StopHere;
19937 }
19938 goto decode_success;
19939 }
19940
19941 /* Memory Synchronization Instructions */
19942 case 0x034: case 0x074: // lbarx, lharx
19943 case 0x2B6: case 0x2D6: // stbcx, sthcx
19944 if (!allow_isa_2_07) goto decode_noP8;
19945 if (dis_memsync( theInstr )) goto decode_success;
19946 goto decode_failure;
19947
19948 case 0x356: case 0x014: case 0x096: // eieio, lwarx, stwcx.
19949 case 0x256: // sync
19950 if (dis_memsync( theInstr )) goto decode_success;
19951 goto decode_failure;
19952
19953 /* 64bit Memory Synchronization Instructions */
19954 case 0x054: case 0x0D6: // ldarx, stdcx.
19955 if (!mode64) goto decode_failure;
19956 if (dis_memsync( theInstr )) goto decode_success;
19957 goto decode_failure;
19958
19959 case 0x114: case 0x0B6: // lqarx, stqcx.
19960 if (dis_memsync( theInstr )) goto decode_success;
19961 goto decode_failure;
19962
19963 /* Processor Control Instructions */
19964 case 0x33: case 0x73: // mfvsrd, mfvsrwz
19965 case 0xB3: case 0xD3: case 0xF3: // mtvsrd, mtvsrwa, mtvsrwz
19966 case 0x200: case 0x013: case 0x153: // mcrxr, mfcr, mfspr
19967 case 0x173: case 0x090: case 0x1D3: // mftb, mtcrf, mtspr
19968 case 0x220: // mcrxrt
19969 if (dis_proc_ctl( abiinfo, theInstr )) goto decode_success;
19970 goto decode_failure;
19971
19972 /* Cache Management Instructions */
19973 case 0x2F6: case 0x056: case 0x036: // dcba, dcbf, dcbst
19974 case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz
19975 case 0x3D6: // icbi
19976 if (dis_cache_manage( theInstr, &dres, archinfo ))
19977 goto decode_success;
19978 goto decode_failure;
19979
19980 //zz /* External Control Instructions */
19981 //zz case 0x136: case 0x1B6: // eciwx, ecowx
19982 //zz DIP("external control op => not implemented\n");
19983 //zz goto decode_failure;
19984
19985 /* Trap Instructions */
19986 case 0x004: // tw
19987 if (dis_trap(theInstr, &dres)) goto decode_success;
19988 goto decode_failure;
19989
19990 case 0x044: // td
19991 if (!mode64) goto decode_failure;
19992 if (dis_trap(theInstr, &dres)) goto decode_success;
19993 goto decode_failure;
19994
19995 /* Floating Point Load Instructions */
19996 case 0x217: case 0x237: case 0x257: // lfsx, lfsux, lfdx
19997 case 0x277: // lfdux
19998 if (!allow_F) goto decode_noF;
19999 if (dis_fp_load( theInstr )) goto decode_success;
20000 goto decode_failure;
20001
20002 /* Floating Point Store Instructions */
20003 case 0x297: case 0x2B7: case 0x2D7: // stfs, stfsu, stfd
20004 case 0x2F7: // stfdu, stfiwx
20005 if (!allow_F) goto decode_noF;
20006 if (dis_fp_store( theInstr )) goto decode_success;
20007 goto decode_failure;
20008 case 0x3D7: // stfiwx
20009 if (!allow_F) goto decode_noF;
20010 if (!allow_GX) goto decode_noGX;
20011 if (dis_fp_store( theInstr )) goto decode_success;
20012 goto decode_failure;
20013
20014 /* Floating Point Double Pair Indexed Instructions */
20015 case 0x317: // lfdpx (Power6)
20016 case 0x397: // stfdpx (Power6)
20017 if (!allow_F) goto decode_noF;
20018 if (dis_fp_pair(theInstr)) goto decode_success;
20019 goto decode_failure;
20020
20021 case 0x357: // lfiwax
20022 if (!allow_F) goto decode_noF;
20023 if (dis_fp_load( theInstr )) goto decode_success;
20024 goto decode_failure;
20025
20026 case 0x377: // lfiwzx
20027 if (!allow_F) goto decode_noF;
20028 if (dis_fp_load( theInstr )) goto decode_success;
20029 goto decode_failure;
20030
20031 /* AltiVec instructions */
20032
20033 /* AV Cache Control - Data streams */
20034 case 0x156: case 0x176: case 0x336: // dst, dstst, dss
20035 if (!allow_V) goto decode_noV;
20036 if (dis_av_datastream( theInstr )) goto decode_success;
20037 goto decode_failure;
20038
20039 /* AV Load */
20040 case 0x006: case 0x026: // lvsl, lvsr
20041 case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx
20042 case 0x067: case 0x167: // lvx, lvxl
20043 if (!allow_V) goto decode_noV;
20044 if (dis_av_load( abiinfo, theInstr )) goto decode_success;
20045 goto decode_failure;
20046
20047 /* AV Store */
20048 case 0x087: case 0x0A7: case 0x0C7: // stvebx, stvehx, stvewx
20049 case 0x0E7: case 0x1E7: // stvx, stvxl
20050 if (!allow_V) goto decode_noV;
20051 if (dis_av_store( theInstr )) goto decode_success;
20052 goto decode_failure;
20053
20054 /* VSX Load */
20055 case 0x00C: // lxsiwzx
20056 case 0x04C: // lxsiwax
20057 case 0x20C: // lxsspx
20058 case 0x24C: // lxsdx
20059 case 0x34C: // lxvd2x
20060 case 0x14C: // lxvdsx
20061 case 0x30C: // lxvw4x
20062 // All of these VSX load instructions use some VMX facilities, so
20063 // if allow_V is not set, we'll skip trying to decode.
20064 if (!allow_V) goto decode_noV;
20065
20066 if (dis_vx_load( theInstr )) goto decode_success;
20067 goto decode_failure;
20068
20069 /* VSX Store */
20070 case 0x08C: // stxsiwx
20071 case 0x28C: // stxsspx
20072 case 0x2CC: // stxsdx
20073 case 0x3CC: // stxvd2x
20074 case 0x38C: // stxvw4x
20075 // All of these VSX store instructions use some VMX facilities, so
20076 // if allow_V is not set, we'll skip trying to decode.
20077 if (!allow_V) goto decode_noV;
20078
20079 if (dis_vx_store( theInstr )) goto decode_success;
20080 goto decode_failure;
20081
20082 /* Miscellaneous ISA 2.06 instructions */
20083 case 0x1FA: // popcntd
20084 case 0x17A: // popcntw
20085 case 0x7A: // popcntb
20086 if (dis_int_logic( theInstr )) goto decode_success;
20087 goto decode_failure;
20088
20089 case 0x0FC: // bpermd
20090 if (!mode64) goto decode_failure;
20091 if (dis_int_logic( theInstr )) goto decode_success;
20092 goto decode_failure;
20093
20094 default:
20095 /* Deal with some other cases that we would otherwise have
20096 punted on. */
20097 /* --- ISEL (PowerISA_V2.05.pdf, p74) --- */
20098 /* only decode this insn when reserved bit 0 (31 in IBM's
20099 notation) is zero */
20100 if (IFIELD(theInstr, 0, 6) == (15<<1)) {
20101 UInt rT = ifieldRegDS( theInstr );
20102 UInt rA = ifieldRegA( theInstr );
20103 UInt rB = ifieldRegB( theInstr );
20104 UInt bi = ifieldRegC( theInstr );
20105 putIReg(
20106 rT,
20107 IRExpr_ITE( binop(Iop_CmpNE32, getCRbit( bi ), mkU32(0)),
20108 rA == 0 ? (mode64 ? mkU64(0) : mkU32(0))
20109 : getIReg(rA),
20110 getIReg(rB))
20111
20112 );
20113 DIP("isel r%u,r%u,r%u,crb%u\n", rT,rA,rB,bi);
20114 goto decode_success;
20115 }
20116 goto decode_failure;
20117 }
20118 break;
20119
20120
20121 case 0x04:
20122 /* AltiVec instructions */
20123
20124 opc2 = IFIELD(theInstr, 0, 6);
20125 switch (opc2) {
20126 /* AV Mult-Add, Mult-Sum */
20127 case 0x20: case 0x21: case 0x22: // vmhaddshs, vmhraddshs, vmladduhm
20128 case 0x24: case 0x25: case 0x26: // vmsumubm, vmsummbm, vmsumuhm
20129 case 0x27: case 0x28: case 0x29: // vmsumuhs, vmsumshm, vmsumshs
20130 if (!allow_V) goto decode_noV;
20131 if (dis_av_multarith( theInstr )) goto decode_success;
20132 goto decode_failure;
20133
20134 /* AV Permutations */
20135 case 0x2A: // vsel
20136 case 0x2B: // vperm
20137 case 0x2C: // vsldoi
20138 if (!allow_V) goto decode_noV;
20139 if (dis_av_permute( theInstr )) goto decode_success;
20140 goto decode_failure;
20141
20142 case 0x2D: // vpermxor
20143 if (!allow_isa_2_07) goto decode_noP8;
20144 if (dis_av_permute( theInstr )) goto decode_success;
20145 goto decode_failure;
20146
20147 /* AV Floating Point Mult-Add/Sub */
20148 case 0x2E: case 0x2F: // vmaddfp, vnmsubfp
20149 if (!allow_V) goto decode_noV;
20150 if (dis_av_fp_arith( theInstr )) goto decode_success;
20151 goto decode_failure;
20152
20153 case 0x3D: case 0x3C: // vaddecuq, vaddeuqm
20154 case 0x3F: case 0x3E: // vsubecuq, vsubeuqm
20155 if (!allow_V) goto decode_noV;
20156 if (dis_av_quad( theInstr)) goto decode_success;
20157 goto decode_failure;
20158
20159 default:
20160 break; // Fall through...
20161 }
20162
20163 opc2 = IFIELD(theInstr, 0, 9);
20164 switch (opc2) {
20165 /* BCD arithmetic */
20166 case 0x1: case 0x41: // bcdadd, bcdsub
20167 if (!allow_isa_2_07) goto decode_noP8;
20168 if (dis_av_bcd( theInstr )) goto decode_success;
20169 goto decode_failure;
20170
20171 default:
20172 break; // Fall through...
20173 }
20174
20175 opc2 = IFIELD(theInstr, 0, 11);
20176 switch (opc2) {
20177 /* AV Arithmetic */
20178 case 0x180: // vaddcuw
20179 case 0x000: case 0x040: case 0x080: // vaddubm, vadduhm, vadduwm
20180 case 0x200: case 0x240: case 0x280: // vaddubs, vadduhs, vadduws
20181 case 0x300: case 0x340: case 0x380: // vaddsbs, vaddshs, vaddsws
20182 case 0x580: // vsubcuw
20183 case 0x400: case 0x440: case 0x480: // vsububm, vsubuhm, vsubuwm
20184 case 0x600: case 0x640: case 0x680: // vsububs, vsubuhs, vsubuws
20185 case 0x700: case 0x740: case 0x780: // vsubsbs, vsubshs, vsubsws
20186 case 0x402: case 0x442: case 0x482: // vavgub, vavguh, vavguw
20187 case 0x502: case 0x542: case 0x582: // vavgsb, vavgsh, vavgsw
20188 case 0x002: case 0x042: case 0x082: // vmaxub, vmaxuh, vmaxuw
20189 case 0x102: case 0x142: case 0x182: // vmaxsb, vmaxsh, vmaxsw
20190 case 0x202: case 0x242: case 0x282: // vminub, vminuh, vminuw
20191 case 0x302: case 0x342: case 0x382: // vminsb, vminsh, vminsw
20192 case 0x008: case 0x048: // vmuloub, vmulouh
20193 case 0x108: case 0x148: // vmulosb, vmulosh
20194 case 0x208: case 0x248: // vmuleub, vmuleuh
20195 case 0x308: case 0x348: // vmulesb, vmulesh
20196 case 0x608: case 0x708: case 0x648: // vsum4ubs, vsum4sbs, vsum4shs
20197 case 0x688: case 0x788: // vsum2sws, vsumsws
20198 if (!allow_V) goto decode_noV;
20199 if (dis_av_arith( theInstr )) goto decode_success;
20200 goto decode_failure;
20201
20202 case 0x088: case 0x089: // vmulouw, vmuluwm
20203 case 0x0C0: case 0x0C2: // vaddudm, vmaxud
20204 case 0x1C2: case 0x2C2: case 0x3C2: // vnaxsd, vminud, vminsd
20205 case 0x188: case 0x288: case 0x388: // vmulosw, vmuleuw, vmulesw
20206 case 0x4C0: // vsubudm
20207 if (!allow_isa_2_07) goto decode_noP8;
20208 if (dis_av_arith( theInstr )) goto decode_success;
20209 goto decode_failure;
20210
20211 /* AV Polynomial Vector Multiply Add */
20212 case 0x408: case 0x448: // vpmsumb, vpmsumd
20213 case 0x488: case 0x4C8: // vpmsumw, vpmsumh
20214 if (!allow_isa_2_07) goto decode_noP8;
20215 if (dis_av_polymultarith( theInstr )) goto decode_success;
20216 goto decode_failure;
20217
20218 /* AV Rotate, Shift */
20219 case 0x004: case 0x044: case 0x084: // vrlb, vrlh, vrlw
20220 case 0x104: case 0x144: case 0x184: // vslb, vslh, vslw
20221 case 0x204: case 0x244: case 0x284: // vsrb, vsrh, vsrw
20222 case 0x304: case 0x344: case 0x384: // vsrab, vsrah, vsraw
20223 case 0x1C4: case 0x2C4: // vsl, vsr
20224 case 0x40C: case 0x44C: // vslo, vsro
20225 if (!allow_V) goto decode_noV;
20226 if (dis_av_shift( theInstr )) goto decode_success;
20227 goto decode_failure;
20228
20229 case 0x0C4: // vrld
20230 case 0x3C4: case 0x5C4: case 0x6C4: // vsrad, vsld, vsrd
20231 if (!allow_isa_2_07) goto decode_noP8;
20232 if (dis_av_shift( theInstr )) goto decode_success;
20233 goto decode_failure;
20234
20235 /* AV Logic */
20236 case 0x404: case 0x444: case 0x484: // vand, vandc, vor
20237 case 0x4C4: case 0x504: // vxor, vnor
20238 if (!allow_V) goto decode_noV;
20239 if (dis_av_logic( theInstr )) goto decode_success;
20240 goto decode_failure;
20241
20242 case 0x544: // vorc
20243 case 0x584: case 0x684: // vnand, veqv
20244 if (!allow_isa_2_07) goto decode_noP8;
20245 if (dis_av_logic( theInstr )) goto decode_success;
20246 goto decode_failure;
20247
20248 /* AV Processor Control */
20249 case 0x604: case 0x644: // mfvscr, mtvscr
20250 if (!allow_V) goto decode_noV;
20251 if (dis_av_procctl( theInstr )) goto decode_success;
20252 goto decode_failure;
20253
20254 /* AV Floating Point Arithmetic */
20255 case 0x00A: case 0x04A: // vaddfp, vsubfp
20256 case 0x10A: case 0x14A: case 0x18A: // vrefp, vrsqrtefp, vexptefp
20257 case 0x1CA: // vlogefp
20258 case 0x40A: case 0x44A: // vmaxfp, vminfp
20259 if (!allow_V) goto decode_noV;
20260 if (dis_av_fp_arith( theInstr )) goto decode_success;
20261 goto decode_failure;
20262
20263 /* AV Floating Point Round/Convert */
20264 case 0x20A: case 0x24A: case 0x28A: // vrfin, vrfiz, vrfip
20265 case 0x2CA: // vrfim
20266 case 0x30A: case 0x34A: case 0x38A: // vcfux, vcfsx, vctuxs
20267 case 0x3CA: // vctsxs
20268 if (!allow_V) goto decode_noV;
20269 if (dis_av_fp_convert( theInstr )) goto decode_success;
20270 goto decode_failure;
20271
20272 /* AV Merge, Splat */
20273 case 0x00C: case 0x04C: case 0x08C: // vmrghb, vmrghh, vmrghw
20274 case 0x10C: case 0x14C: case 0x18C: // vmrglb, vmrglh, vmrglw
20275 case 0x20C: case 0x24C: case 0x28C: // vspltb, vsplth, vspltw
20276 case 0x30C: case 0x34C: case 0x38C: // vspltisb, vspltish, vspltisw
20277 if (!allow_V) goto decode_noV;
20278 if (dis_av_permute( theInstr )) goto decode_success;
20279 goto decode_failure;
20280
20281 case 0x68C: case 0x78C: // vmrgow, vmrgew
20282 if (!allow_isa_2_07) goto decode_noP8;
20283 if (dis_av_permute( theInstr )) goto decode_success;
20284 goto decode_failure;
20285
20286 /* AV Pack, Unpack */
20287 case 0x00E: case 0x04E: case 0x08E: // vpkuhum, vpkuwum, vpkuhus
20288 case 0x0CE: // vpkuwus
20289 case 0x10E: case 0x14E: case 0x18E: // vpkshus, vpkswus, vpkshss
20290 case 0x1CE: // vpkswss
20291 case 0x20E: case 0x24E: case 0x28E: // vupkhsb, vupkhsh, vupklsb
20292 case 0x2CE: // vupklsh
20293 case 0x30E: case 0x34E: case 0x3CE: // vpkpx, vupkhpx, vupklpx
20294 if (!allow_V) goto decode_noV;
20295 if (dis_av_pack( theInstr )) goto decode_success;
20296 goto decode_failure;
20297
20298 case 0x44E: case 0x4CE: case 0x54E: // vpkudum, vpkudus, vpksdus
20299 case 0x5CE: case 0x64E: case 0x6cE: // vpksdss, vupkhsw, vupklsw
20300 if (!allow_isa_2_07) goto decode_noP8;
20301 if (dis_av_pack( theInstr )) goto decode_success;
20302 goto decode_failure;
20303
20304 case 0x508: case 0x509: // vcipher, vcipherlast
20305 case 0x548: case 0x549: // vncipher, vncipherlast
20306 case 0x5C8: // vsbox
20307 if (!allow_isa_2_07) goto decode_noP8;
20308 if (dis_av_cipher( theInstr )) goto decode_success;
20309 goto decode_failure;
20310
20311 case 0x6C2: case 0x682: // vshasigmaw, vshasigmad
20312 if (!allow_isa_2_07) goto decode_noP8;
20313 if (dis_av_hash( theInstr )) goto decode_success;
20314 goto decode_failure;
20315
20316 case 0x702: case 0x742: // vclzb, vclzh
20317 case 0x782: case 0x7c2: // vclzw, vclzd
20318 if (!allow_isa_2_07) goto decode_noP8;
20319 if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
20320 goto decode_failure;
20321
20322 case 0x703: case 0x743: // vpopcntb, vpopcnth
20323 case 0x783: case 0x7c3: // vpopcntw, vpopcntd
20324 if (!allow_isa_2_07) goto decode_noP8;
20325 if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
20326 goto decode_failure;
20327
20328 case 0x50c: // vgbbd
20329 if (!allow_isa_2_07) goto decode_noP8;
20330 if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
20331 goto decode_failure;
20332
20333 case 0x140: case 0x100: // vaddcuq, vadduqm
20334 case 0x540: case 0x500: // vsubcuq, vsubuqm
20335 case 0x54C: // vbpermq
20336 if (!allow_V) goto decode_noV;
20337 if (dis_av_quad( theInstr)) goto decode_success;
20338 goto decode_failure;
20339
20340 default:
20341 break; // Fall through...
20342 }
20343
20344 opc2 = IFIELD(theInstr, 0, 10);
20345 switch (opc2) {
20346
20347 /* AV Compare */
20348 case 0x006: case 0x046: case 0x086: // vcmpequb, vcmpequh, vcmpequw
20349 case 0x206: case 0x246: case 0x286: // vcmpgtub, vcmpgtuh, vcmpgtuw
20350 case 0x306: case 0x346: case 0x386: // vcmpgtsb, vcmpgtsh, vcmpgtsw
20351 if (!allow_V) goto decode_noV;
20352 if (dis_av_cmp( theInstr )) goto decode_success;
20353 goto decode_failure;
20354
20355 case 0x0C7: // vcmpequd
20356 case 0x2C7: // vcmpgtud
20357 case 0x3C7: // vcmpgtsd
20358 if (!allow_isa_2_07) goto decode_noP8;
20359 if (dis_av_cmp( theInstr )) goto decode_success;
20360 goto decode_failure;
20361
20362 /* AV Floating Point Compare */
20363 case 0x0C6: case 0x1C6: case 0x2C6: // vcmpeqfp, vcmpgefp, vcmpgtfp
20364 case 0x3C6: // vcmpbfp
20365 if (!allow_V) goto decode_noV;
20366 if (dis_av_fp_cmp( theInstr )) goto decode_success;
20367 goto decode_failure;
20368
20369 default:
20370 goto decode_failure;
20371 }
20372 break;
20373
20374 default:
20375 goto decode_failure;
20376
20377 decode_noF:
20378 vassert(!allow_F);
20379 vex_printf("disInstr(ppc): found the Floating Point instruction 0x%x that\n"
20380 "can't be handled by Valgrind on this host. This instruction\n"
20381 "requires a host that supports Floating Point instructions.\n",
20382 theInstr);
20383 goto not_supported;
20384 decode_noV:
20385 vassert(!allow_V);
20386 vex_printf("disInstr(ppc): found an AltiVec or an e500 instruction 0x%x\n"
20387 "that can't be handled by Valgrind. If this instruction is an\n"
20388 "Altivec instruction, Valgrind must be run on a host that supports"
20389 "AltiVec instructions. If the application was compiled for e500, then\n"
20390 "unfortunately Valgrind does not yet support e500 instructions.\n",
20391 theInstr);
20392 goto not_supported;
20393 decode_noVX:
20394 vassert(!allow_VX);
20395 vex_printf("disInstr(ppc): found the instruction 0x%x that is defined in the\n"
20396 "Power ISA 2.06 ABI but can't be handled by Valgrind on this host.\n"
20397 "This instruction \nrequires a host that supports the ISA 2.06 ABI.\n",
20398 theInstr);
20399 goto not_supported;
20400 decode_noFX:
20401 vassert(!allow_FX);
20402 vex_printf("disInstr(ppc): found the General Purpose-Optional instruction 0x%x\n"
20403 "that can't be handled by Valgrind on this host. This instruction\n"
20404 "requires a host that supports the General Purpose-Optional instructions.\n",
20405 theInstr);
20406 goto not_supported;
20407 decode_noGX:
20408 vassert(!allow_GX);
20409 vex_printf("disInstr(ppc): found the Graphics-Optional instruction 0x%x\n"
20410 "that can't be handled by Valgrind on this host. This instruction\n"
20411 "requires a host that supports the Graphic-Optional instructions.\n",
20412 theInstr);
20413 goto not_supported;
20414 decode_noDFP:
20415 vassert(!allow_DFP);
20416 vex_printf("disInstr(ppc): found the decimal floating point (DFP) instruction 0x%x\n"
20417 "that can't be handled by Valgrind on this host. This instruction\n"
20418 "requires a host that supports DFP instructions.\n",
20419 theInstr);
20420 goto not_supported;
20421 decode_noP8:
20422 vassert(!allow_isa_2_07);
20423 vex_printf("disInstr(ppc): found the Power 8 instruction 0x%x that can't be handled\n"
20424 "by Valgrind on this host. This instruction requires a host that\n"
20425 "supports Power 8 instructions.\n",
20426 theInstr);
20427 goto not_supported;
20428
20429
20430 decode_failure:
20431 /* All decode failures end up here. */
20432 opc2 = (theInstr) & 0x7FF;
20433 if (sigill_diag) {
20434 vex_printf("disInstr(ppc): unhandled instruction: "
20435 "0x%x\n", theInstr);
20436 vex_printf(" primary %d(0x%x), secondary %u(0x%x)\n",
20437 opc1, opc1, opc2, opc2);
20438 }
20439
20440 not_supported:
20441 /* Tell the dispatcher that this insn cannot be decoded, and so has
20442 not been executed, and (is currently) the next to be executed.
20443 CIA should be up-to-date since it made so at the start of each
20444 insn, but nevertheless be paranoid and update it again right
20445 now. */
20446 putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) );
20447 dres.len = 0;
20448 dres.whatNext = Dis_StopHere;
20449 dres.jk_StopHere = Ijk_NoDecode;
20450 dres.continueAt = 0;
20451 return dres;
20452 } /* switch (opc) for the main (primary) opcode switch. */
20453
20454 decode_success:
20455 /* All decode successes end up here. */
20456 switch (dres.whatNext) {
20457 case Dis_Continue:
20458 putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr + 4));
20459 break;
20460 case Dis_ResteerU:
20461 case Dis_ResteerC:
20462 putGST( PPC_GST_CIA, mkSzImm(ty, dres.continueAt));
20463 break;
20464 case Dis_StopHere:
20465 break;
20466 default:
20467 vassert(0);
20468 }
20469 DIP("\n");
20470
20471 if (dres.len == 0) {
20472 dres.len = 4;
20473 } else {
20474 vassert(dres.len == 20);
20475 }
20476 return dres;
20477 }
20478
20479 #undef DIP
20480 #undef DIS
20481
20482
20483 /*------------------------------------------------------------*/
20484 /*--- Top-level fn ---*/
20485 /*------------------------------------------------------------*/
20486
20487 /* Disassemble a single instruction into IR. The instruction
20488 is located in host memory at &guest_code[delta]. */
20489
disInstr_PPC(IRSB * irsb_IN,Bool (* resteerOkFn)(void *,Addr),Bool resteerCisOk,void * callback_opaque,const UChar * guest_code_IN,Long delta,Addr guest_IP,VexArch guest_arch,const VexArchInfo * archinfo,const VexAbiInfo * abiinfo,VexEndness host_endness_IN,Bool sigill_diag_IN)20490 DisResult disInstr_PPC ( IRSB* irsb_IN,
20491 Bool (*resteerOkFn) ( void*, Addr ),
20492 Bool resteerCisOk,
20493 void* callback_opaque,
20494 const UChar* guest_code_IN,
20495 Long delta,
20496 Addr guest_IP,
20497 VexArch guest_arch,
20498 const VexArchInfo* archinfo,
20499 const VexAbiInfo* abiinfo,
20500 VexEndness host_endness_IN,
20501 Bool sigill_diag_IN )
20502 {
20503 IRType ty;
20504 DisResult dres;
20505 UInt mask32, mask64;
20506 UInt hwcaps_guest = archinfo->hwcaps;
20507
20508 vassert(guest_arch == VexArchPPC32 || guest_arch == VexArchPPC64);
20509
20510 /* global -- ick */
20511 mode64 = guest_arch == VexArchPPC64;
20512 ty = mode64 ? Ity_I64 : Ity_I32;
20513 if (!mode64 && (host_endness_IN == VexEndnessLE)) {
20514 vex_printf("disInstr(ppc): Little Endian 32-bit mode is not supported\n");
20515 dres.len = 0;
20516 dres.whatNext = Dis_StopHere;
20517 dres.jk_StopHere = Ijk_NoDecode;
20518 dres.continueAt = 0;
20519 return dres;
20520 }
20521
20522 /* do some sanity checks */
20523 mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V
20524 | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX
20525 | VEX_HWCAPS_PPC32_DFP | VEX_HWCAPS_PPC32_ISA2_07;
20526
20527 mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX
20528 | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX | VEX_HWCAPS_PPC64_DFP
20529 | VEX_HWCAPS_PPC64_ISA2_07;
20530
20531 if (mode64) {
20532 vassert((hwcaps_guest & mask32) == 0);
20533 } else {
20534 vassert((hwcaps_guest & mask64) == 0);
20535 }
20536
20537 /* Set globals (see top of this file) */
20538 guest_code = guest_code_IN;
20539 irsb = irsb_IN;
20540 host_endness = host_endness_IN;
20541
20542 guest_CIA_curr_instr = mkSzAddr(ty, guest_IP);
20543 guest_CIA_bbstart = mkSzAddr(ty, guest_IP - delta);
20544
20545 dres = disInstr_PPC_WRK ( resteerOkFn, resteerCisOk, callback_opaque,
20546 delta, archinfo, abiinfo, sigill_diag_IN);
20547
20548 return dres;
20549 }
20550
20551
20552 /*------------------------------------------------------------*/
20553 /*--- Unused stuff ---*/
20554 /*------------------------------------------------------------*/
20555
20556 ///* A potentially more memcheck-friendly implementation of Clz32, with
20557 // the boundary case Clz32(0) = 32, which is what ppc requires. */
20558 //
20559 //static IRExpr* /* :: Ity_I32 */ verbose_Clz32 ( IRTemp arg )
20560 //{
20561 // /* Welcome ... to SSA R Us. */
20562 // IRTemp n1 = newTemp(Ity_I32);
20563 // IRTemp n2 = newTemp(Ity_I32);
20564 // IRTemp n3 = newTemp(Ity_I32);
20565 // IRTemp n4 = newTemp(Ity_I32);
20566 // IRTemp n5 = newTemp(Ity_I32);
20567 // IRTemp n6 = newTemp(Ity_I32);
20568 // IRTemp n7 = newTemp(Ity_I32);
20569 // IRTemp n8 = newTemp(Ity_I32);
20570 // IRTemp n9 = newTemp(Ity_I32);
20571 // IRTemp n10 = newTemp(Ity_I32);
20572 // IRTemp n11 = newTemp(Ity_I32);
20573 // IRTemp n12 = newTemp(Ity_I32);
20574 //
20575 // /* First, propagate the most significant 1-bit into all lower
20576 // positions in the word. */
20577 // /* unsigned int clz ( unsigned int n )
20578 // {
20579 // n |= (n >> 1);
20580 // n |= (n >> 2);
20581 // n |= (n >> 4);
20582 // n |= (n >> 8);
20583 // n |= (n >> 16);
20584 // return bitcount(~n);
20585 // }
20586 // */
20587 // assign(n1, mkexpr(arg));
20588 // assign(n2, binop(Iop_Or32, mkexpr(n1), binop(Iop_Shr32, mkexpr(n1), mkU8(1))));
20589 // assign(n3, binop(Iop_Or32, mkexpr(n2), binop(Iop_Shr32, mkexpr(n2), mkU8(2))));
20590 // assign(n4, binop(Iop_Or32, mkexpr(n3), binop(Iop_Shr32, mkexpr(n3), mkU8(4))));
20591 // assign(n5, binop(Iop_Or32, mkexpr(n4), binop(Iop_Shr32, mkexpr(n4), mkU8(8))));
20592 // assign(n6, binop(Iop_Or32, mkexpr(n5), binop(Iop_Shr32, mkexpr(n5), mkU8(16))));
20593 // /* This gives a word of the form 0---01---1. Now invert it, giving
20594 // a word of the form 1---10---0, then do a population-count idiom
20595 // (to count the 1s, which is the number of leading zeroes, or 32
20596 // if the original word was 0. */
20597 // assign(n7, unop(Iop_Not32, mkexpr(n6)));
20598 //
20599 // /* unsigned int bitcount ( unsigned int n )
20600 // {
20601 // n = n - ((n >> 1) & 0x55555555);
20602 // n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
20603 // n = (n + (n >> 4)) & 0x0F0F0F0F;
20604 // n = n + (n >> 8);
20605 // n = (n + (n >> 16)) & 0x3F;
20606 // return n;
20607 // }
20608 // */
20609 // assign(n8,
20610 // binop(Iop_Sub32,
20611 // mkexpr(n7),
20612 // binop(Iop_And32,
20613 // binop(Iop_Shr32, mkexpr(n7), mkU8(1)),
20614 // mkU32(0x55555555))));
20615 // assign(n9,
20616 // binop(Iop_Add32,
20617 // binop(Iop_And32, mkexpr(n8), mkU32(0x33333333)),
20618 // binop(Iop_And32,
20619 // binop(Iop_Shr32, mkexpr(n8), mkU8(2)),
20620 // mkU32(0x33333333))));
20621 // assign(n10,
20622 // binop(Iop_And32,
20623 // binop(Iop_Add32,
20624 // mkexpr(n9),
20625 // binop(Iop_Shr32, mkexpr(n9), mkU8(4))),
20626 // mkU32(0x0F0F0F0F)));
20627 // assign(n11,
20628 // binop(Iop_Add32,
20629 // mkexpr(n10),
20630 // binop(Iop_Shr32, mkexpr(n10), mkU8(8))));
20631 // assign(n12,
20632 // binop(Iop_Add32,
20633 // mkexpr(n11),
20634 // binop(Iop_Shr32, mkexpr(n11), mkU8(16))));
20635 // return
20636 // binop(Iop_And32, mkexpr(n12), mkU32(0x3F));
20637 //}
20638
20639 /*--------------------------------------------------------------------*/
20640 /*--- end guest_ppc_toIR.c ---*/
20641 /*--------------------------------------------------------------------*/
20642