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-2017 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 /* The OV32 and CA32 bits were added with ISA3.0 */
243 static Bool OV32_CA32_supported = False;
244 
245 #define SIGN_BIT  0x8000000000000000ULL
246 #define SIGN_MASK 0x7fffffffffffffffULL
247 #define SIGN_BIT32  0x80000000
248 #define SIGN_MASK32 0x7fffffff
249 
250 
251 /*------------------------------------------------------------*/
252 /*--- Debugging output                                     ---*/
253 /*------------------------------------------------------------*/
254 
255 #define DIP(format, args...)           \
256    if (vex_traceflags & VEX_TRACE_FE)  \
257       vex_printf(format, ## args)
258 
259 #define DIS(buf, format, args...)      \
260    if (vex_traceflags & VEX_TRACE_FE)  \
261       vex_sprintf(buf, format, ## args)
262 
263 
264 /*------------------------------------------------------------*/
265 /*--- Offsets of various parts of the ppc32/64 guest state ---*/
266 /*------------------------------------------------------------*/
267 
268 #define offsetofPPCGuestState(_x) \
269    (mode64 ? offsetof(VexGuestPPC64State, _x) : \
270              offsetof(VexGuestPPC32State, _x))
271 
272 #define OFFB_CIA         offsetofPPCGuestState(guest_CIA)
273 #define OFFB_IP_AT_SYSCALL offsetofPPCGuestState(guest_IP_AT_SYSCALL)
274 #define OFFB_SPRG3_RO    offsetofPPCGuestState(guest_SPRG3_RO)
275 #define OFFB_LR          offsetofPPCGuestState(guest_LR)
276 #define OFFB_CTR         offsetofPPCGuestState(guest_CTR)
277 #define OFFB_XER_SO      offsetofPPCGuestState(guest_XER_SO)
278 #define OFFB_XER_OV      offsetofPPCGuestState(guest_XER_OV)
279 #define OFFB_XER_OV32    offsetofPPCGuestState(guest_XER_OV32)
280 #define OFFB_XER_CA      offsetofPPCGuestState(guest_XER_CA)
281 #define OFFB_XER_CA32    offsetofPPCGuestState(guest_XER_CA32)
282 #define OFFB_XER_BC      offsetofPPCGuestState(guest_XER_BC)
283 #define OFFB_FPROUND     offsetofPPCGuestState(guest_FPROUND)
284 #define OFFB_DFPROUND    offsetofPPCGuestState(guest_DFPROUND)
285 #define OFFB_C_FPCC      offsetofPPCGuestState(guest_C_FPCC)
286 #define OFFB_VRSAVE      offsetofPPCGuestState(guest_VRSAVE)
287 #define OFFB_VSCR        offsetofPPCGuestState(guest_VSCR)
288 #define OFFB_EMNOTE      offsetofPPCGuestState(guest_EMNOTE)
289 #define OFFB_CMSTART     offsetofPPCGuestState(guest_CMSTART)
290 #define OFFB_CMLEN       offsetofPPCGuestState(guest_CMLEN)
291 #define OFFB_NRADDR      offsetofPPCGuestState(guest_NRADDR)
292 #define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2)
293 #define OFFB_TFHAR       offsetofPPCGuestState(guest_TFHAR)
294 #define OFFB_TEXASR      offsetofPPCGuestState(guest_TEXASR)
295 #define OFFB_TEXASRU     offsetofPPCGuestState(guest_TEXASRU)
296 #define OFFB_TFIAR       offsetofPPCGuestState(guest_TFIAR)
297 #define OFFB_PPR         offsetofPPCGuestState(guest_PPR)
298 #define OFFB_PSPB        offsetofPPCGuestState(guest_PSPB)
299 #define OFFB_DSCR        offsetofPPCGuestState(guest_DSCR)
300 
301 
302 /*------------------------------------------------------------*/
303 /*--- Extract instruction fields                          --- */
304 /*------------------------------------------------------------*/
305 
306 /* Extract field from insn, given idx (zero = lsb) and field length */
307 #define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1))
308 
309 /* Extract primary opcode, instr[31:26] */
ifieldOPC(UInt instr)310 static UChar ifieldOPC( UInt instr ) {
311    return toUChar( IFIELD( instr, 26, 6 ) );
312 }
313 
314 /* Extract 10-bit secondary opcode, instr[10:1] */
ifieldOPClo10(UInt instr)315 static UInt ifieldOPClo10 ( UInt instr) {
316    return IFIELD( instr, 1, 10 );
317 }
318 
319 /* Extract 9-bit secondary opcode, instr[9:1] */
ifieldOPClo9(UInt instr)320 static UInt ifieldOPClo9 ( UInt instr) {
321    return IFIELD( instr, 1, 9 );
322 }
323 
324 /* Extract 8-bit secondary opcode, instr[8:1] */
ifieldOPClo8(UInt instr)325 static UInt ifieldOPClo8 ( UInt instr) {
326    return IFIELD( instr, 1, 8 );
327 }
328 
329 /* Extract 5-bit secondary opcode, instr[5:1] */
ifieldOPClo5(UInt instr)330 static UInt ifieldOPClo5 ( UInt instr) {
331    return IFIELD( instr, 1, 5 );
332 }
333 
334 /* Extract 2-bit secondary opcode, instr[1:0] */
ifieldOPC0o2(UInt instr)335 static UInt ifieldOPC0o2 ( UInt instr) {
336    return IFIELD( instr, 0, 2 );
337 }
338 
339 /* Extract RD (destination register) field, instr[25:21] */
ifieldRegDS(UInt instr)340 static UChar ifieldRegDS( UInt instr ) {
341    return toUChar( IFIELD( instr, 21, 5 ) );
342 }
343 
344 /* Extract XT (destination register) field, instr[0,25:21] */
ifieldRegXT(UInt instr)345 static UChar ifieldRegXT ( UInt instr )
346 {
347   UChar upper_bit = toUChar (IFIELD (instr, 0, 1));
348   UChar lower_bits = toUChar (IFIELD (instr, 21, 5));
349   return (upper_bit << 5) | lower_bits;
350 }
351 
352 /* Extract XS (store source register) field, instr[0,25:21] */
ifieldRegXS(UInt instr)353 static inline UChar ifieldRegXS ( UInt instr )
354 {
355   return ifieldRegXT ( instr );
356 }
357 
358 /* Extract RA (1st source register) field, instr[20:16] */
ifieldRegA(UInt instr)359 static UChar ifieldRegA ( UInt instr ) {
360    return toUChar( IFIELD( instr, 16, 5 ) );
361 }
362 
363 /* Extract XA (1st source register) field, instr[2,20:16] */
ifieldRegXA(UInt instr)364 static UChar ifieldRegXA ( UInt instr )
365 {
366   UChar upper_bit = toUChar (IFIELD (instr, 2, 1));
367   UChar lower_bits = toUChar (IFIELD (instr, 16, 5));
368   return (upper_bit << 5) | lower_bits;
369 }
370 
371 /* Extract RB (2nd source register) field, instr[15:11] */
ifieldRegB(UInt instr)372 static UChar ifieldRegB ( UInt instr ) {
373    return toUChar( IFIELD( instr, 11, 5 ) );
374 }
375 
376 /* Extract XB (2nd source register) field, instr[1,15:11] */
ifieldRegXB(UInt instr)377 static UChar ifieldRegXB ( UInt instr )
378 {
379   UChar upper_bit = toUChar (IFIELD (instr, 1, 1));
380   UChar lower_bits = toUChar (IFIELD (instr, 11, 5));
381   return (upper_bit << 5) | lower_bits;
382 }
383 
384 /* Extract RC (3rd source register) field, instr[10:6] */
ifieldRegC(UInt instr)385 static UChar ifieldRegC ( UInt instr ) {
386    return toUChar( IFIELD( instr, 6, 5 ) );
387 }
388 
389 /* Extract XC (3rd source register) field, instr[3,10:6] */
ifieldRegXC(UInt instr)390 static UChar ifieldRegXC ( UInt instr )
391 {
392   UChar upper_bit = toUChar (IFIELD (instr, 3, 1));
393   UChar lower_bits = toUChar (IFIELD (instr, 6, 5));
394   return (upper_bit << 5) | lower_bits;
395 }
396 
397 /* Extract bit 10, instr[10] */
ifieldBIT10(UInt instr)398 static UChar ifieldBIT10 ( UInt instr ) {
399    return toUChar( IFIELD( instr, 10, 1 ) );
400 }
401 
402 /* Extract 2nd lowest bit, instr[1] */
ifieldBIT1(UInt instr)403 static UChar ifieldBIT1 ( UInt instr ) {
404    return toUChar( IFIELD( instr, 1, 1 ) );
405 }
406 
407 /* Extract lowest bit, instr[0] */
ifieldBIT0(UInt instr)408 static UChar ifieldBIT0 ( UInt instr ) {
409    return toUChar( instr & 0x1 );
410 }
411 
412 /* Extract unsigned bottom half, instr[15:0] */
ifieldUIMM16(UInt instr)413 static UInt ifieldUIMM16 ( UInt instr ) {
414    return instr & 0xFFFF;
415 }
416 
417 /* Extract unsigned bottom 26 bits, instr[25:0] */
ifieldUIMM26(UInt instr)418 static UInt ifieldUIMM26 ( UInt instr ) {
419    return instr & 0x3FFFFFF;
420 }
421 
422 /* Extract DM field, instr[9:8] */
ifieldDM(UInt instr)423 static UChar ifieldDM ( UInt instr ) {
424    return toUChar( IFIELD( instr, 8, 2 ) );
425 }
426 
427 /* Extract SHW field, instr[9:8] */
ifieldSHW(UInt instr)428 static inline UChar ifieldSHW ( UInt instr )
429 {
430   return ifieldDM ( instr );
431 }
432 
433 /*------------------------------------------------------------*/
434 /*--- Guest-state identifiers                              ---*/
435 /*------------------------------------------------------------*/
436 
437 typedef enum {
438     PPC_GST_CIA,    // Current Instruction Address
439     PPC_GST_LR,     // Link Register
440     PPC_GST_CTR,    // Count Register
441     PPC_GST_XER,    // Overflow, carry flags, byte count
442     PPC_GST_CR,     // Condition Register
443     PPC_GST_FPSCR,  // Floating Point Status/Control Register
444     PPC_GST_VRSAVE, // Vector Save/Restore Register
445     PPC_GST_VSCR,   // Vector Status and Control Register
446     PPC_GST_EMWARN, // Emulation warnings
447     PPC_GST_CMSTART,// For icbi: start of area to invalidate
448     PPC_GST_CMLEN,  // For icbi: length of area to invalidate
449     PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn
450     PPC_GST_SPRG3_RO, // SPRG3
451     PPC_GST_TFHAR,  // Transactional Failure Handler Address Register
452     PPC_GST_TFIAR,  // Transactional Failure Instruction Address Register
453     PPC_GST_TEXASR, // Transactional EXception And Summary Register
454     PPC_GST_TEXASRU, // Transactional EXception And Summary Register Upper
455     PPC_GST_PPR,     // Program Priority register
456     PPC_GST_PPR32,   // Upper 32-bits of Program Priority register
457     PPC_GST_PSPB,    /* Problem State Priority Boost register, Note, the
458                       * register is initialized to a non-zero value.  Currently
459                       * Valgrind is not supporting the register value to
460                       * automatically decrement. Could be added later if
461                       * needed.
462                       */
463     PPC_GST_DSCR,     // Data Stream Control Register
464     PPC_GST_MAX
465 } PPC_GST;
466 
467 #define MASK_FPSCR_RN     0x3ULL         // Binary floating point rounding mode
468 #define MASK_FPSCR_DRN    0x700000000ULL // Decimal floating point rounding mode
469 #define MASK_FPSCR_C_FPCC 0x1F000ULL     // Floating-Point Condition code FPCC
470 
471 #define MASK_VSCR_VALID 0x00010001
472 
473 
474 /*------------------------------------------------------------*/
475 /*---  FP Helpers                                          ---*/
476 /*------------------------------------------------------------*/
477 
478 /* Produce the 32-bit pattern corresponding to the supplied
479    float. */
float_to_bits(Float f)480 static UInt float_to_bits ( Float f )
481 {
482    union { UInt i; Float f; } u;
483    vassert(4 == sizeof(UInt));
484    vassert(4 == sizeof(Float));
485    vassert(4 == sizeof(u));
486    u.f = f;
487    return u.i;
488 }
489 
490 
491 /*------------------------------------------------------------*/
492 /*--- Misc Helpers                                         ---*/
493 /*------------------------------------------------------------*/
494 
495 /* Generate mask with 1's from 'begin' through 'end',
496    wrapping if begin > end.
497    begin->end works from right to left, 0=lsb
498 */
MASK32(UInt begin,UInt end)499 static UInt MASK32( UInt begin, UInt end )
500 {
501    UInt m1, m2, mask;
502    vassert(begin < 32);
503    vassert(end < 32);
504    m1   = ((UInt)(-1)) << begin;
505    m2   = ((UInt)(-1)) << end << 1;
506    mask = m1 ^ m2;
507    if (begin > end) mask = ~mask;  // wrap mask
508    return mask;
509 }
510 
MASK64(UInt begin,UInt end)511 static ULong MASK64( UInt begin, UInt end )
512 {
513    ULong m1, m2, mask;
514    vassert(begin < 64);
515    vassert(end < 64);
516    m1   = ((ULong)(-1)) << begin;
517    m2   = ((ULong)(-1)) << end << 1;
518    mask = m1 ^ m2;
519    if (begin > end) mask = ~mask;  // wrap mask
520    return mask;
521 }
522 
nextInsnAddr(void)523 static Addr64 nextInsnAddr( void )
524 {
525    return guest_CIA_curr_instr + 4;
526 }
527 
528 
529 /*------------------------------------------------------------*/
530 /*--- Helper bits and pieces for deconstructing the        ---*/
531 /*--- ppc32/64 insn stream.                                ---*/
532 /*------------------------------------------------------------*/
533 
534 /* Add a statement to the list held by "irsb". */
stmt(IRStmt * st)535 static void stmt ( IRStmt* st )
536 {
537    addStmtToIRSB( irsb, st );
538 }
539 
540 /* Generate a new temporary of the given type. */
newTemp(IRType ty)541 static IRTemp newTemp ( IRType ty )
542 {
543    vassert(isPlausibleIRType(ty));
544    return newIRTemp( irsb->tyenv, ty );
545 }
546 
547 /* Various simple conversions */
548 
extend_s_5to8(UChar x)549 static UChar extend_s_5to8 ( UChar x )
550 {
551    return toUChar((((Int)x) << 27) >> 27);
552 }
553 
extend_s_8to32(UChar x)554 static UInt extend_s_8to32( UChar x )
555 {
556    return (UInt)((((Int)x) << 24) >> 24);
557 }
558 
extend_s_16to32(UInt x)559 static UInt extend_s_16to32 ( UInt x )
560 {
561    return (UInt)((((Int)x) << 16) >> 16);
562 }
563 
extend_s_16to64(UInt x)564 static ULong extend_s_16to64 ( UInt x )
565 {
566    return (ULong)((((Long)x) << 48) >> 48);
567 }
568 
extend_s_26to64(UInt x)569 static ULong extend_s_26to64 ( UInt x )
570 {
571    return (ULong)((((Long)x) << 38) >> 38);
572 }
573 
extend_s_32to64(UInt x)574 static ULong extend_s_32to64 ( UInt x )
575 {
576    return (ULong)((((Long)x) << 32) >> 32);
577 }
578 
579 /* Do a proper-endian load of a 32-bit word, regardless of the endianness
580    of the underlying host. */
getUIntPPCendianly(const UChar * p)581 static UInt getUIntPPCendianly ( const UChar* p )
582 {
583    UInt w = 0;
584    if (host_endness == VexEndnessBE) {
585        w = (w << 8) | p[0];
586        w = (w << 8) | p[1];
587        w = (w << 8) | p[2];
588        w = (w << 8) | p[3];
589    } else {
590        w = (w << 8) | p[3];
591        w = (w << 8) | p[2];
592        w = (w << 8) | p[1];
593        w = (w << 8) | p[0];
594    }
595    return w;
596 }
597 
598 
599 /*------------------------------------------------------------*/
600 /*--- Helpers for constructing IR.                         ---*/
601 /*------------------------------------------------------------*/
602 
assign(IRTemp dst,IRExpr * e)603 static void assign ( IRTemp dst, IRExpr* e )
604 {
605    stmt( IRStmt_WrTmp(dst, e) );
606 }
607 
608 /* This generates a normal (non store-conditional) store. */
store(IRExpr * addr,IRExpr * data)609 static void store ( IRExpr* addr, IRExpr* data )
610 {
611    IRType tyA = typeOfIRExpr(irsb->tyenv, addr);
612    vassert(tyA == Ity_I32 || tyA == Ity_I64);
613 
614    if (host_endness == VexEndnessBE)
615       stmt( IRStmt_Store(Iend_BE, addr, data) );
616    else
617       stmt( IRStmt_Store(Iend_LE, addr, data) );
618 }
619 
unop(IROp op,IRExpr * a)620 static IRExpr* unop ( IROp op, IRExpr* a )
621 {
622    return IRExpr_Unop(op, a);
623 }
624 
binop(IROp op,IRExpr * a1,IRExpr * a2)625 static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
626 {
627    return IRExpr_Binop(op, a1, a2);
628 }
629 
triop(IROp op,IRExpr * a1,IRExpr * a2,IRExpr * a3)630 static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 )
631 {
632    return IRExpr_Triop(op, a1, a2, a3);
633 }
634 
qop(IROp op,IRExpr * a1,IRExpr * a2,IRExpr * a3,IRExpr * a4)635 static IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2,
636                               IRExpr* a3, IRExpr* a4 )
637 {
638    return IRExpr_Qop(op, a1, a2, a3, a4);
639 }
640 
mkexpr(IRTemp tmp)641 static IRExpr* mkexpr ( IRTemp tmp )
642 {
643    return IRExpr_RdTmp(tmp);
644 }
645 
646 #define mkU1(_n)  IRExpr_Const(IRConst_U1(_n))
647 
mkU8(UChar i)648 static IRExpr* mkU8 ( UChar i )
649 {
650    return IRExpr_Const(IRConst_U8(i));
651 }
652 
mkU16(UInt i)653 static IRExpr* mkU16 ( UInt i )
654 {
655    return IRExpr_Const(IRConst_U16(i));
656 }
657 
mkU32(UInt i)658 static IRExpr* mkU32 ( UInt i )
659 {
660    return IRExpr_Const(IRConst_U32(i));
661 }
662 
mkU64(ULong i)663 static IRExpr* mkU64 ( ULong i )
664 {
665    return IRExpr_Const(IRConst_U64(i));
666 }
667 
mkV128(UShort i)668 static IRExpr* mkV128 ( UShort i )
669 {
670    vassert(i == 0 || i == 0xffff);
671    return IRExpr_Const(IRConst_V128(i));
672 }
673 
674 /* This generates a normal (non load-linked) load. */
load(IRType ty,IRExpr * addr)675 static IRExpr* load ( IRType ty, IRExpr* addr )
676 {
677    if (host_endness == VexEndnessBE)
678       return IRExpr_Load(Iend_BE, ty, addr);
679    else
680       return IRExpr_Load(Iend_LE, ty, addr);
681 }
682 
stmt_load(IRTemp result,IRExpr * addr,IRExpr * storedata)683 static IRStmt* stmt_load ( IRTemp result,
684                            IRExpr* addr, IRExpr* storedata )
685 {
686    if (host_endness == VexEndnessBE)
687       return IRStmt_LLSC(Iend_BE, result, addr, storedata);
688    else
689       return IRStmt_LLSC(Iend_LE, result, addr, storedata);
690 }
691 
mkOR1(IRExpr * arg1,IRExpr * arg2)692 static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 )
693 {
694    vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
695    vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
696    return unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1),
697                                           unop(Iop_1Uto32, arg2)));
698 }
699 
mkAND1(IRExpr * arg1,IRExpr * arg2)700 static IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 )
701 {
702    vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
703    vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
704    return unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1),
705                                            unop(Iop_1Uto32, arg2)));
706 }
707 
mkXOr4_32(IRTemp t0,IRTemp t1,IRTemp t2,IRTemp t3)708 static inline IRExpr* mkXOr4_32( IRTemp t0, IRTemp t1, IRTemp t2,
709                                  IRTemp t3 )
710 {
711    return binop( Iop_Xor32,
712                  binop( Iop_Xor32, mkexpr( t0 ), mkexpr( t1 ) ),
713                  binop( Iop_Xor32, mkexpr( t2 ), mkexpr( t3 ) ) );
714 }
715 
mkOr3_V128(IRTemp t0,IRTemp t1,IRTemp t2)716 static inline IRExpr* mkOr3_V128( IRTemp t0, IRTemp t1, IRTemp t2 )
717 {
718    return binop( Iop_OrV128,
719                  mkexpr( t0 ),
720                  binop( Iop_OrV128, mkexpr( t1 ), mkexpr( t2 ) ) );
721 }
722 
mkOr4_V128(IRTemp t0,IRTemp t1,IRTemp t2,IRTemp t3)723 static inline IRExpr* mkOr4_V128( IRTemp t0, IRTemp t1, IRTemp t2,
724                                   IRTemp t3 )
725 {
726    return binop( Iop_OrV128,
727                  binop( Iop_OrV128, mkexpr( t0 ), mkexpr( t1 ) ),
728                  binop( Iop_OrV128, mkexpr( t2 ), mkexpr( t3 ) ) );
729 }
730 
mkOr4_V128_expr(IRExpr * t0,IRExpr * t1,IRExpr * t2,IRExpr * t3)731 static inline IRExpr* mkOr4_V128_expr( IRExpr* t0, IRExpr* t1, IRExpr* t2,
732                                        IRExpr* t3 )
733 {
734    /* arguments are already expressions */
735    return binop( Iop_OrV128,
736                  binop( Iop_OrV128, ( t0 ), ( t1 ) ),
737                  binop( Iop_OrV128, ( t2 ), ( t3 ) ) );
738 }
739 
mkNOT1(IRExpr * arg1)740 static IRExpr* mkNOT1 ( IRExpr* arg1 )
741 {
742    vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
743    return unop(Iop_32to1, unop(Iop_Not32, unop(Iop_1Uto32, arg1) ) );
744 }
745 
746 /* expand V128_8Ux16 to 2x V128_16Ux8's */
expand8Ux16(IRExpr * vIn,IRTemp * vEvn,IRTemp * vOdd)747 static void expand8Ux16( IRExpr* vIn,
748                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
749 {
750    IRTemp ones8x16 = newTemp(Ity_V128);
751 
752    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
753    vassert(vEvn && *vEvn == IRTemp_INVALID);
754    vassert(vOdd && *vOdd == IRTemp_INVALID);
755    *vEvn = newTemp(Ity_V128);
756    *vOdd = newTemp(Ity_V128);
757 
758    assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
759    assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) );
760    assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16),
761                         binop(Iop_ShrV128, vIn, mkU8(8))) );
762 }
763 
764 /* expand V128_8Sx16 to 2x V128_16Sx8's */
expand8Sx16(IRExpr * vIn,IRTemp * vEvn,IRTemp * vOdd)765 static void expand8Sx16( IRExpr* vIn,
766                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
767 {
768    IRTemp ones8x16 = newTemp(Ity_V128);
769 
770    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
771    vassert(vEvn && *vEvn == IRTemp_INVALID);
772    vassert(vOdd && *vOdd == IRTemp_INVALID);
773    *vEvn = newTemp(Ity_V128);
774    *vOdd = newTemp(Ity_V128);
775 
776    assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
777    assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) );
778    assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16),
779                         binop(Iop_ShrV128, vIn, mkU8(8))) );
780 }
781 
782 /* expand V128_16Uto8 to 2x V128_32Ux4's */
expand16Ux8(IRExpr * vIn,IRTemp * vEvn,IRTemp * vOdd)783 static void expand16Ux8( IRExpr* vIn,
784                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
785 {
786    IRTemp ones16x8 = newTemp(Ity_V128);
787 
788    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
789    vassert(vEvn && *vEvn == IRTemp_INVALID);
790    vassert(vOdd && *vOdd == IRTemp_INVALID);
791    *vEvn = newTemp(Ity_V128);
792    *vOdd = newTemp(Ity_V128);
793 
794    assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
795    assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) );
796    assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8),
797                         binop(Iop_ShrV128, vIn, mkU8(16))) );
798 }
799 
800 /* expand V128_16Sto8 to 2x V128_32Sx4's */
expand16Sx8(IRExpr * vIn,IRTemp * vEvn,IRTemp * vOdd)801 static void expand16Sx8( IRExpr* vIn,
802                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
803 {
804    IRTemp ones16x8 = newTemp(Ity_V128);
805 
806    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
807    vassert(vEvn && *vEvn == IRTemp_INVALID);
808    vassert(vOdd && *vOdd == IRTemp_INVALID);
809    *vEvn = newTemp(Ity_V128);
810    *vOdd = newTemp(Ity_V128);
811 
812    assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
813    assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) );
814    assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8),
815                        binop(Iop_ShrV128, vIn, mkU8(16))) );
816 }
817 
818 /* break V128 to 4xF64's*/
breakV128to4xF64(IRExpr * t128,IRTemp * t3,IRTemp * t2,IRTemp * t1,IRTemp * t0)819 static void breakV128to4xF64( IRExpr* t128,
820                               /*OUTs*/
821                               IRTemp* t3, IRTemp* t2,
822                               IRTemp* t1, IRTemp* t0 )
823 {
824    IRTemp hi64 = newTemp(Ity_I64);
825    IRTemp lo64 = newTemp(Ity_I64);
826 
827    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
828    vassert(t0 && *t0 == IRTemp_INVALID);
829    vassert(t1 && *t1 == IRTemp_INVALID);
830    vassert(t2 && *t2 == IRTemp_INVALID);
831    vassert(t3 && *t3 == IRTemp_INVALID);
832    *t0 = newTemp(Ity_F64);
833    *t1 = newTemp(Ity_F64);
834    *t2 = newTemp(Ity_F64);
835    *t3 = newTemp(Ity_F64);
836 
837    assign( hi64, unop(Iop_V128HIto64, t128) );
838    assign( lo64, unop(Iop_V128to64,   t128) );
839    assign( *t3,
840            unop( Iop_F32toF64,
841                  unop( Iop_ReinterpI32asF32,
842                        unop( Iop_64HIto32, mkexpr( hi64 ) ) ) ) );
843    assign( *t2,
844            unop( Iop_F32toF64,
845                  unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( hi64 ) ) ) ) );
846    assign( *t1,
847            unop( Iop_F32toF64,
848                  unop( Iop_ReinterpI32asF32,
849                        unop( Iop_64HIto32, mkexpr( lo64 ) ) ) ) );
850    assign( *t0,
851            unop( Iop_F32toF64,
852                  unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( lo64 ) ) ) ) );
853 }
854 
855 
856 /* break V128 to 4xI32's, then sign-extend to I64's */
breakV128to4x64S(IRExpr * t128,IRTemp * t3,IRTemp * t2,IRTemp * t1,IRTemp * t0)857 static void breakV128to4x64S( IRExpr* t128,
858                               /*OUTs*/
859                               IRTemp* t3, IRTemp* t2,
860                               IRTemp* t1, IRTemp* t0 )
861 {
862    IRTemp hi64 = newTemp(Ity_I64);
863    IRTemp lo64 = newTemp(Ity_I64);
864 
865    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
866    vassert(t0 && *t0 == IRTemp_INVALID);
867    vassert(t1 && *t1 == IRTemp_INVALID);
868    vassert(t2 && *t2 == IRTemp_INVALID);
869    vassert(t3 && *t3 == IRTemp_INVALID);
870    *t0 = newTemp(Ity_I64);
871    *t1 = newTemp(Ity_I64);
872    *t2 = newTemp(Ity_I64);
873    *t3 = newTemp(Ity_I64);
874 
875    assign( hi64, unop(Iop_V128HIto64, t128) );
876    assign( lo64, unop(Iop_V128to64,   t128) );
877    assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) );
878    assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(hi64))) );
879    assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) );
880    assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(lo64))) );
881 }
882 
883 /* break V128 to 4xI32's, then zero-extend to I64's */
breakV128to4x64U(IRExpr * t128,IRTemp * t3,IRTemp * t2,IRTemp * t1,IRTemp * t0)884 static void breakV128to4x64U ( IRExpr* t128,
885                                /*OUTs*/
886                                IRTemp* t3, IRTemp* t2,
887                                IRTemp* t1, IRTemp* t0 )
888 {
889    IRTemp hi64 = newTemp(Ity_I64);
890    IRTemp lo64 = newTemp(Ity_I64);
891 
892    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
893    vassert(t0 && *t0 == IRTemp_INVALID);
894    vassert(t1 && *t1 == IRTemp_INVALID);
895    vassert(t2 && *t2 == IRTemp_INVALID);
896    vassert(t3 && *t3 == IRTemp_INVALID);
897    *t0 = newTemp(Ity_I64);
898    *t1 = newTemp(Ity_I64);
899    *t2 = newTemp(Ity_I64);
900    *t3 = newTemp(Ity_I64);
901 
902    assign( hi64, unop(Iop_V128HIto64, t128) );
903    assign( lo64, unop(Iop_V128to64,   t128) );
904    assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) );
905    assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(hi64))) );
906    assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) );
907    assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(lo64))) );
908 }
909 
breakV128to4x32(IRExpr * t128,IRTemp * t3,IRTemp * t2,IRTemp * t1,IRTemp * t0)910 static void breakV128to4x32( IRExpr* t128,
911                               /*OUTs*/
912                               IRTemp* t3, IRTemp* t2,
913                               IRTemp* t1, IRTemp* t0 )
914 {
915    IRTemp hi64 = newTemp(Ity_I64);
916    IRTemp lo64 = newTemp(Ity_I64);
917 
918    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
919    vassert(t0 && *t0 == IRTemp_INVALID);
920    vassert(t1 && *t1 == IRTemp_INVALID);
921    vassert(t2 && *t2 == IRTemp_INVALID);
922    vassert(t3 && *t3 == IRTemp_INVALID);
923    *t0 = newTemp(Ity_I32);
924    *t1 = newTemp(Ity_I32);
925    *t2 = newTemp(Ity_I32);
926    *t3 = newTemp(Ity_I32);
927 
928    assign( hi64, unop(Iop_V128HIto64, t128) );
929    assign( lo64, unop(Iop_V128to64,   t128) );
930    assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) );
931    assign( *t2, unop(Iop_64to32,   mkexpr(hi64)) );
932    assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) );
933    assign( *t0, unop(Iop_64to32,   mkexpr(lo64)) );
934 }
935 
mkV128from32(IRTemp t3,IRTemp t2,IRTemp t1,IRTemp t0)936 static IRExpr* mkV128from32( IRTemp t3, IRTemp t2,
937                                IRTemp t1, IRTemp t0 )
938 {
939    return
940       binop( Iop_64HLtoV128,
941              binop(Iop_32HLto64, mkexpr(t3), mkexpr(t2)),
942              binop(Iop_32HLto64, mkexpr(t1), mkexpr(t0))
943    );
944 }
945 
extract_field_from_vector(IRTemp vB,IRExpr * index,UInt mask)946 static IRExpr* extract_field_from_vector( IRTemp vB, IRExpr* index, UInt mask)
947 {
948    /* vB is a vector, extract bits starting at index to size of mask */
949    return unop( Iop_V128to64,
950                 binop( Iop_AndV128,
951                        binop( Iop_ShrV128,
952                               mkexpr( vB ),
953                               unop( Iop_64to8,
954                                     binop( Iop_Mul64, index,
955                                            mkU64( 8 ) ) ) ),
956                        binop( Iop_64HLtoV128,
957                               mkU64( 0x0 ),
958                               mkU64( mask ) ) ) );
959 }
960 
961 /* Signed saturating narrow 64S to 32 */
mkQNarrow64Sto32(IRExpr * t64)962 static IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 )
963 {
964    IRTemp hi32 = newTemp(Ity_I32);
965    IRTemp lo32 = newTemp(Ity_I32);
966 
967    vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
968 
969    assign( hi32, unop(Iop_64HIto32, t64));
970    assign( lo32, unop(Iop_64to32,   t64));
971 
972    return IRExpr_ITE(
973              /* if (hi32 == (lo32 >>s 31)) */
974              binop(Iop_CmpEQ32, mkexpr(hi32),
975                    binop( Iop_Sar32, mkexpr(lo32), mkU8(31))),
976              /* then: within signed-32 range: lo half good enough */
977              mkexpr(lo32),
978              /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */
979              binop(Iop_Add32, mkU32(0x7FFFFFFF),
980                    binop(Iop_Shr32, mkexpr(hi32), mkU8(31))));
981 }
982 
983 /* Unsigned saturating narrow 64S to 32 */
mkQNarrow64Uto32(IRExpr * t64)984 static IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 )
985 {
986    IRTemp hi32 = newTemp(Ity_I32);
987    IRTemp lo32 = newTemp(Ity_I32);
988 
989    vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
990 
991    assign( hi32, unop(Iop_64HIto32, t64));
992    assign( lo32, unop(Iop_64to32,   t64));
993 
994    return IRExpr_ITE(
995             /* if (top 32 bits of t64 are 0) */
996             binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0)),
997             /* then: within unsigned-32 range: lo half good enough */
998             mkexpr(lo32),
999             /* else: positive saturate -> 0xFFFFFFFF */
1000             mkU32(0xFFFFFFFF));
1001 }
1002 
1003 /* Signed saturate narrow 64->32, combining to V128 */
mkV128from4x64S(IRExpr * t3,IRExpr * t2,IRExpr * t1,IRExpr * t0)1004 static IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2,
1005                                  IRExpr* t1, IRExpr* t0 )
1006 {
1007    vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
1008    vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
1009    vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
1010    vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
1011    return binop(Iop_64HLtoV128,
1012                 binop(Iop_32HLto64,
1013                       mkQNarrow64Sto32( t3 ),
1014                       mkQNarrow64Sto32( t2 )),
1015                 binop(Iop_32HLto64,
1016                       mkQNarrow64Sto32( t1 ),
1017                       mkQNarrow64Sto32( t0 )));
1018 }
1019 
1020 /* Unsigned saturate narrow 64->32, combining to V128 */
mkV128from4x64U(IRExpr * t3,IRExpr * t2,IRExpr * t1,IRExpr * t0)1021 static IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2,
1022                                  IRExpr* t1, IRExpr* t0 )
1023 {
1024    vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
1025    vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
1026    vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
1027    vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
1028    return binop(Iop_64HLtoV128,
1029                 binop(Iop_32HLto64,
1030                       mkQNarrow64Uto32( t3 ),
1031                       mkQNarrow64Uto32( t2 )),
1032                 binop(Iop_32HLto64,
1033                       mkQNarrow64Uto32( t1 ),
1034                       mkQNarrow64Uto32( t0 )));
1035 }
1036 
1037 /* Simulate irops Iop_MullOdd*, since we don't have them  */
1038 #define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \
1039       binop(Iop_MullEven8Ux16, \
1040             binop(Iop_ShrV128, expr_vA, mkU8(8)), \
1041             binop(Iop_ShrV128, expr_vB, mkU8(8)))
1042 
1043 #define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \
1044       binop(Iop_MullEven8Sx16, \
1045             binop(Iop_ShrV128, expr_vA, mkU8(8)), \
1046             binop(Iop_ShrV128, expr_vB, mkU8(8)))
1047 
1048 #define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \
1049       binop(Iop_MullEven16Ux8, \
1050             binop(Iop_ShrV128, expr_vA, mkU8(16)), \
1051             binop(Iop_ShrV128, expr_vB, mkU8(16)))
1052 
1053 #define MK_Iop_MullOdd32Ux4( expr_vA, expr_vB ) \
1054       binop(Iop_MullEven32Ux4, \
1055             binop(Iop_ShrV128, expr_vA, mkU8(32)), \
1056             binop(Iop_ShrV128, expr_vB, mkU8(32)))
1057 
1058 #define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \
1059       binop(Iop_MullEven16Sx8, \
1060             binop(Iop_ShrV128, expr_vA, mkU8(16)), \
1061             binop(Iop_ShrV128, expr_vB, mkU8(16)))
1062 
1063 #define MK_Iop_MullOdd32Sx4( expr_vA, expr_vB ) \
1064       binop(Iop_MullEven32Sx4, \
1065             binop(Iop_ShrV128, expr_vA, mkU8(32)), \
1066             binop(Iop_ShrV128, expr_vB, mkU8(32)))
1067 
1068 
mk64lo32Sto64(IRExpr * src)1069 static IRExpr* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr* src )
1070 {
1071    vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
1072    return unop(Iop_32Sto64, unop(Iop_64to32, src));
1073 }
1074 
mk64lo32Uto64(IRExpr * src)1075 static IRExpr* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr* src )
1076 {
1077    vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
1078    return unop(Iop_32Uto64, unop(Iop_64to32, src));
1079 }
1080 
mkSzOp(IRType ty,IROp op8)1081 static IROp mkSzOp ( IRType ty, IROp op8 )
1082 {
1083    Int adj;
1084    vassert(ty == Ity_I8  || ty == Ity_I16 ||
1085            ty == Ity_I32 || ty == Ity_I64);
1086    vassert(op8 == Iop_Add8   || op8 == Iop_Sub8   || op8 == Iop_Mul8 ||
1087            op8 == Iop_Or8    || op8 == Iop_And8   || op8 == Iop_Xor8 ||
1088            op8 == Iop_Shl8   || op8 == Iop_Shr8   || op8 == Iop_Sar8 ||
1089            op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 ||
1090            op8 == Iop_Not8 );
1091    adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3));
1092    return adj + op8;
1093 }
1094 
1095 /* Make sure we get valid 32 and 64bit addresses */
mkSzAddr(IRType ty,Addr64 addr)1096 static Addr64 mkSzAddr ( IRType ty, Addr64 addr )
1097 {
1098    vassert(ty == Ity_I32 || ty == Ity_I64);
1099    return ( ty == Ity_I64 ?
1100             (Addr64)addr :
1101             (Addr64)extend_s_32to64( toUInt(addr) ) );
1102 }
1103 
1104 /* sz, ULong -> IRExpr */
mkSzImm(IRType ty,ULong imm64)1105 static IRExpr* mkSzImm ( IRType ty, ULong imm64 )
1106 {
1107    vassert(ty == Ity_I32 || ty == Ity_I64);
1108    return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64);
1109 }
1110 
1111 /* sz, ULong -> IRConst */
mkSzConst(IRType ty,ULong imm64)1112 static IRConst* mkSzConst ( IRType ty, ULong imm64 )
1113 {
1114    vassert(ty == Ity_I32 || ty == Ity_I64);
1115    return ( ty == Ity_I64 ?
1116             IRConst_U64(imm64) :
1117             IRConst_U32((UInt)imm64) );
1118 }
1119 
1120 /* Sign extend imm16 -> IRExpr* */
mkSzExtendS16(IRType ty,UInt imm16)1121 static IRExpr* mkSzExtendS16 ( IRType ty, UInt imm16 )
1122 {
1123    vassert(ty == Ity_I32 || ty == Ity_I64);
1124    return ( ty == Ity_I64 ?
1125             mkU64(extend_s_16to64(imm16)) :
1126             mkU32(extend_s_16to32(imm16)) );
1127 }
1128 
1129 /* Sign extend imm32 -> IRExpr* */
mkSzExtendS32(IRType ty,UInt imm32)1130 static IRExpr* mkSzExtendS32 ( IRType ty, UInt imm32 )
1131 {
1132    vassert(ty == Ity_I32 || ty == Ity_I64);
1133    return ( ty == Ity_I64 ?
1134             mkU64(extend_s_32to64(imm32)) :
1135             mkU32(imm32) );
1136 }
1137 
1138 /* IR narrows I32/I64 -> I8/I16/I32 */
mkNarrowTo8(IRType ty,IRExpr * src)1139 static IRExpr* mkNarrowTo8 ( IRType ty, IRExpr* src )
1140 {
1141    vassert(ty == Ity_I32 || ty == Ity_I64);
1142    return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src);
1143 }
1144 
mkNarrowTo16(IRType ty,IRExpr * src)1145 static IRExpr* mkNarrowTo16 ( IRType ty, IRExpr* src )
1146 {
1147    vassert(ty == Ity_I32 || ty == Ity_I64);
1148    return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src);
1149 }
1150 
mkNarrowTo32(IRType ty,IRExpr * src)1151 static IRExpr* mkNarrowTo32 ( IRType ty, IRExpr* src )
1152 {
1153    vassert(ty == Ity_I32 || ty == Ity_I64);
1154    return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
1155 }
1156 
1157 /* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */
mkWidenFrom8(IRType ty,IRExpr * src,Bool sined)1158 static IRExpr* mkWidenFrom8 ( IRType ty, IRExpr* src, Bool sined )
1159 {
1160    IROp op;
1161    vassert(ty == Ity_I32 || ty == Ity_I64);
1162    if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64;
1163    else       op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64;
1164    return unop(op, src);
1165 }
1166 
mkWidenFrom16(IRType ty,IRExpr * src,Bool sined)1167 static IRExpr* mkWidenFrom16 ( IRType ty, IRExpr* src, Bool sined )
1168 {
1169    IROp op;
1170    vassert(ty == Ity_I32 || ty == Ity_I64);
1171    if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64;
1172    else       op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64;
1173    return unop(op, src);
1174 }
1175 
mkWidenFrom32(IRType ty,IRExpr * src,Bool sined)1176 static IRExpr* mkWidenFrom32 ( IRType ty, IRExpr* src, Bool sined )
1177 {
1178    vassert(ty == Ity_I32 || ty == Ity_I64);
1179    if (ty == Ity_I32)
1180       return src;
1181    return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
1182 }
1183 
1184 
integerGuestRegOffset(UInt archreg)1185 static Int integerGuestRegOffset ( UInt archreg )
1186 {
1187    vassert(archreg < 32);
1188 
1189    // jrs: probably not necessary; only matters if we reference sub-parts
1190    // of the ppc registers, but that isn't the case
1191    // later: this might affect Altivec though?
1192 
1193    switch (archreg) {
1194    case  0: return offsetofPPCGuestState(guest_GPR0);
1195    case  1: return offsetofPPCGuestState(guest_GPR1);
1196    case  2: return offsetofPPCGuestState(guest_GPR2);
1197    case  3: return offsetofPPCGuestState(guest_GPR3);
1198    case  4: return offsetofPPCGuestState(guest_GPR4);
1199    case  5: return offsetofPPCGuestState(guest_GPR5);
1200    case  6: return offsetofPPCGuestState(guest_GPR6);
1201    case  7: return offsetofPPCGuestState(guest_GPR7);
1202    case  8: return offsetofPPCGuestState(guest_GPR8);
1203    case  9: return offsetofPPCGuestState(guest_GPR9);
1204    case 10: return offsetofPPCGuestState(guest_GPR10);
1205    case 11: return offsetofPPCGuestState(guest_GPR11);
1206    case 12: return offsetofPPCGuestState(guest_GPR12);
1207    case 13: return offsetofPPCGuestState(guest_GPR13);
1208    case 14: return offsetofPPCGuestState(guest_GPR14);
1209    case 15: return offsetofPPCGuestState(guest_GPR15);
1210    case 16: return offsetofPPCGuestState(guest_GPR16);
1211    case 17: return offsetofPPCGuestState(guest_GPR17);
1212    case 18: return offsetofPPCGuestState(guest_GPR18);
1213    case 19: return offsetofPPCGuestState(guest_GPR19);
1214    case 20: return offsetofPPCGuestState(guest_GPR20);
1215    case 21: return offsetofPPCGuestState(guest_GPR21);
1216    case 22: return offsetofPPCGuestState(guest_GPR22);
1217    case 23: return offsetofPPCGuestState(guest_GPR23);
1218    case 24: return offsetofPPCGuestState(guest_GPR24);
1219    case 25: return offsetofPPCGuestState(guest_GPR25);
1220    case 26: return offsetofPPCGuestState(guest_GPR26);
1221    case 27: return offsetofPPCGuestState(guest_GPR27);
1222    case 28: return offsetofPPCGuestState(guest_GPR28);
1223    case 29: return offsetofPPCGuestState(guest_GPR29);
1224    case 30: return offsetofPPCGuestState(guest_GPR30);
1225    case 31: return offsetofPPCGuestState(guest_GPR31);
1226    default: break;
1227    }
1228    vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/
1229 }
1230 
getIReg(UInt archreg)1231 static IRExpr* getIReg ( UInt archreg )
1232 {
1233    IRType ty = mode64 ? Ity_I64 : Ity_I32;
1234    vassert(archreg < 32);
1235    return IRExpr_Get( integerGuestRegOffset(archreg), ty );
1236 }
1237 
1238 /* Ditto, but write to a reg instead. */
putIReg(UInt archreg,IRExpr * e)1239 static void putIReg ( UInt archreg, IRExpr* e )
1240 {
1241    IRType ty = mode64 ? Ity_I64 : Ity_I32;
1242    vassert(archreg < 32);
1243    vassert(typeOfIRExpr(irsb->tyenv, e) == ty );
1244    stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) );
1245 }
1246 
1247 
1248 /* Floating point egisters are mapped to VSX registers[0..31]. */
floatGuestRegOffset(UInt archreg)1249 static Int floatGuestRegOffset ( UInt archreg )
1250 {
1251    vassert(archreg < 32);
1252 
1253    if (host_endness == VexEndnessLE) {
1254       switch (archreg) {
1255          case  0: return offsetofPPCGuestState(guest_VSR0) + 8;
1256          case  1: return offsetofPPCGuestState(guest_VSR1) + 8;
1257          case  2: return offsetofPPCGuestState(guest_VSR2) + 8;
1258          case  3: return offsetofPPCGuestState(guest_VSR3) + 8;
1259          case  4: return offsetofPPCGuestState(guest_VSR4) + 8;
1260          case  5: return offsetofPPCGuestState(guest_VSR5) + 8;
1261          case  6: return offsetofPPCGuestState(guest_VSR6) + 8;
1262          case  7: return offsetofPPCGuestState(guest_VSR7) + 8;
1263          case  8: return offsetofPPCGuestState(guest_VSR8) + 8;
1264          case  9: return offsetofPPCGuestState(guest_VSR9) + 8;
1265          case 10: return offsetofPPCGuestState(guest_VSR10) + 8;
1266          case 11: return offsetofPPCGuestState(guest_VSR11) + 8;
1267          case 12: return offsetofPPCGuestState(guest_VSR12) + 8;
1268          case 13: return offsetofPPCGuestState(guest_VSR13) + 8;
1269          case 14: return offsetofPPCGuestState(guest_VSR14) + 8;
1270          case 15: return offsetofPPCGuestState(guest_VSR15) + 8;
1271          case 16: return offsetofPPCGuestState(guest_VSR16) + 8;
1272          case 17: return offsetofPPCGuestState(guest_VSR17) + 8;
1273          case 18: return offsetofPPCGuestState(guest_VSR18) + 8;
1274          case 19: return offsetofPPCGuestState(guest_VSR19) + 8;
1275          case 20: return offsetofPPCGuestState(guest_VSR20) + 8;
1276          case 21: return offsetofPPCGuestState(guest_VSR21) + 8;
1277          case 22: return offsetofPPCGuestState(guest_VSR22) + 8;
1278          case 23: return offsetofPPCGuestState(guest_VSR23) + 8;
1279          case 24: return offsetofPPCGuestState(guest_VSR24) + 8;
1280          case 25: return offsetofPPCGuestState(guest_VSR25) + 8;
1281          case 26: return offsetofPPCGuestState(guest_VSR26) + 8;
1282          case 27: return offsetofPPCGuestState(guest_VSR27) + 8;
1283          case 28: return offsetofPPCGuestState(guest_VSR28) + 8;
1284          case 29: return offsetofPPCGuestState(guest_VSR29) + 8;
1285          case 30: return offsetofPPCGuestState(guest_VSR30) + 8;
1286          case 31: return offsetofPPCGuestState(guest_VSR31) + 8;
1287          default: break;
1288       }
1289    } else {
1290       switch (archreg) {
1291          case  0: return offsetofPPCGuestState(guest_VSR0);
1292          case  1: return offsetofPPCGuestState(guest_VSR1);
1293          case  2: return offsetofPPCGuestState(guest_VSR2);
1294          case  3: return offsetofPPCGuestState(guest_VSR3);
1295          case  4: return offsetofPPCGuestState(guest_VSR4);
1296          case  5: return offsetofPPCGuestState(guest_VSR5);
1297          case  6: return offsetofPPCGuestState(guest_VSR6);
1298          case  7: return offsetofPPCGuestState(guest_VSR7);
1299          case  8: return offsetofPPCGuestState(guest_VSR8);
1300          case  9: return offsetofPPCGuestState(guest_VSR9);
1301          case 10: return offsetofPPCGuestState(guest_VSR10);
1302          case 11: return offsetofPPCGuestState(guest_VSR11);
1303          case 12: return offsetofPPCGuestState(guest_VSR12);
1304          case 13: return offsetofPPCGuestState(guest_VSR13);
1305          case 14: return offsetofPPCGuestState(guest_VSR14);
1306          case 15: return offsetofPPCGuestState(guest_VSR15);
1307          case 16: return offsetofPPCGuestState(guest_VSR16);
1308          case 17: return offsetofPPCGuestState(guest_VSR17);
1309          case 18: return offsetofPPCGuestState(guest_VSR18);
1310          case 19: return offsetofPPCGuestState(guest_VSR19);
1311          case 20: return offsetofPPCGuestState(guest_VSR20);
1312          case 21: return offsetofPPCGuestState(guest_VSR21);
1313          case 22: return offsetofPPCGuestState(guest_VSR22);
1314          case 23: return offsetofPPCGuestState(guest_VSR23);
1315          case 24: return offsetofPPCGuestState(guest_VSR24);
1316          case 25: return offsetofPPCGuestState(guest_VSR25);
1317          case 26: return offsetofPPCGuestState(guest_VSR26);
1318          case 27: return offsetofPPCGuestState(guest_VSR27);
1319          case 28: return offsetofPPCGuestState(guest_VSR28);
1320          case 29: return offsetofPPCGuestState(guest_VSR29);
1321          case 30: return offsetofPPCGuestState(guest_VSR30);
1322          case 31: return offsetofPPCGuestState(guest_VSR31);
1323          default: break;
1324       }
1325    }
1326    vpanic("floatGuestRegOffset(ppc)"); /*notreached*/
1327 }
1328 
getFReg(UInt archreg)1329 static IRExpr* getFReg ( UInt archreg )
1330 {
1331    vassert(archreg < 32);
1332    return IRExpr_Get( floatGuestRegOffset(archreg), Ity_F64 );
1333 }
1334 
1335 /* Ditto, but write to a reg instead. */
putFReg(UInt archreg,IRExpr * e)1336 static void putFReg ( UInt archreg, IRExpr* e )
1337 {
1338    vassert(archreg < 32);
1339    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
1340    stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) );
1341 }
1342 
1343 /* get Decimal float value.  Note, they share floating point register file. */
getDReg(UInt archreg)1344 static IRExpr* getDReg(UInt archreg) {
1345    IRExpr *e;
1346    vassert( archreg < 32 );
1347    e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D64 );
1348    return e;
1349 }
getDReg32(UInt archreg)1350 static IRExpr* getDReg32(UInt archreg) {
1351    IRExpr *e;
1352    vassert( archreg < 32 );
1353    e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D32 );
1354    return e;
1355 }
1356 
1357 /* Read a floating point register pair and combine their contents into a
1358  128-bit value */
getDReg_pair(UInt archreg)1359 static IRExpr *getDReg_pair(UInt archreg) {
1360    IRExpr *high = getDReg( archreg );
1361    IRExpr *low = getDReg( archreg + 1 );
1362 
1363    return binop( Iop_D64HLtoD128, high, low );
1364 }
1365 
1366 /* Ditto, but write to a reg instead. */
putDReg32(UInt archreg,IRExpr * e)1367 static void putDReg32(UInt archreg, IRExpr* e) {
1368    vassert( archreg < 32 );
1369    vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D32 );
1370    stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) );
1371 }
1372 
putDReg(UInt archreg,IRExpr * e)1373 static void putDReg(UInt archreg, IRExpr* e) {
1374    vassert( archreg < 32 );
1375    vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D64 );
1376    stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) );
1377 }
1378 
1379 /* Write a 128-bit floating point value into a register pair. */
putDReg_pair(UInt archreg,IRExpr * e)1380 static void putDReg_pair(UInt archreg, IRExpr *e) {
1381    IRTemp low = newTemp( Ity_D64 );
1382    IRTemp high = newTemp( Ity_D64 );
1383 
1384    vassert( archreg < 32 );
1385    vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D128 );
1386 
1387    assign( low, unop( Iop_D128LOtoD64, e ) );
1388    assign( high, unop( Iop_D128HItoD64, e ) );
1389 
1390    stmt( IRStmt_Put( floatGuestRegOffset( archreg ), mkexpr( high ) ) );
1391    stmt( IRStmt_Put( floatGuestRegOffset( archreg + 1 ), mkexpr( low ) ) );
1392 }
1393 
vsxGuestRegOffset(UInt archreg)1394 static Int vsxGuestRegOffset ( UInt archreg )
1395 {
1396    vassert(archreg < 64);
1397    switch (archreg) {
1398    case  0: return offsetofPPCGuestState(guest_VSR0);
1399    case  1: return offsetofPPCGuestState(guest_VSR1);
1400    case  2: return offsetofPPCGuestState(guest_VSR2);
1401    case  3: return offsetofPPCGuestState(guest_VSR3);
1402    case  4: return offsetofPPCGuestState(guest_VSR4);
1403    case  5: return offsetofPPCGuestState(guest_VSR5);
1404    case  6: return offsetofPPCGuestState(guest_VSR6);
1405    case  7: return offsetofPPCGuestState(guest_VSR7);
1406    case  8: return offsetofPPCGuestState(guest_VSR8);
1407    case  9: return offsetofPPCGuestState(guest_VSR9);
1408    case 10: return offsetofPPCGuestState(guest_VSR10);
1409    case 11: return offsetofPPCGuestState(guest_VSR11);
1410    case 12: return offsetofPPCGuestState(guest_VSR12);
1411    case 13: return offsetofPPCGuestState(guest_VSR13);
1412    case 14: return offsetofPPCGuestState(guest_VSR14);
1413    case 15: return offsetofPPCGuestState(guest_VSR15);
1414    case 16: return offsetofPPCGuestState(guest_VSR16);
1415    case 17: return offsetofPPCGuestState(guest_VSR17);
1416    case 18: return offsetofPPCGuestState(guest_VSR18);
1417    case 19: return offsetofPPCGuestState(guest_VSR19);
1418    case 20: return offsetofPPCGuestState(guest_VSR20);
1419    case 21: return offsetofPPCGuestState(guest_VSR21);
1420    case 22: return offsetofPPCGuestState(guest_VSR22);
1421    case 23: return offsetofPPCGuestState(guest_VSR23);
1422    case 24: return offsetofPPCGuestState(guest_VSR24);
1423    case 25: return offsetofPPCGuestState(guest_VSR25);
1424    case 26: return offsetofPPCGuestState(guest_VSR26);
1425    case 27: return offsetofPPCGuestState(guest_VSR27);
1426    case 28: return offsetofPPCGuestState(guest_VSR28);
1427    case 29: return offsetofPPCGuestState(guest_VSR29);
1428    case 30: return offsetofPPCGuestState(guest_VSR30);
1429    case 31: return offsetofPPCGuestState(guest_VSR31);
1430    case 32: return offsetofPPCGuestState(guest_VSR32);
1431    case 33: return offsetofPPCGuestState(guest_VSR33);
1432    case 34: return offsetofPPCGuestState(guest_VSR34);
1433    case 35: return offsetofPPCGuestState(guest_VSR35);
1434    case 36: return offsetofPPCGuestState(guest_VSR36);
1435    case 37: return offsetofPPCGuestState(guest_VSR37);
1436    case 38: return offsetofPPCGuestState(guest_VSR38);
1437    case 39: return offsetofPPCGuestState(guest_VSR39);
1438    case 40: return offsetofPPCGuestState(guest_VSR40);
1439    case 41: return offsetofPPCGuestState(guest_VSR41);
1440    case 42: return offsetofPPCGuestState(guest_VSR42);
1441    case 43: return offsetofPPCGuestState(guest_VSR43);
1442    case 44: return offsetofPPCGuestState(guest_VSR44);
1443    case 45: return offsetofPPCGuestState(guest_VSR45);
1444    case 46: return offsetofPPCGuestState(guest_VSR46);
1445    case 47: return offsetofPPCGuestState(guest_VSR47);
1446    case 48: return offsetofPPCGuestState(guest_VSR48);
1447    case 49: return offsetofPPCGuestState(guest_VSR49);
1448    case 50: return offsetofPPCGuestState(guest_VSR50);
1449    case 51: return offsetofPPCGuestState(guest_VSR51);
1450    case 52: return offsetofPPCGuestState(guest_VSR52);
1451    case 53: return offsetofPPCGuestState(guest_VSR53);
1452    case 54: return offsetofPPCGuestState(guest_VSR54);
1453    case 55: return offsetofPPCGuestState(guest_VSR55);
1454    case 56: return offsetofPPCGuestState(guest_VSR56);
1455    case 57: return offsetofPPCGuestState(guest_VSR57);
1456    case 58: return offsetofPPCGuestState(guest_VSR58);
1457    case 59: return offsetofPPCGuestState(guest_VSR59);
1458    case 60: return offsetofPPCGuestState(guest_VSR60);
1459    case 61: return offsetofPPCGuestState(guest_VSR61);
1460    case 62: return offsetofPPCGuestState(guest_VSR62);
1461    case 63: return offsetofPPCGuestState(guest_VSR63);
1462    default: break;
1463    }
1464    vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/
1465 }
1466 
1467 /* Vector registers are mapped to VSX registers[32..63]. */
vectorGuestRegOffset(UInt archreg)1468 static Int vectorGuestRegOffset ( UInt archreg )
1469 {
1470    vassert(archreg < 32);
1471 
1472    switch (archreg) {
1473    case  0: return offsetofPPCGuestState(guest_VSR32);
1474    case  1: return offsetofPPCGuestState(guest_VSR33);
1475    case  2: return offsetofPPCGuestState(guest_VSR34);
1476    case  3: return offsetofPPCGuestState(guest_VSR35);
1477    case  4: return offsetofPPCGuestState(guest_VSR36);
1478    case  5: return offsetofPPCGuestState(guest_VSR37);
1479    case  6: return offsetofPPCGuestState(guest_VSR38);
1480    case  7: return offsetofPPCGuestState(guest_VSR39);
1481    case  8: return offsetofPPCGuestState(guest_VSR40);
1482    case  9: return offsetofPPCGuestState(guest_VSR41);
1483    case 10: return offsetofPPCGuestState(guest_VSR42);
1484    case 11: return offsetofPPCGuestState(guest_VSR43);
1485    case 12: return offsetofPPCGuestState(guest_VSR44);
1486    case 13: return offsetofPPCGuestState(guest_VSR45);
1487    case 14: return offsetofPPCGuestState(guest_VSR46);
1488    case 15: return offsetofPPCGuestState(guest_VSR47);
1489    case 16: return offsetofPPCGuestState(guest_VSR48);
1490    case 17: return offsetofPPCGuestState(guest_VSR49);
1491    case 18: return offsetofPPCGuestState(guest_VSR50);
1492    case 19: return offsetofPPCGuestState(guest_VSR51);
1493    case 20: return offsetofPPCGuestState(guest_VSR52);
1494    case 21: return offsetofPPCGuestState(guest_VSR53);
1495    case 22: return offsetofPPCGuestState(guest_VSR54);
1496    case 23: return offsetofPPCGuestState(guest_VSR55);
1497    case 24: return offsetofPPCGuestState(guest_VSR56);
1498    case 25: return offsetofPPCGuestState(guest_VSR57);
1499    case 26: return offsetofPPCGuestState(guest_VSR58);
1500    case 27: return offsetofPPCGuestState(guest_VSR59);
1501    case 28: return offsetofPPCGuestState(guest_VSR60);
1502    case 29: return offsetofPPCGuestState(guest_VSR61);
1503    case 30: return offsetofPPCGuestState(guest_VSR62);
1504    case 31: return offsetofPPCGuestState(guest_VSR63);
1505    default: break;
1506    }
1507    vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/
1508 }
1509 
getVReg(UInt archreg)1510 static IRExpr* getVReg ( UInt archreg )
1511 {
1512    vassert(archreg < 32);
1513    return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 );
1514 }
1515 
1516 /* Get contents of 128-bit reg guest register */
getF128Reg(UInt archreg)1517 static IRExpr* getF128Reg ( UInt archreg )
1518 {
1519    vassert(archreg < 64);
1520    return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_F128 );
1521 }
1522 
1523 /* Ditto, but write to a reg instead. */
putF128Reg(UInt archreg,IRExpr * e)1524 static void putF128Reg ( UInt archreg, IRExpr* e )
1525 {
1526    vassert(archreg < 64);
1527    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F128);
1528    stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) );
1529 }
1530 
1531 /* Ditto, but write to a reg instead. */
putVReg(UInt archreg,IRExpr * e)1532 static void putVReg ( UInt archreg, IRExpr* e )
1533 {
1534    vassert(archreg < 32);
1535    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
1536    stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) );
1537 }
1538 
1539 /* Get contents of VSX guest register */
getVSReg(UInt archreg)1540 static IRExpr* getVSReg ( UInt archreg )
1541 {
1542    vassert(archreg < 64);
1543    return IRExpr_Get( vsxGuestRegOffset(archreg), Ity_V128 );
1544 }
1545 
1546 /* Ditto, but write to a VSX reg instead. */
putVSReg(UInt archreg,IRExpr * e)1547 static void putVSReg ( UInt archreg, IRExpr* e )
1548 {
1549    vassert(archreg < 64);
1550    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
1551    stmt( IRStmt_Put(vsxGuestRegOffset(archreg), e) );
1552 }
1553 
1554 
guestCR321offset(UInt cr)1555 static Int guestCR321offset ( UInt cr )
1556 {
1557    switch (cr) {
1558    case 0: return offsetofPPCGuestState(guest_CR0_321 );
1559    case 1: return offsetofPPCGuestState(guest_CR1_321 );
1560    case 2: return offsetofPPCGuestState(guest_CR2_321 );
1561    case 3: return offsetofPPCGuestState(guest_CR3_321 );
1562    case 4: return offsetofPPCGuestState(guest_CR4_321 );
1563    case 5: return offsetofPPCGuestState(guest_CR5_321 );
1564    case 6: return offsetofPPCGuestState(guest_CR6_321 );
1565    case 7: return offsetofPPCGuestState(guest_CR7_321 );
1566    default: vpanic("guestCR321offset(ppc)");
1567    }
1568 }
1569 
guestCR0offset(UInt cr)1570 static Int guestCR0offset ( UInt cr )
1571 {
1572    switch (cr) {
1573    case 0: return offsetofPPCGuestState(guest_CR0_0 );
1574    case 1: return offsetofPPCGuestState(guest_CR1_0 );
1575    case 2: return offsetofPPCGuestState(guest_CR2_0 );
1576    case 3: return offsetofPPCGuestState(guest_CR3_0 );
1577    case 4: return offsetofPPCGuestState(guest_CR4_0 );
1578    case 5: return offsetofPPCGuestState(guest_CR5_0 );
1579    case 6: return offsetofPPCGuestState(guest_CR6_0 );
1580    case 7: return offsetofPPCGuestState(guest_CR7_0 );
1581    default: vpanic("guestCR3offset(ppc)");
1582    }
1583 }
1584 
1585 typedef enum {
1586    _placeholder0,
1587    _placeholder1,
1588    _placeholder2,
1589    BYTE,
1590    HWORD,
1591    WORD,
1592    DWORD
1593 } _popcount_data_type;
1594 
1595 /* Generate an IR sequence to do a popcount operation on the supplied
1596    IRTemp, and return a new IRTemp holding the result.  'ty' may be
1597    Ity_I32 or Ity_I64 only. */
gen_POPCOUNT(IRType ty,IRTemp src,_popcount_data_type data_type)1598 static IRTemp gen_POPCOUNT ( IRType ty, IRTemp src,
1599                              _popcount_data_type data_type )
1600 {
1601   /* Do count across 2^data_type bits,
1602      byte:        data_type = 3
1603      half word:   data_type = 4
1604      word:        data_type = 5
1605      double word: data_type = 6  (not supported for 32-bit type)
1606     */
1607    Int shift[6];
1608    _popcount_data_type idx, i;
1609    IRTemp mask[6];
1610    IRTemp old = IRTemp_INVALID;
1611    IRTemp nyu = IRTemp_INVALID;
1612 
1613    vassert(ty == Ity_I64 || ty == Ity_I32);
1614 
1615    // Use a single IROp in cases where we can.
1616 
1617    if (ty == Ity_I64 && data_type == DWORD) {
1618       IRTemp res = newTemp(Ity_I64);
1619       assign(res, unop(Iop_PopCount64, mkexpr(src)));
1620       return res;
1621    }
1622 
1623    if (ty == Ity_I32 && data_type == WORD) {
1624       IRTemp res = newTemp(Ity_I32);
1625       assign(res, unop(Iop_PopCount32, mkexpr(src)));
1626       return res;
1627    }
1628 
1629    // For the rest, we have to do it the slow way.
1630 
1631    if (ty == Ity_I32) {
1632 
1633       for (idx = 0; idx < WORD; idx++) {
1634          mask[idx]  = newTemp(ty);
1635          shift[idx] = 1 << idx;
1636       }
1637       assign(mask[0], mkU32(0x55555555));
1638       assign(mask[1], mkU32(0x33333333));
1639       assign(mask[2], mkU32(0x0F0F0F0F));
1640       assign(mask[3], mkU32(0x00FF00FF));
1641       assign(mask[4], mkU32(0x0000FFFF));
1642       old = src;
1643       for (i = 0; i < data_type; i++) {
1644          nyu = newTemp(ty);
1645          assign(nyu,
1646                 binop(Iop_Add32,
1647                       binop(Iop_And32,
1648                             mkexpr(old),
1649                             mkexpr(mask[i])),
1650                       binop(Iop_And32,
1651                             binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
1652                             mkexpr(mask[i]))));
1653          old = nyu;
1654       }
1655       return nyu;
1656    }
1657 
1658    // else, ty == Ity_I64
1659    vassert(mode64);
1660 
1661    for (i = 0; i < DWORD; i++) {
1662       mask[i] = newTemp( Ity_I64 );
1663       shift[i] = 1 << i;
1664    }
1665    assign( mask[0], mkU64( 0x5555555555555555ULL ) );
1666    assign( mask[1], mkU64( 0x3333333333333333ULL ) );
1667    assign( mask[2], mkU64( 0x0F0F0F0F0F0F0F0FULL ) );
1668    assign( mask[3], mkU64( 0x00FF00FF00FF00FFULL ) );
1669    assign( mask[4], mkU64( 0x0000FFFF0000FFFFULL ) );
1670    assign( mask[5], mkU64( 0x00000000FFFFFFFFULL ) );
1671    old = src;
1672    for (i = 0; i < data_type; i++) {
1673       nyu = newTemp( Ity_I64 );
1674       assign( nyu,
1675               binop( Iop_Add64,
1676                      binop( Iop_And64, mkexpr( old ), mkexpr( mask[i] ) ),
1677                      binop( Iop_And64,
1678                             binop( Iop_Shr64, mkexpr( old ), mkU8( shift[i] ) ),
1679                             mkexpr( mask[i] ) ) ) );
1680       old = nyu;
1681    }
1682    return nyu;
1683 }
1684 
1685 /* Special purpose population count function for
1686  * vpopcntd in 32-bit mode.
1687  */
gen_vpopcntd_mode32(IRTemp src1,IRTemp src2)1688 static IRTemp gen_vpopcntd_mode32 ( IRTemp src1, IRTemp src2 )
1689 {
1690    IRTemp retval = newTemp(Ity_I64);
1691 
1692    vassert(!mode64);
1693 
1694    assign(retval,
1695           unop(Iop_32Uto64,
1696                binop(Iop_Add32,
1697                      unop(Iop_PopCount32, mkexpr(src1)),
1698                      unop(Iop_PopCount32, mkexpr(src2)))));
1699    return retval;
1700 }
1701 
1702 
1703 // ROTL(src32/64, rot_amt5/6)
ROTL(IRExpr * src,IRExpr * rot_amt)1704 static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src,
1705                                           IRExpr* rot_amt )
1706 {
1707    IRExpr *mask, *rot;
1708    vassert(typeOfIRExpr(irsb->tyenv,rot_amt) == Ity_I8);
1709 
1710    if (typeOfIRExpr(irsb->tyenv,src) == Ity_I64) {
1711       // rot = (src << rot_amt) | (src >> (64-rot_amt))
1712       mask = binop(Iop_And8, rot_amt, mkU8(63));
1713       rot  = binop(Iop_Or64,
1714                 binop(Iop_Shl64, src, mask),
1715                 binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask)));
1716    } else {
1717       // rot = (src << rot_amt) | (src >> (32-rot_amt))
1718       mask = binop(Iop_And8, rot_amt, mkU8(31));
1719       rot  = binop(Iop_Or32,
1720                 binop(Iop_Shl32, src, mask),
1721                 binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask)));
1722    }
1723    /* Note: the ITE not merely an optimisation; it's needed
1724       because otherwise the Shr is a shift by the word size when
1725       mask denotes zero.  For rotates by immediates, a lot of
1726       this junk gets folded out. */
1727    return IRExpr_ITE( binop(Iop_CmpNE8, mask, mkU8(0)),
1728                       /* non-zero rotate */ rot,
1729                       /*     zero rotate */ src);
1730 }
1731 
1732 /* Standard effective address calc: (rA + rB) */
ea_rA_idxd(UInt rA,UInt rB)1733 static IRExpr* ea_rA_idxd ( UInt rA, UInt rB )
1734 {
1735    IRType ty = mode64 ? Ity_I64 : Ity_I32;
1736    vassert(rA < 32);
1737    vassert(rB < 32);
1738    return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), getIReg(rB));
1739 }
1740 
1741 /* Standard effective address calc: (rA + simm) */
ea_rA_simm(UInt rA,UInt simm16)1742 static IRExpr* ea_rA_simm ( UInt rA, UInt simm16 )
1743 {
1744    IRType ty = mode64 ? Ity_I64 : Ity_I32;
1745    vassert(rA < 32);
1746    return binop(mkSzOp(ty, Iop_Add8), getIReg(rA),
1747                 mkSzExtendS16(ty, simm16));
1748 }
1749 
1750 /* Standard effective address calc: (rA|0) */
ea_rAor0(UInt rA)1751 static IRExpr* ea_rAor0 ( UInt rA )
1752 {
1753    IRType ty = mode64 ? Ity_I64 : Ity_I32;
1754    vassert(rA < 32);
1755    if (rA == 0) {
1756       return mkSzImm(ty, 0);
1757    } else {
1758       return getIReg(rA);
1759    }
1760 }
1761 
1762 /* Standard effective address calc: (rA|0) + rB */
ea_rAor0_idxd(UInt rA,UInt rB)1763 static IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB )
1764 {
1765    vassert(rA < 32);
1766    vassert(rB < 32);
1767    return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB );
1768 }
1769 
1770 /* Standard effective address calc: (rA|0) + simm16 */
ea_rAor0_simm(UInt rA,UInt simm16)1771 static IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 )
1772 {
1773    IRType ty = mode64 ? Ity_I64 : Ity_I32;
1774    vassert(rA < 32);
1775    if (rA == 0) {
1776       return mkSzExtendS16(ty, simm16);
1777    } else {
1778       return ea_rA_simm( rA, simm16 );
1779    }
1780 }
1781 
1782 
1783 /* Align effective address */
addr_align(IRExpr * addr,UChar align)1784 static IRExpr* addr_align( IRExpr* addr, UChar align )
1785 {
1786    IRType ty = mode64 ? Ity_I64 : Ity_I32;
1787    ULong mask;
1788    switch (align) {
1789    case 1:  return addr;                    // byte aligned
1790    case 2:  mask = ~0ULL << 1; break;       // half-word aligned
1791    case 4:  mask = ~0ULL << 2; break;       // word aligned
1792    case 16: mask = ~0ULL << 4; break;       // quad-word aligned
1793    default:
1794       vex_printf("addr_align: align = %u\n", align);
1795       vpanic("addr_align(ppc)");
1796    }
1797 
1798    vassert(typeOfIRExpr(irsb->tyenv,addr) == ty);
1799    return binop( mkSzOp(ty, Iop_And8), addr, mkSzImm(ty, mask) );
1800 }
1801 
1802 
1803 /* Exit the trace if ADDR (intended to be a guest memory address) is
1804    not ALIGN-aligned, generating a request for a SIGBUS followed by a
1805    restart of the current insn. */
gen_SIGBUS_if_misaligned(IRTemp addr,UChar align)1806 static void gen_SIGBUS_if_misaligned ( IRTemp addr, UChar align )
1807 {
1808    vassert(align == 2 || align == 4 || align == 8 || align == 16);
1809    if (mode64) {
1810       vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64);
1811       stmt(
1812          IRStmt_Exit(
1813             binop(Iop_CmpNE64,
1814                   binop(Iop_And64, mkexpr(addr), mkU64(align-1)),
1815                   mkU64(0)),
1816             Ijk_SigBUS,
1817             IRConst_U64( guest_CIA_curr_instr ), OFFB_CIA
1818          )
1819       );
1820    } else {
1821       vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32);
1822       stmt(
1823          IRStmt_Exit(
1824             binop(Iop_CmpNE32,
1825                   binop(Iop_And32, mkexpr(addr), mkU32(align-1)),
1826                   mkU32(0)),
1827             Ijk_SigBUS,
1828             IRConst_U32( guest_CIA_curr_instr ), OFFB_CIA
1829          )
1830       );
1831    }
1832 }
1833 
1834 
1835 /* Generate AbiHints which mark points at which the ELF or PowerOpen
1836    ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some
1837    N) becomes undefined.  That is at function calls and returns.  ELF
1838    ppc32 doesn't have this "feature" (how fortunate for it).  nia is
1839    the address of the next instruction to be executed.
1840 */
make_redzone_AbiHint(const VexAbiInfo * vbi,IRTemp nia,const HChar * who)1841 static void make_redzone_AbiHint ( const VexAbiInfo* vbi,
1842                                    IRTemp nia, const HChar* who )
1843 {
1844    Int szB = vbi->guest_stack_redzone_size;
1845    if (0) vex_printf("AbiHint: %s\n", who);
1846    vassert(szB >= 0);
1847    if (szB > 0) {
1848       if (mode64) {
1849          vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64);
1850          stmt( IRStmt_AbiHint(
1851                   binop(Iop_Sub64, getIReg(1), mkU64(szB)),
1852                   szB,
1853                   mkexpr(nia)
1854          ));
1855       } else {
1856          vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32);
1857          stmt( IRStmt_AbiHint(
1858                   binop(Iop_Sub32, getIReg(1), mkU32(szB)),
1859                   szB,
1860                   mkexpr(nia)
1861          ));
1862       }
1863    }
1864 }
1865 
1866 
1867 /*------------------------------------------------------------*/
1868 /*--- Helpers for condition codes.                         ---*/
1869 /*------------------------------------------------------------*/
1870 
1871 /* Condition register layout.
1872 
1873    In the hardware, CR is laid out like this.  The leftmost end is the
1874    most significant bit in the register; however the IBM documentation
1875    numbers the bits backwards for some reason.
1876 
1877    CR0      CR1    ..........   CR6       CR7
1878    0 .. 3   .......................  28 .. 31    (IBM bit numbering)
1879    31  28                             3    0     (normal bit numbering)
1880 
1881    Each CR field is 4 bits:  [<,>,==,SO]
1882 
1883    Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc.
1884 
1885    Indexing from BI to guest state:
1886 
1887      let    n = BI / 4
1888           off = BI % 4
1889      this references CR n:
1890 
1891         off==0   ->  guest_CRn_321 >> 3
1892         off==1   ->  guest_CRn_321 >> 2
1893         off==2   ->  guest_CRn_321 >> 1
1894         off==3   ->  guest_CRn_SO
1895 
1896    Bear in mind the only significant bit in guest_CRn_SO is bit 0
1897    (normal notation) and in guest_CRn_321 the significant bits are
1898    3, 2 and 1 (normal notation).
1899 */
1900 
putCR321(UInt cr,IRExpr * e)1901 static void putCR321 ( UInt cr, IRExpr* e )
1902 {
1903    vassert(cr < 8);
1904    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1905    stmt( IRStmt_Put(guestCR321offset(cr), e) );
1906 }
1907 
putCR0(UInt cr,IRExpr * e)1908 static void putCR0 ( UInt cr, IRExpr* e )
1909 {
1910    vassert(cr < 8);
1911    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1912    stmt( IRStmt_Put(guestCR0offset(cr), e) );
1913 }
1914 
putC(IRExpr * e)1915 static void putC ( IRExpr* e )
1916 {
1917    /* The assumption is that the value of the Floating-Point Result
1918     * Class Descriptor bit (C) is passed in the lower four bits of a
1919     * 32 bit value.
1920     *
1921     * Note, the C and FPCC bits which are fields in the FPSCR
1922     * register are stored in their own memory location of
1923     * memory.  The FPCC bits are in the lower 4 bits.  The C bit needs
1924     * to be shifted to bit 4 in the memory location that holds C and FPCC.
1925     * Note not all of the FPSCR register bits are supported.  We are
1926     * only writing C bit.
1927     */
1928    IRExpr* tmp;
1929 
1930    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I32);
1931 
1932    /* Get the FPCC bit field */
1933    tmp = binop( Iop_And32,
1934                 mkU32( 0xF ),
1935                 unop( Iop_8Uto32, IRExpr_Get( OFFB_C_FPCC, Ity_I8 ) ) );
1936 
1937    stmt( IRStmt_Put( OFFB_C_FPCC,
1938                      unop( Iop_32to8,
1939                            binop( Iop_Or32, tmp,
1940                                   binop( Iop_Shl32,
1941                                          binop( Iop_And32, mkU32( 0x1 ), e ),
1942                                          mkU8( 4 ) ) ) ) ) );
1943 }
1944 
getCR0(UInt cr)1945 static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr )
1946 {
1947    vassert(cr < 8);
1948    return IRExpr_Get(guestCR0offset(cr), Ity_I8);
1949 }
1950 
getCR321(UInt cr)1951 static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr )
1952 {
1953    vassert(cr < 8);
1954    return IRExpr_Get(guestCR321offset(cr), Ity_I8);
1955 }
1956 
1957 /* Fetch the specified CR bit (as per IBM/hardware notation) and
1958    return it at the bottom of an I32; the top 31 bits are guaranteed
1959    to be zero. */
getCRbit(UInt bi)1960 static IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi )
1961 {
1962    UInt n   = bi / 4;
1963    UInt off = bi % 4;
1964    vassert(bi < 32);
1965    if (off == 3) {
1966       /* Fetch the SO bit for this CR field */
1967       /* Note: And32 is redundant paranoia iff guest state only has 0
1968          or 1 in that slot. */
1969       return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
1970    } else {
1971       /* Fetch the <, > or == bit for this CR field */
1972       return binop( Iop_And32,
1973                     binop( Iop_Shr32,
1974                            unop(Iop_8Uto32, getCR321(n)),
1975                            mkU8(toUChar(3-off)) ),
1976                     mkU32(1) );
1977    }
1978 }
1979 
1980 /* Dually, write the least significant bit of BIT to the specified CR
1981    bit.  Indexing as per getCRbit. */
putCRbit(UInt bi,IRExpr * bit)1982 static void putCRbit ( UInt bi, IRExpr* bit )
1983 {
1984    UInt    n, off;
1985    IRExpr* safe;
1986    vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32);
1987    safe = binop(Iop_And32, bit, mkU32(1));
1988    n   = bi / 4;
1989    off = bi % 4;
1990    vassert(bi < 32);
1991    if (off == 3) {
1992       /* This is the SO bit for this CR field */
1993       putCR0(n, unop(Iop_32to8, safe));
1994    } else {
1995       off = 3 - off;
1996       vassert(off == 1 || off == 2 || off == 3);
1997       putCR321(
1998          n,
1999          unop( Iop_32to8,
2000                binop( Iop_Or32,
2001                       /* old value with field masked out */
2002                       binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)),
2003                                        mkU32(~(1 << off))),
2004                       /* new value in the right place */
2005                       binop(Iop_Shl32, safe, mkU8(toUChar(off)))
2006                )
2007          )
2008       );
2009    }
2010 }
2011 
2012 /* Fetch the specified CR bit (as per IBM/hardware notation) and
2013    return it somewhere in an I32; it does not matter where, but
2014    whichever bit it is, all other bits are guaranteed to be zero.  In
2015    other words, the I32-typed expression will be zero if the bit is
2016    zero and nonzero if the bit is 1.  Write into *where the index
2017    of where the bit will be. */
2018 
2019 static
getCRbit_anywhere(UInt bi,Int * where)2020 IRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where )
2021 {
2022    UInt n   = bi / 4;
2023    UInt off = bi % 4;
2024    vassert(bi < 32);
2025    if (off == 3) {
2026       /* Fetch the SO bit for this CR field */
2027       /* Note: And32 is redundant paranoia iff guest state only has 0
2028          or 1 in that slot. */
2029       *where = 0;
2030       return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
2031    } else {
2032       /* Fetch the <, > or == bit for this CR field */
2033       *where = 3-off;
2034       return binop( Iop_And32,
2035                     unop(Iop_8Uto32, getCR321(n)),
2036                     mkU32(1 << (3-off)) );
2037    }
2038 }
2039 
2040 /* Set the CR0 flags following an arithmetic operation.
2041    (Condition Register CR0 Field Definition, PPC32 p60)
2042 */
2043 static IRExpr* getXER_SO ( void );
set_CR0(IRExpr * result)2044 static void set_CR0 ( IRExpr* result )
2045 {
2046    vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_I32 ||
2047            typeOfIRExpr(irsb->tyenv,result) == Ity_I64);
2048    if (mode64) {
2049       putCR321( 0, unop(Iop_64to8,
2050                         binop(Iop_CmpORD64S, result, mkU64(0))) );
2051    } else {
2052       putCR321( 0, unop(Iop_32to8,
2053                         binop(Iop_CmpORD32S, result, mkU32(0))) );
2054    }
2055    putCR0( 0, getXER_SO() );
2056 }
2057 
2058 
2059 /* Set the CR6 flags following an AltiVec compare operation.
2060  * NOTE: This also works for VSX single-precision compares.
2061  * */
set_AV_CR6(IRExpr * result,Bool test_all_ones)2062 static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones )
2063 {
2064    /* CR6[0:3] = {all_ones, 0, all_zeros, 0}
2065       32 bit: all_zeros =  (v[0] || v[1] || v[2] || v[3]) == 0x0000'0000
2066               all_ones  = ~(v[0] && v[1] && v[2] && v[3]) == 0x0000'0000
2067               where v[] denotes 32-bit lanes
2068       or
2069       64 bit: all_zeros =  (v[0] || v[1]) == 0x0000'0000'0000'0000
2070               all_ones  = ~(v[0] && v[1]) == 0x0000'0000'0000'0000
2071               where v[] denotes 64-bit lanes
2072 
2073       The 32- and 64-bit versions compute the same thing, but the 64-bit one
2074       tries to be a bit more efficient.
2075    */
2076    vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_V128);
2077 
2078    IRTemp overlappedOred  = newTemp(Ity_V128);
2079    IRTemp overlappedAnded = newTemp(Ity_V128);
2080 
2081    if (mode64) {
2082       IRTemp v0 = newTemp(Ity_V128);
2083       IRTemp v1 = newTemp(Ity_V128);
2084       assign( v0, result );
2085       assign( v1, binop(Iop_ShrV128, result, mkU8(64)) );
2086       assign(overlappedOred,
2087              binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)));
2088       assign(overlappedAnded,
2089              binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)));
2090    } else {
2091       IRTemp v0 = newTemp(Ity_V128);
2092       IRTemp v1 = newTemp(Ity_V128);
2093       IRTemp v2 = newTemp(Ity_V128);
2094       IRTemp v3 = newTemp(Ity_V128);
2095       assign( v0, result );
2096       assign( v1, binop(Iop_ShrV128, result, mkU8(32)) );
2097       assign( v2, binop(Iop_ShrV128, result, mkU8(64)) );
2098       assign( v3, binop(Iop_ShrV128, result, mkU8(96)) );
2099       assign(overlappedOred,
2100              binop(Iop_OrV128,
2101                    binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)),
2102                    binop(Iop_OrV128, mkexpr(v2), mkexpr(v3))));
2103       assign(overlappedAnded,
2104              binop(Iop_AndV128,
2105                    binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)),
2106                    binop(Iop_AndV128, mkexpr(v2), mkexpr(v3))));
2107    }
2108 
2109    IRTemp rOnes   = newTemp(Ity_I8);
2110    IRTemp rZeroes = newTemp(Ity_I8);
2111 
2112    if (mode64) {
2113       assign(rZeroes,
2114              unop(Iop_1Uto8,
2115                   binop(Iop_CmpEQ64,
2116                         mkU64(0),
2117                         unop(Iop_V128to64, mkexpr(overlappedOred)))));
2118       assign(rOnes,
2119              unop(Iop_1Uto8,
2120                   binop(Iop_CmpEQ64,
2121                         mkU64(0),
2122                         unop(Iop_Not64,
2123                              unop(Iop_V128to64, mkexpr(overlappedAnded))))));
2124    } else {
2125       assign(rZeroes,
2126              unop(Iop_1Uto8,
2127                   binop(Iop_CmpEQ32,
2128                         mkU32(0),
2129                         unop(Iop_V128to32, mkexpr(overlappedOred)))));
2130       assign(rOnes,
2131              unop(Iop_1Uto8,
2132                   binop(Iop_CmpEQ32,
2133                         mkU32(0),
2134                         unop(Iop_Not32,
2135                              unop(Iop_V128to32, mkexpr(overlappedAnded))))));
2136    }
2137 
2138    // rOnes might not be used below.  But iropt will remove it, so there's no
2139    // inefficiency as a result.
2140 
2141    if (test_all_ones) {
2142       putCR321( 6, binop(Iop_Or8,
2143                          binop(Iop_Shl8, mkexpr(rOnes),  mkU8(3)),
2144                          binop(Iop_Shl8, mkexpr(rZeroes), mkU8(1))) );
2145    } else {
2146       putCR321( 6, binop(Iop_Shl8, mkexpr(rZeroes), mkU8(1)) );
2147    }
2148    putCR0( 6, mkU8(0) );
2149 }
2150 
2151 
create_DCM(IRType size,IRTemp NaN,IRTemp inf,IRTemp zero,IRTemp dnorm,IRTemp pos)2152 static IRExpr * create_DCM ( IRType size, IRTemp NaN, IRTemp inf, IRTemp zero,
2153                              IRTemp dnorm, IRTemp pos)
2154 {
2155    /* This is a general function for creating the DCM for a 32-bit or
2156       64-bit expression based on the passes size.
2157    */
2158    IRTemp neg;
2159    IROp opAND, opOR, opSHL, opXto1, op1UtoX;
2160 
2161    vassert( ( size == Ity_I32 ) || ( size == Ity_I64 ) );
2162 
2163    if ( size == Ity_I32 ) {
2164       opSHL = Iop_Shl32;
2165       opAND = Iop_And32;
2166       opOR  = Iop_Or32;
2167       opXto1 = Iop_32to1;
2168       op1UtoX = Iop_1Uto32;
2169       neg = newTemp( Ity_I32 );
2170 
2171    } else {
2172       opSHL = Iop_Shl64;
2173       opAND = Iop_And64;
2174       opOR  = Iop_Or64;
2175       opXto1 = Iop_64to1;
2176       op1UtoX = Iop_1Uto64;
2177       neg = newTemp( Ity_I64 );
2178    }
2179 
2180    assign( neg, unop( op1UtoX, mkNOT1( unop( opXto1,
2181                                              mkexpr ( pos ) ) ) ) );
2182 
2183    return binop( opOR,
2184                  binop( opSHL, mkexpr( NaN ), mkU8( 6 ) ),
2185                  binop( opOR,
2186                         binop( opOR,
2187                                binop( opOR,
2188                                       binop( opSHL,
2189                                              binop( opAND,
2190                                                     mkexpr( pos ),
2191                                                     mkexpr( inf ) ),
2192                                              mkU8( 5 ) ),
2193                                       binop( opSHL,
2194                                              binop( opAND,
2195                                                     mkexpr( neg ),
2196                                                     mkexpr( inf ) ),
2197                                              mkU8( 4 ) ) ),
2198                                binop( opOR,
2199                                       binop( opSHL,
2200                                              binop( opAND,
2201                                                     mkexpr( pos ),
2202                                                     mkexpr( zero ) ),
2203                                              mkU8( 3 ) ),
2204                                       binop( opSHL,
2205                                              binop( opAND,
2206                                                     mkexpr( neg ),
2207                                                     mkexpr( zero ) ),
2208                                              mkU8( 2 ) ) ) ),
2209                         binop( opOR,
2210                                binop( opSHL,
2211                                       binop( opAND,
2212                                              mkexpr( pos ),
2213                                              mkexpr( dnorm ) ),
2214                                       mkU8( 1 ) ),
2215                                binop( opAND,
2216                                       mkexpr( neg ),
2217                                       mkexpr( dnorm ) ) ) ) );
2218 }
2219 
2220 /*------------------------------------------------------------*/
2221 /*--- Helpers for XER flags.                               ---*/
2222 /*------------------------------------------------------------*/
2223 
putXER_SO(IRExpr * e)2224 static void putXER_SO ( IRExpr* e )
2225 {
2226    IRExpr* so;
2227    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2228    so = binop(Iop_And8, e, mkU8(1));
2229    stmt( IRStmt_Put( OFFB_XER_SO, so ) );
2230 }
2231 
putXER_OV(IRExpr * e)2232 static void putXER_OV ( IRExpr* e )
2233 {
2234    /* Interface to write XER[OV] */
2235    IRExpr* ov;
2236    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2237    ov = binop(Iop_And8, e, mkU8(1));
2238    stmt( IRStmt_Put( OFFB_XER_OV, ov ) );
2239 }
2240 
putXER_OV32(IRExpr * e)2241 static void putXER_OV32 ( IRExpr* e )
2242 {
2243    /*Interface to write XER[OV32] */
2244    IRExpr* ov;
2245    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2246    ov = binop(Iop_And8, e, mkU8(1));
2247 
2248    /* The OV32 bit was added to XER in ISA 3.0.  Do not write unless we
2249     * ISA 3.0 or beyond is supported. */
2250    if( OV32_CA32_supported )
2251       stmt( IRStmt_Put( OFFB_XER_OV32, ov ) );
2252 }
2253 
putXER_CA(IRExpr * e)2254 static void putXER_CA ( IRExpr* e )
2255 {
2256    /* Interface to write XER[CA] */
2257    IRExpr* ca;
2258    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2259    ca = binop(Iop_And8, e, mkU8(1));
2260    stmt( IRStmt_Put( OFFB_XER_CA, ca ) );
2261 }
2262 
putXER_CA32(IRExpr * e)2263 static void putXER_CA32 ( IRExpr* e )
2264 {
2265    /* Interface to write XER[CA32] */
2266    IRExpr* ca;
2267    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2268    ca = binop(Iop_And8, e, mkU8(1));
2269 
2270    /* The CA32 bit was added to XER in ISA 3.0.  Do not write unless we
2271     * ISA 3.0 or beyond is supported. */
2272    if( OV32_CA32_supported )
2273       stmt( IRStmt_Put( OFFB_XER_CA32, ca ) );
2274 }
2275 
putXER_BC(IRExpr * e)2276 static void putXER_BC ( IRExpr* e )
2277 {
2278    IRExpr* bc;
2279    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2280    bc = binop(Iop_And8, e, mkU8(0x7F));
2281    stmt( IRStmt_Put( OFFB_XER_BC, bc ) );
2282 }
2283 
getXER_SO(void)2284 static IRExpr* /* :: Ity_I8 */ getXER_SO ( void )
2285 {
2286    return IRExpr_Get( OFFB_XER_SO, Ity_I8 );
2287 }
2288 
getXER_SO_32(void)2289 static IRExpr* /* :: Ity_I32 */ getXER_SO_32 ( void )
2290 {
2291    return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) );
2292 }
2293 
getXER_OV(void)2294 static IRExpr* /* :: Ity_I8 */ getXER_OV ( void )
2295 {
2296    return IRExpr_Get( OFFB_XER_OV, Ity_I8 );
2297 }
2298 
getXER_OV32(void)2299 static IRExpr* /* :: Ity_I8 */ getXER_OV32 ( void )
2300 {
2301    return IRExpr_Get( OFFB_XER_OV32, Ity_I8 );
2302 }
2303 
getXER_OV_32(void)2304 static IRExpr* /* :: Ity_I32 */ getXER_OV_32 ( void )
2305 {
2306    /* get XER[OV], 32-bit interface */
2307    return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) );
2308 }
2309 
getXER_OV32_32(void)2310 static IRExpr* /* :: Ity_I32 */ getXER_OV32_32 ( void )
2311 {
2312    /* get XER[OV32], 32-bit interface */
2313    return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV32()), mkU32(1) );
2314 }
2315 
getXER_CA_32(void)2316 static IRExpr* /* :: Ity_I32 */ getXER_CA_32 ( void )
2317 {
2318    /* get XER[CA], 32-bit interface */
2319    IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 );
2320    return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) );
2321 }
2322 
getXER_CA32_32(void)2323 static IRExpr* /* :: Ity_I32 */ getXER_CA32_32 ( void )
2324 {
2325    /* get XER[CA32], 32-bit interface */
2326    IRExpr* ca = IRExpr_Get( OFFB_XER_CA32, Ity_I8 );
2327    return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) );
2328 }
2329 
getXER_BC(void)2330 static IRExpr* /* :: Ity_I8 */ getXER_BC ( void )
2331 {
2332    return IRExpr_Get( OFFB_XER_BC, Ity_I8 );
2333 }
2334 
getXER_BC_32(void)2335 static IRExpr* /* :: Ity_I32 */ getXER_BC_32 ( void )
2336 {
2337    IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 );
2338    return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) );
2339 }
2340 
2341 
2342 /* RES is the result of doing OP on ARGL and ARGR.  Set %XER.OV and
2343    %XER.SO accordingly. */
2344 
calculate_XER_OV_32(UInt op,IRExpr * res,IRExpr * argL,IRExpr * argR)2345 static IRExpr* calculate_XER_OV_32( UInt op, IRExpr* res,
2346                                     IRExpr* argL, IRExpr* argR )
2347 {
2348    IRTemp  t64;
2349    IRExpr* xer_ov;
2350 
2351 #  define INT32_MIN 0x80000000
2352 
2353 #  define XOR2(_aa,_bb) \
2354       binop(Iop_Xor32,(_aa),(_bb))
2355 
2356 #  define XOR3(_cc,_dd,_ee) \
2357       binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee))
2358 
2359 #  define AND3(_ff,_gg,_hh) \
2360       binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh))
2361 
2362 #define NOT(_jj) \
2363       unop(Iop_Not32, (_jj))
2364 
2365    switch (op) {
2366    case /* 0  */ PPCG_FLAG_OP_ADD:
2367    case /* 1  */ PPCG_FLAG_OP_ADDE:
2368       /* (argL^argR^-1) & (argL^res) & (1<<31)  ?1:0 */
2369       // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
2370       xer_ov
2371          = AND3( XOR3(argL,argR,mkU32(-1)),
2372                  XOR2(argL,res),
2373                  mkU32(INT32_MIN) );
2374       /* xer_ov can only be 0 or 1<<31 */
2375       xer_ov
2376          = binop(Iop_Shr32, xer_ov, mkU8(31) );
2377       break;
2378 
2379    case /* 2  */ PPCG_FLAG_OP_DIVW:
2380       /* (argL == INT32_MIN && argR == -1) || argR == 0 */
2381       xer_ov
2382          = mkOR1(
2383               mkAND1(
2384                  binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)),
2385                  binop(Iop_CmpEQ32, argR, mkU32(-1))
2386               ),
2387               binop(Iop_CmpEQ32, argR, mkU32(0) )
2388            );
2389       xer_ov
2390          = unop(Iop_1Uto32, xer_ov);
2391       break;
2392 
2393    case /* 3  */ PPCG_FLAG_OP_DIVWU:
2394       /* argR == 0 */
2395       xer_ov
2396          = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0)));
2397       break;
2398 
2399    case /* 4  */ PPCG_FLAG_OP_MULLW:
2400       /* OV true if result can't be represented in 32 bits
2401          i.e sHi != sign extension of sLo */
2402       t64 = newTemp(Ity_I64);
2403       assign( t64, binop(Iop_MullS32, argL, argR) );
2404       xer_ov
2405          = binop( Iop_CmpNE32,
2406                   unop(Iop_64HIto32, mkexpr(t64)),
2407                   binop( Iop_Sar32,
2408                          unop(Iop_64to32, mkexpr(t64)),
2409                          mkU8(31))
2410                   );
2411       xer_ov
2412          = unop(Iop_1Uto32, xer_ov);
2413       break;
2414 
2415    case /* 5  */ PPCG_FLAG_OP_NEG:
2416       /* argL == INT32_MIN */
2417       xer_ov
2418          = unop( Iop_1Uto32,
2419                  binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) );
2420       break;
2421 
2422    case /* 6  */ PPCG_FLAG_OP_SUBF:
2423    case /* 7  */ PPCG_FLAG_OP_SUBFC:
2424    case /* 8  */ PPCG_FLAG_OP_SUBFE:
2425       /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */
2426       xer_ov
2427          = AND3( XOR3(NOT(argL),argR,mkU32(-1)),
2428                  XOR2(NOT(argL),res),
2429                  mkU32(INT32_MIN) );
2430       /* xer_ov can only be 0 or 1<<31 */
2431       xer_ov
2432          = binop(Iop_Shr32, xer_ov, mkU8(31) );
2433       break;
2434 
2435    case PPCG_FLAG_OP_DIVWEU:
2436       xer_ov
2437                = binop( Iop_Or32,
2438                         unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
2439                         unop( Iop_1Uto32, binop( Iop_CmpLT32U, argR, argL ) ) );
2440       break;
2441 
2442    case PPCG_FLAG_OP_DIVWE:
2443 
2444       /* If argR == 0 of if the result cannot fit in the 32-bit destination register,
2445        * then OV <- 1.   If dest reg is 0 AND both dividend and divisor are non-zero,
2446        * an overflow is implied.
2447        */
2448       xer_ov = binop( Iop_Or32,
2449                       unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
2450                       unop( Iop_1Uto32, mkAND1( binop( Iop_CmpEQ32, res, mkU32( 0 ) ),
2451                               mkAND1( binop( Iop_CmpNE32, argL, mkU32( 0 ) ),
2452                                       binop( Iop_CmpNE32, argR, mkU32( 0 ) ) ) ) ) );
2453       break;
2454 
2455 
2456 
2457    default:
2458       vex_printf("calculate_XER_OV_32: op = %u\n", op);
2459       vpanic("calculate_XER_OV_32(ppc)");
2460    }
2461 
2462    return xer_ov;
2463 
2464 #  undef INT32_MIN
2465 #  undef AND3
2466 #  undef XOR3
2467 #  undef XOR2
2468 #  undef NOT
2469 }
2470 
set_XER_OV_OV32_32(UInt op,IRExpr * res,IRExpr * argL,IRExpr * argR)2471 static void set_XER_OV_OV32_32( UInt op, IRExpr* res,
2472                                 IRExpr* argL, IRExpr* argR )
2473 {
2474    IRExpr* xer_ov;
2475 
2476    vassert(op < PPCG_FLAG_OP_NUMBER);
2477    vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I32);
2478    vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32);
2479    vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32);
2480 
2481    xer_ov = calculate_XER_OV_32( op, res, argL, argR );
2482 
2483    /* xer_ov MUST denote either 0 or 1, no other value allowed */
2484    putXER_OV( unop(Iop_32to8, xer_ov) );
2485    putXER_OV32( unop(Iop_32to8, xer_ov) );
2486 }
2487 
calculate_XER_OV_64(UInt op,IRExpr * res,IRExpr * argL,IRExpr * argR)2488 static IRExpr* calculate_XER_OV_64( UInt op, IRExpr* res,
2489                                  IRExpr* argL, IRExpr* argR )
2490 {
2491    IRExpr* xer_ov;
2492 
2493 #  define INT64_MIN 0x8000000000000000ULL
2494 
2495 #  define XOR2(_aa,_bb) \
2496       binop(Iop_Xor64,(_aa),(_bb))
2497 
2498 #  define XOR3(_cc,_dd,_ee) \
2499       binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee))
2500 
2501 #  define AND3(_ff,_gg,_hh) \
2502       binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh))
2503 
2504 #define NOT(_jj) \
2505       unop(Iop_Not64, (_jj))
2506 
2507    switch (op) {
2508    case /* 0  */ PPCG_FLAG_OP_ADD:
2509    case /* 1  */ PPCG_FLAG_OP_ADDE:
2510       /* (argL^argR^-1) & (argL^res) & (1<<63)  ? 1:0 */
2511       // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
2512       xer_ov
2513          = AND3( XOR3(argL,argR,mkU64(-1)),
2514                  XOR2(argL,res),
2515                  mkU64(INT64_MIN) );
2516       /* xer_ov can only be 0 or 1<<63 */
2517       xer_ov
2518          = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
2519       break;
2520 
2521    case /* 2  */ PPCG_FLAG_OP_DIVW:
2522       /* (argL == INT64_MIN && argR == -1) || argR == 0 */
2523       xer_ov
2524          = mkOR1(
2525               mkAND1(
2526                  binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)),
2527                  binop(Iop_CmpEQ64, argR, mkU64(-1))
2528               ),
2529               binop(Iop_CmpEQ64, argR, mkU64(0) )
2530            );
2531       break;
2532 
2533    case /* 3  */ PPCG_FLAG_OP_DIVWU:
2534       /* argR == 0 */
2535       xer_ov
2536          = binop(Iop_CmpEQ64, argR, mkU64(0));
2537       break;
2538 
2539    case /* 4  */ PPCG_FLAG_OP_MULLW: {
2540       /* OV true if result can't be represented in 64 bits
2541          i.e sHi != sign extension of sLo */
2542       xer_ov
2543          = binop( Iop_CmpNE32,
2544                   unop(Iop_64HIto32, res),
2545                   binop( Iop_Sar32,
2546                          unop(Iop_64to32, res),
2547                          mkU8(31))
2548                   );
2549       break;
2550    }
2551 
2552    case /* 5  */ PPCG_FLAG_OP_NEG:
2553       /* argL == INT64_MIN */
2554       xer_ov
2555          = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN));
2556       break;
2557 
2558    case /* 6  */ PPCG_FLAG_OP_SUBF:
2559    case /* 7  */ PPCG_FLAG_OP_SUBFC:
2560    case /* 8  */ PPCG_FLAG_OP_SUBFE:
2561       /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */
2562       xer_ov
2563          = AND3( XOR3(NOT(argL),argR,mkU64(-1)),
2564                  XOR2(NOT(argL),res),
2565                  mkU64(INT64_MIN) );
2566       /* xer_ov can only be 0 or 1<<63 */
2567       xer_ov
2568          = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
2569       break;
2570 
2571    case /* 14 */ PPCG_FLAG_OP_DIVDE:
2572 
2573       /* If argR == 0, we must set the OV bit.  But there's another condition
2574        * where we can get overflow set for divde . . . when the
2575        * result cannot fit in the 64-bit destination register.  If dest reg is 0 AND
2576        * both dividend and divisor are non-zero, it implies an overflow.
2577        */
2578       xer_ov
2579                   = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
2580                            mkAND1( binop( Iop_CmpEQ64, res, mkU64( 0 ) ),
2581                                    mkAND1( binop( Iop_CmpNE64, argL, mkU64( 0 ) ),
2582                                            binop( Iop_CmpNE64, argR, mkU64( 0 ) ) ) ) );
2583       break;
2584 
2585    case /* 17 */ PPCG_FLAG_OP_DIVDEU:
2586      /* If argR == 0 or if argL >= argR, set OV. */
2587      xer_ov = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
2588                          binop( Iop_CmpLE64U, argR, argL ) );
2589      break;
2590 
2591    case /* 18 */ PPCG_FLAG_OP_MULLD: {
2592       IRTemp  t128;
2593       /* OV true if result can't be represented in 64 bits
2594          i.e sHi != sign extension of sLo */
2595       t128 = newTemp(Ity_I128);
2596       assign( t128, binop(Iop_MullS64, argL, argR) );
2597       xer_ov
2598          = binop( Iop_CmpNE64,
2599                   unop(Iop_128HIto64, mkexpr(t128)),
2600                   binop( Iop_Sar64,
2601                          unop(Iop_128to64, mkexpr(t128)),
2602                          mkU8(63))
2603                   );
2604       break;
2605    }
2606 
2607    default:
2608       vex_printf("calculate_XER_OV_64: op = %u\n", op);
2609       vpanic("calculate_XER_OV_64(ppc64)");
2610    }
2611 
2612    return xer_ov;
2613 
2614 #  undef INT64_MIN
2615 #  undef AND3
2616 #  undef XOR3
2617 #  undef XOR2
2618 #  undef NOT
2619 }
2620 
set_XER_OV_64(UInt op,IRExpr * res,IRExpr * argL,IRExpr * argR)2621 static void set_XER_OV_64( UInt op, IRExpr* res,
2622                            IRExpr* argL, IRExpr* argR )
2623 {
2624    IRExpr* xer_ov;
2625    vassert(op < PPCG_FLAG_OP_NUMBER);
2626    vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I64);
2627    vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64);
2628    vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64);
2629 
2630    /* xer_ov MUST denote either 0 or 1, no other value allowed */
2631    xer_ov = calculate_XER_OV_64( op, res, argL, argR);
2632    putXER_OV( unop(Iop_1Uto8, xer_ov) );
2633 
2634    /* Update the summary overflow */
2635    putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
2636 }
2637 
update_SO(void)2638 static void update_SO( void ) {
2639    /* Update the summary overflow bit */
2640    putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
2641 }
2642 
copy_OV_to_OV32(void)2643 static void copy_OV_to_OV32( void ) {
2644    /* Update the OV32 to match OV */
2645    putXER_OV32( getXER_OV() );
2646 }
2647 
set_XER_OV_OV32(IRType ty,UInt op,IRExpr * res,IRExpr * argL,IRExpr * argR)2648 static void set_XER_OV_OV32 ( IRType ty, UInt op, IRExpr* res,
2649                               IRExpr* argL, IRExpr* argR )
2650 {
2651    if (ty == Ity_I32) {
2652       set_XER_OV_OV32_32( op, res, argL, argR );
2653    } else {
2654       IRExpr* xer_ov_32;
2655       set_XER_OV_64( op, res, argL, argR );
2656       xer_ov_32 = calculate_XER_OV_32( op, unop(Iop_64to32, res),
2657                                        unop(Iop_64to32, argL),
2658                                        unop(Iop_64to32, argR));
2659       putXER_OV32( unop(Iop_32to8, xer_ov_32) );
2660    }
2661 }
2662 
set_XER_OV_OV32_SO(IRType ty,UInt op,IRExpr * res,IRExpr * argL,IRExpr * argR)2663 static void set_XER_OV_OV32_SO ( IRType ty, UInt op, IRExpr* res,
2664                                  IRExpr* argL, IRExpr* argR )
2665 {
2666    if (ty == Ity_I32) {
2667       set_XER_OV_OV32_32( op, res, argL, argR );
2668    } else {
2669       IRExpr* xer_ov_32;
2670       set_XER_OV_64( op, res, argL, argR );
2671       xer_ov_32 = calculate_XER_OV_32( op, unop(Iop_64to32, res),
2672                                        unop(Iop_64to32, argL),
2673                                        unop(Iop_64to32, argR));
2674       putXER_OV32( unop(Iop_32to8, xer_ov_32) );
2675    }
2676    update_SO();
2677 }
2678 
2679 
2680 
2681 /* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA
2682    value being OLDCA.  Set %XER.CA accordingly. */
2683 
calculate_XER_CA_32(UInt op,IRExpr * res,IRExpr * argL,IRExpr * argR,IRExpr * oldca)2684 static IRExpr* calculate_XER_CA_32 ( UInt op, IRExpr* res,
2685                                      IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2686 {
2687    IRExpr* xer_ca;
2688 
2689    switch (op) {
2690    case /* 0 */ PPCG_FLAG_OP_ADD:
2691       /* res <u argL */
2692       xer_ca
2693          = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL));
2694       break;
2695 
2696    case /* 1 */ PPCG_FLAG_OP_ADDE:
2697       /* res <u argL || (old_ca==1 && res==argL) */
2698       xer_ca
2699          = mkOR1(
2700               binop(Iop_CmpLT32U, res, argL),
2701               mkAND1(
2702                  binop(Iop_CmpEQ32, oldca, mkU32(1)),
2703                  binop(Iop_CmpEQ32, res, argL)
2704               )
2705            );
2706       xer_ca
2707          = unop(Iop_1Uto32, xer_ca);
2708       break;
2709 
2710    case /* 8 */ PPCG_FLAG_OP_SUBFE:
2711       /* res <u argR || (old_ca==1 && res==argR) */
2712       xer_ca
2713          = mkOR1(
2714               binop(Iop_CmpLT32U, res, argR),
2715               mkAND1(
2716                  binop(Iop_CmpEQ32, oldca, mkU32(1)),
2717                  binop(Iop_CmpEQ32, res, argR)
2718               )
2719            );
2720       xer_ca
2721          = unop(Iop_1Uto32, xer_ca);
2722       break;
2723 
2724    case /* 7 */ PPCG_FLAG_OP_SUBFC:
2725    case /* 9 */ PPCG_FLAG_OP_SUBFI:
2726       /* res <=u argR */
2727       xer_ca
2728          = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR));
2729       break;
2730 
2731    case /* 10 */ PPCG_FLAG_OP_SRAW:
2732       /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
2733          If it is <= 31, behave like SRAWI; else XER.CA is the sign
2734          bit of argL. */
2735       /* This term valid for shift amount < 32 only */
2736       xer_ca
2737          = binop(
2738               Iop_And32,
2739               binop(Iop_Sar32, argL, mkU8(31)),
2740               binop( Iop_And32,
2741                      argL,
2742                      binop( Iop_Sub32,
2743                             binop(Iop_Shl32, mkU32(1),
2744                                              unop(Iop_32to8,argR)),
2745                             mkU32(1) )
2746                      )
2747               );
2748       xer_ca
2749          = IRExpr_ITE(
2750               /* shift amt > 31 ? */
2751               binop(Iop_CmpLT32U, mkU32(31), argR),
2752               /* yes -- get sign bit of argL */
2753               binop(Iop_Shr32, argL, mkU8(31)),
2754               /* no -- be like srawi */
2755               unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)))
2756            );
2757       break;
2758 
2759    case /* 11 */ PPCG_FLAG_OP_SRAWI:
2760       /* xer_ca is 1 iff src was negative and bits_shifted_out !=
2761          0.  Since the shift amount is known to be in the range
2762          0 .. 31 inclusive the following seems viable:
2763          xer.ca == 1 iff the following is nonzero:
2764          (argL >>s 31)           -- either all 0s or all 1s
2765          & (argL & (1<<argR)-1)  -- the stuff shifted out */
2766       xer_ca
2767          = binop(
2768               Iop_And32,
2769               binop(Iop_Sar32, argL, mkU8(31)),
2770               binop( Iop_And32,
2771                      argL,
2772                      binop( Iop_Sub32,
2773                             binop(Iop_Shl32, mkU32(1),
2774                                              unop(Iop_32to8,argR)),
2775                             mkU32(1) )
2776                      )
2777               );
2778       xer_ca
2779          = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)));
2780       break;
2781 
2782    default:
2783       vex_printf("set_XER_CA: op = %u\n", op);
2784       vpanic("set_XER_CA(ppc)");
2785    }
2786 
2787    return xer_ca;
2788 }
2789 
set_XER_CA_32(UInt op,IRExpr * res,IRExpr * argL,IRExpr * argR,IRExpr * oldca)2790 static void set_XER_CA_32 ( UInt op, IRExpr* res,
2791                             IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2792 {
2793    IRExpr* xer_ca;
2794    vassert(op < PPCG_FLAG_OP_NUMBER);
2795    vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I32);
2796    vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I32);
2797    vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I32);
2798    vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I32);
2799 
2800    /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
2801       seems reasonable given that it's always generated by
2802       getXER_CA_32(), which masks it accordingly.  In any case it being
2803       0 or 1 is an invariant of the ppc guest state representation;
2804       if it has any other value, that invariant has been violated. */
2805 
2806    xer_ca = calculate_XER_CA_32( op, res, argL, argR, oldca);
2807 
2808    /* xer_ca MUST denote either 0 or 1, no other value allowed */
2809    putXER_CA( unop(Iop_32to8, xer_ca) );
2810 }
2811 
calculate_XER_CA_64(UInt op,IRExpr * res,IRExpr * argL,IRExpr * argR,IRExpr * oldca)2812 static IRExpr* calculate_XER_CA_64 ( UInt op, IRExpr* res,
2813                                      IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2814 {
2815    IRExpr* xer_ca;
2816 
2817    switch (op) {
2818    case /* 0 */ PPCG_FLAG_OP_ADD:
2819       /* res <u argL */
2820       xer_ca
2821          = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL));
2822       break;
2823 
2824    case /* 1 */ PPCG_FLAG_OP_ADDE:
2825       /* res <u argL || (old_ca==1 && res==argL) */
2826       xer_ca
2827          = mkOR1(
2828               binop(Iop_CmpLT64U, res, argL),
2829               mkAND1(
2830                  binop(Iop_CmpEQ64, oldca, mkU64(1)),
2831                  binop(Iop_CmpEQ64, res, argL)
2832                  )
2833               );
2834       xer_ca
2835          = unop(Iop_1Uto32, xer_ca);
2836       break;
2837 
2838    case /* 8 */ PPCG_FLAG_OP_SUBFE:
2839       /* res <u argR || (old_ca==1 && res==argR) */
2840       xer_ca
2841          = mkOR1(
2842               binop(Iop_CmpLT64U, res, argR),
2843               mkAND1(
2844                  binop(Iop_CmpEQ64, oldca, mkU64(1)),
2845                  binop(Iop_CmpEQ64, res, argR)
2846               )
2847            );
2848       xer_ca
2849          = unop(Iop_1Uto32, xer_ca);
2850       break;
2851 
2852    case /* 7 */ PPCG_FLAG_OP_SUBFC:
2853    case /* 9 */ PPCG_FLAG_OP_SUBFI:
2854       /* res <=u argR */
2855       xer_ca
2856          = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR));
2857       break;
2858 
2859 
2860    case /* 10 */ PPCG_FLAG_OP_SRAW:
2861       /* The shift amount is guaranteed to be in 0 .. 31 inclusive.
2862          If it is <= 31, behave like SRAWI; else XER.CA is the sign
2863          bit of argL. */
2864          /* This term valid for shift amount < 31 only */
2865 
2866       xer_ca
2867          = binop(
2868               Iop_And64,
2869               binop(Iop_Sar64, argL, mkU8(31)),
2870               binop( Iop_And64,
2871                      argL,
2872                      binop( Iop_Sub64,
2873                             binop(Iop_Shl64, mkU64(1),
2874                                              unop(Iop_64to8,argR)),
2875                             mkU64(1) )
2876               )
2877            );
2878       xer_ca
2879          = IRExpr_ITE(
2880               /* shift amt > 31 ? */
2881               binop(Iop_CmpLT64U, mkU64(31), argR),
2882               /* yes -- get sign bit of argL */
2883               unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))),
2884               /* no -- be like srawi */
2885               unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)))
2886           );
2887       break;
2888 
2889    case /* 11 */ PPCG_FLAG_OP_SRAWI:
2890       /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
2891          Since the shift amount is known to be in the range 0 .. 31
2892          inclusive the following seems viable:
2893          xer.ca == 1 iff the following is nonzero:
2894          (argL >>s 31)           -- either all 0s or all 1s
2895          & (argL & (1<<argR)-1)  -- the stuff shifted out */
2896 
2897       xer_ca
2898          = binop(
2899               Iop_And64,
2900               binop(Iop_Sar64, argL, mkU8(31)),
2901               binop( Iop_And64,
2902                      argL,
2903                      binop( Iop_Sub64,
2904                             binop(Iop_Shl64, mkU64(1),
2905                                              unop(Iop_64to8,argR)),
2906                             mkU64(1) )
2907               )
2908            );
2909       xer_ca
2910          = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
2911       break;
2912 
2913 
2914    case /* 12 */ PPCG_FLAG_OP_SRAD:
2915       /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
2916          If it is <= 63, behave like SRADI; else XER.CA is the sign
2917          bit of argL. */
2918          /* This term valid for shift amount < 63 only */
2919 
2920       xer_ca
2921          = binop(
2922               Iop_And64,
2923               binop(Iop_Sar64, argL, mkU8(63)),
2924               binop( Iop_And64,
2925                      argL,
2926                      binop( Iop_Sub64,
2927                             binop(Iop_Shl64, mkU64(1),
2928                                              unop(Iop_64to8,argR)),
2929                             mkU64(1) )
2930               )
2931            );
2932       xer_ca
2933          = IRExpr_ITE(
2934               /* shift amt > 63 ? */
2935               binop(Iop_CmpLT64U, mkU64(63), argR),
2936               /* yes -- get sign bit of argL */
2937               unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))),
2938               /* no -- be like sradi */
2939               unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)))
2940            );
2941       break;
2942 
2943 
2944    case /* 13 */ PPCG_FLAG_OP_SRADI:
2945       /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
2946          Since the shift amount is known to be in the range 0 .. 63
2947          inclusive, the following seems viable:
2948          xer.ca == 1 iff the following is nonzero:
2949          (argL >>s 63)           -- either all 0s or all 1s
2950          & (argL & (1<<argR)-1)  -- the stuff shifted out */
2951 
2952       xer_ca
2953          = binop(
2954               Iop_And64,
2955               binop(Iop_Sar64, argL, mkU8(63)),
2956               binop( Iop_And64,
2957                      argL,
2958                      binop( Iop_Sub64,
2959                             binop(Iop_Shl64, mkU64(1),
2960                                              unop(Iop_64to8,argR)),
2961                             mkU64(1) )
2962               )
2963            );
2964       xer_ca
2965          = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
2966       break;
2967 
2968    default:
2969       vex_printf("set_XER_CA: op = %u\n", op);
2970       vpanic("set_XER_CA(ppc64)");
2971    }
2972 
2973    return xer_ca;
2974 }
2975 
set_XER_CA_64(UInt op,IRExpr * res,IRExpr * argL,IRExpr * argR,IRExpr * oldca)2976 static void set_XER_CA_64 ( UInt op, IRExpr* res,
2977                             IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2978 {
2979    IRExpr* xer_ca;
2980    vassert(op < PPCG_FLAG_OP_NUMBER);
2981    vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I64);
2982    vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I64);
2983    vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I64);
2984    vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I64);
2985 
2986    /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
2987       seems reasonable given that it's always generated by
2988       getXER_CA_32(), which masks it accordingly.  In any case it being
2989       0 or 1 is an invariant of the ppc guest state representation;
2990       if it has any other value, that invariant has been violated. */
2991 
2992    xer_ca = calculate_XER_CA_64( op, res, argL, argR, oldca );
2993 
2994    /* xer_ca MUST denote either 0 or 1, no other value allowed */
2995    putXER_CA( unop(Iop_32to8, xer_ca) );
2996 }
2997 
set_XER_CA_CA32(IRType ty,UInt op,IRExpr * res,IRExpr * argL,IRExpr * argR,IRExpr * oldca)2998 static void set_XER_CA_CA32 ( IRType ty, UInt op, IRExpr* res,
2999                               IRExpr* argL, IRExpr* argR, IRExpr* oldca )
3000 {
3001    if (ty == Ity_I32) {
3002       set_XER_CA_32( op, res, argL, argR, oldca );
3003    } else {
3004       set_XER_CA_64( op, res, argL, argR, oldca );
3005    }
3006 }
3007 
3008 
3009 
3010 /*------------------------------------------------------------*/
3011 /*--- Read/write to guest-state                           --- */
3012 /*------------------------------------------------------------*/
3013 
getGST(PPC_GST reg)3014 static IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg )
3015 {
3016    IRType ty = mode64 ? Ity_I64 : Ity_I32;
3017    switch (reg) {
3018    case PPC_GST_SPRG3_RO:
3019       return IRExpr_Get( OFFB_SPRG3_RO, ty );
3020 
3021    case PPC_GST_CIA:
3022       return IRExpr_Get( OFFB_CIA, ty );
3023 
3024    case PPC_GST_LR:
3025       return IRExpr_Get( OFFB_LR, ty );
3026 
3027    case PPC_GST_CTR:
3028       return IRExpr_Get( OFFB_CTR, ty );
3029 
3030    case PPC_GST_VRSAVE:
3031       return IRExpr_Get( OFFB_VRSAVE, Ity_I32 );
3032 
3033    case PPC_GST_VSCR:
3034       return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ),
3035                               mkU32(MASK_VSCR_VALID));
3036 
3037    case PPC_GST_CR: {
3038       /* Synthesise the entire CR into a single word.  Expensive. */
3039 #     define FIELD(_n)                                               \
3040          binop(Iop_Shl32,                                            \
3041                unop(Iop_8Uto32,                                      \
3042                     binop(Iop_Or8,                                   \
3043                           binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \
3044                           binop(Iop_And8, getCR0(_n), mkU8(1))       \
3045                     )                                                \
3046                ),                                                    \
3047                mkU8(4 * (7-(_n)))                                    \
3048          )
3049       return binop(Iop_Or32,
3050                    binop(Iop_Or32,
3051                          binop(Iop_Or32, FIELD(0), FIELD(1)),
3052                          binop(Iop_Or32, FIELD(2), FIELD(3))
3053                          ),
3054                    binop(Iop_Or32,
3055                          binop(Iop_Or32, FIELD(4), FIELD(5)),
3056                          binop(Iop_Or32, FIELD(6), FIELD(7))
3057                          )
3058                    );
3059 #     undef FIELD
3060    }
3061 
3062    case PPC_GST_XER:
3063       return binop(Iop_Or32,
3064                    binop(Iop_Or32,
3065                          binop(Iop_Or32,
3066                                binop( Iop_Shl32, getXER_SO_32(), mkU8(31)),
3067                                binop( Iop_Shl32, getXER_OV_32(), mkU8(30))),
3068                          binop(Iop_Or32,
3069                                binop( Iop_Shl32, getXER_CA_32(), mkU8(29)),
3070                                getXER_BC_32())),
3071                    binop(Iop_Or32,
3072                          binop( Iop_Shl32, getXER_OV32_32(), mkU8(19)),
3073                          binop( Iop_Shl32, getXER_CA32_32(), mkU8(18))));
3074 
3075    case PPC_GST_TFHAR:
3076       return IRExpr_Get( OFFB_TFHAR, ty );
3077 
3078    case PPC_GST_TEXASR:
3079       return IRExpr_Get( OFFB_TEXASR, ty );
3080 
3081    case PPC_GST_TEXASRU:
3082       return IRExpr_Get( OFFB_TEXASRU, ty );
3083 
3084    case PPC_GST_TFIAR:
3085       return IRExpr_Get( OFFB_TFIAR, ty );
3086 
3087    case PPC_GST_PPR:
3088       return IRExpr_Get( OFFB_PPR, ty );
3089 
3090    case PPC_GST_PPR32:
3091       return unop( Iop_64HIto32, IRExpr_Get( OFFB_PPR, ty ) );
3092 
3093    case PPC_GST_PSPB:
3094       return IRExpr_Get( OFFB_PSPB, ty );
3095 
3096    case PPC_GST_DSCR:
3097       return IRExpr_Get( OFFB_DSCR, ty );
3098 
3099    default:
3100       vex_printf("getGST(ppc): reg = %u", reg);
3101       vpanic("getGST(ppc)");
3102    }
3103 }
3104 
3105 /* Get a masked word from the given reg */
getGST_masked(PPC_GST reg,ULong mask)3106 static IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, ULong mask )
3107 {
3108    IRTemp val = newTemp(Ity_I32);
3109    vassert( reg < PPC_GST_MAX );
3110 
3111    switch (reg) {
3112 
3113    case PPC_GST_FPSCR: {
3114       /* Vex-generated code expects the FPSCR to be set as follows:
3115          all exceptions masked, round-to-nearest.
3116          This corresponds to a FPSCR value of 0x0. */
3117 
3118       /* In the lower 32 bits of FPSCR, we're keeping track of the binary
3119        * floating point rounding mode and Floating-point Condition code, so
3120        * if the mask isn't asking for either of these, just return 0x0.
3121        */
3122       if ( mask & ( MASK_FPSCR_C_FPCC | MASK_FPSCR_RN ) ) {
3123          assign( val, binop( Iop_Or32,
3124                              unop( Iop_8Uto32, IRExpr_Get( OFFB_FPROUND, Ity_I8 ) ),
3125                              binop( Iop_Shl32,
3126                                     unop( Iop_8Uto32,
3127                                           IRExpr_Get( OFFB_C_FPCC, Ity_I8 ) ),
3128                                     mkU8( 12 ) ) ) );
3129       } else {
3130          assign( val, mkU32(0x0) );
3131       }
3132 
3133       break;
3134    }
3135 
3136    default:
3137       vex_printf("getGST_masked(ppc): reg = %u", reg);
3138       vpanic("getGST_masked(ppc)");
3139    }
3140 
3141    if ( mask != 0xFFFFFFFF ) {
3142       return binop(Iop_And32, mkexpr(val), mkU32(mask));
3143    } else {
3144       return mkexpr(val);
3145    }
3146 }
3147 
3148 /* Get a masked word from the given reg */
getGST_masked_upper(PPC_GST reg,ULong mask)3149 static IRExpr* /* ::Ity_I32 */getGST_masked_upper(PPC_GST reg, ULong mask) {
3150    IRExpr * val;
3151    vassert( reg < PPC_GST_MAX );
3152 
3153    switch (reg) {
3154 
3155    case PPC_GST_FPSCR: {
3156       /* In the upper 32 bits of FPSCR, we're only keeping track
3157        * of the decimal floating point rounding mode, so if the mask
3158        * isn't asking for this, just return 0x0.
3159        */
3160       if (mask & MASK_FPSCR_DRN) {
3161          val = binop( Iop_And32,
3162                       unop( Iop_8Uto32, IRExpr_Get( OFFB_DFPROUND, Ity_I8 ) ),
3163                       unop( Iop_64HIto32, mkU64( mask ) ) );
3164       } else {
3165          val = mkU32( 0x0ULL );
3166       }
3167       break;
3168    }
3169 
3170    default:
3171       vex_printf( "getGST_masked_upper(ppc): reg = %u", reg );
3172       vpanic( "getGST_masked_upper(ppc)" );
3173    }
3174    return val;
3175 }
3176 
3177 
3178 /* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation)
3179    and return it at the bottom of an I32; the top 27 bits are
3180    guaranteed to be zero. */
getGST_field(PPC_GST reg,UInt fld)3181 static IRExpr* /* ::Ity_I32 */ getGST_field ( PPC_GST reg, UInt fld )
3182 {
3183    UInt shft, mask;
3184 
3185    vassert( fld < 8 );
3186    vassert( reg < PPC_GST_MAX );
3187 
3188    shft = 4*(7-fld);
3189    mask = 0xF<<shft;
3190 
3191    switch (reg) {
3192    case PPC_GST_XER:
3193       vassert(fld ==7);
3194       return binop(Iop_Or32,
3195                    binop(Iop_Or32,
3196                          binop(Iop_Shl32, getXER_SO_32(), mkU8(3)),
3197                          binop(Iop_Shl32, getXER_OV_32(), mkU8(2))),
3198                    binop(      Iop_Shl32, getXER_CA_32(), mkU8(1)));
3199       break;
3200 
3201    default:
3202       if (shft == 0)
3203          return getGST_masked( reg, mask );
3204       else
3205          return binop(Iop_Shr32,
3206                       getGST_masked( reg, mask ),
3207                       mkU8(toUChar( shft )));
3208    }
3209 }
3210 
putGST(PPC_GST reg,IRExpr * src)3211 static void putGST ( PPC_GST reg, IRExpr* src )
3212 {
3213    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
3214    IRType ty_src = typeOfIRExpr(irsb->tyenv,src );
3215    vassert( reg < PPC_GST_MAX );
3216    switch (reg) {
3217    case PPC_GST_IP_AT_SYSCALL:
3218       vassert( ty_src == ty );
3219       stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) );
3220       break;
3221    case PPC_GST_CIA:
3222       vassert( ty_src == ty );
3223       stmt( IRStmt_Put( OFFB_CIA, src ) );
3224       break;
3225    case PPC_GST_LR:
3226       vassert( ty_src == ty );
3227       stmt( IRStmt_Put( OFFB_LR, src ) );
3228       break;
3229    case PPC_GST_CTR:
3230       vassert( ty_src == ty );
3231       stmt( IRStmt_Put( OFFB_CTR, src ) );
3232       break;
3233    case PPC_GST_VRSAVE:
3234       vassert( ty_src == Ity_I32 );
3235       stmt( IRStmt_Put( OFFB_VRSAVE,src));
3236       break;
3237    case PPC_GST_VSCR:
3238       vassert( ty_src == Ity_I32 );
3239       stmt( IRStmt_Put( OFFB_VSCR,
3240                         binop(Iop_And32, src,
3241                               mkU32(MASK_VSCR_VALID)) ) );
3242       break;
3243    case PPC_GST_XER:
3244       vassert( ty_src == Ity_I32 );
3245       putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) );
3246       putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) );
3247       putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) );
3248       putXER_OV32( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(19))) );
3249       putXER_CA32( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(18))) );
3250       putXER_BC( unop(Iop_32to8, src) );
3251       break;
3252 
3253    case PPC_GST_EMWARN:
3254       vassert( ty_src == Ity_I32 );
3255       stmt( IRStmt_Put( OFFB_EMNOTE,src) );
3256       break;
3257 
3258    case PPC_GST_CMSTART:
3259       vassert( ty_src == ty );
3260       stmt( IRStmt_Put( OFFB_CMSTART, src) );
3261       break;
3262 
3263    case PPC_GST_CMLEN:
3264       vassert( ty_src == ty );
3265       stmt( IRStmt_Put( OFFB_CMLEN, src) );
3266       break;
3267 
3268    case PPC_GST_TEXASR:
3269       vassert( ty_src == Ity_I64 );
3270       stmt( IRStmt_Put( OFFB_TEXASR, src ) );
3271       break;
3272 
3273    case PPC_GST_TEXASRU:
3274       vassert( ty_src == Ity_I32 );
3275       stmt( IRStmt_Put( OFFB_TEXASRU, src ) );
3276       break;
3277 
3278    case PPC_GST_TFIAR:
3279       vassert( ty_src == Ity_I64 );
3280       stmt( IRStmt_Put( OFFB_TFIAR, src ) );
3281       break;
3282    case PPC_GST_TFHAR:
3283       vassert( ty_src == Ity_I64 );
3284       stmt( IRStmt_Put( OFFB_TFHAR, src ) );
3285       break;
3286 
3287    case PPC_GST_PPR32:
3288    case PPC_GST_PPR:
3289       {
3290          /* The Program Priority Register (PPR) stores the priority in
3291           * bits [52:50].  The user setable priorities are:
3292           *
3293           *    001  very low
3294           *    010  low
3295           *    011  medium low
3296           *    100  medium
3297           *    101  medium high
3298           *
3299           * If the argument is not between 0b001 and 0b100 the priority is set
3300           * to 0b100.  The priority can only be set to 0b101 if the the Problem
3301           * State Boost Register is non-zero.  The value of the PPR is not
3302           * changed if the input is not valid.
3303           */
3304 
3305          IRTemp not_valid = newTemp(Ity_I64);
3306          IRTemp has_perm = newTemp(Ity_I64);
3307          IRTemp new_src  = newTemp(Ity_I64);
3308          IRTemp PSPB_val = newTemp(Ity_I64);
3309          IRTemp value    = newTemp(Ity_I64);
3310 
3311          vassert(( ty_src == Ity_I64 ) || ( ty_src == Ity_I32 ));
3312          assign( PSPB_val, binop( Iop_32HLto64,
3313                                   mkU32( 0 ),
3314                                   IRExpr_Get( OFFB_PSPB, Ity_I32 ) ) );
3315          if( reg == PPC_GST_PPR32 ) {
3316             vassert( ty_src == Ity_I32 );
3317             assign( value, binop( Iop_32HLto64,
3318                                   mkU32(0),
3319                                   binop( Iop_And32,
3320                                          binop( Iop_Shr32, src,  mkU8( 18 ) ),
3321                                          mkU32( 0x7 ) ) ) );
3322          } else {
3323             vassert( ty_src == Ity_I64 );
3324             assign( value, binop( Iop_And64,
3325                                   binop( Iop_Shr64, src,  mkU8( 50 ) ),
3326                                   mkU64( 0x7 ) ) );
3327          }
3328          assign( has_perm,
3329                  binop( Iop_And64,
3330                         unop( Iop_1Sto64,
3331                               binop( Iop_CmpEQ64,
3332                                      mkexpr( PSPB_val ),
3333                                      mkU64( 0 ) ) ),
3334                         unop( Iop_1Sto64,
3335                               binop( Iop_CmpEQ64,
3336                                      mkU64( 0x5 ),
3337                                      mkexpr( value ) ) ) ) );
3338          assign( not_valid,
3339                  binop( Iop_Or64,
3340                         unop( Iop_1Sto64,
3341                               binop( Iop_CmpEQ64,
3342                                      mkexpr( value ),
3343                                      mkU64( 0 ) ) ),
3344                         unop( Iop_1Sto64,
3345                               binop( Iop_CmpLT64U,
3346                                      mkU64( 0x5 ),
3347                                      mkexpr( value ) ) ) ) );
3348          assign( new_src,
3349                  binop( Iop_Or64,
3350                         binop( Iop_And64,
3351                                unop( Iop_Not64,
3352                                      mkexpr( not_valid ) ),
3353                                src ),
3354                         binop( Iop_And64,
3355                                mkexpr( not_valid ),
3356                                binop( Iop_Or64,
3357                                       binop( Iop_And64,
3358                                              mkexpr( has_perm),
3359                                              binop( Iop_Shl64,
3360                                                     mkexpr( value ),
3361                                                     mkU8( 50 ) ) ),
3362                                       binop( Iop_And64,
3363                                              IRExpr_Get( OFFB_PPR, ty ),
3364                                              unop( Iop_Not64,
3365                                                    mkexpr( has_perm )
3366                                                    ) ) ) ) ) );
3367 
3368                  /* make sure we only set the valid bit field [52:50] */
3369                  stmt( IRStmt_Put( OFFB_PPR,
3370                                    binop( Iop_And64,
3371                                           mkexpr( new_src ),
3372                                           mkU64( 0x1C000000000000) ) ) );
3373       break;
3374       }
3375    case PPC_GST_DSCR:
3376       vassert( ty_src == Ity_I64 );
3377       stmt( IRStmt_Put( OFFB_DSCR, src ) );
3378       break;
3379 
3380    default:
3381       vex_printf("putGST(ppc): reg = %u", reg);
3382       vpanic("putGST(ppc)");
3383    }
3384 }
3385 
3386 /* Write masked src to the given reg */
putGST_masked(PPC_GST reg,IRExpr * src,ULong mask)3387 static void putGST_masked ( PPC_GST reg, IRExpr* src, ULong mask )
3388 {
3389    IRType ty = mode64 ? Ity_I64 : Ity_I32;
3390    vassert( reg < PPC_GST_MAX );
3391    vassert( typeOfIRExpr( irsb->tyenv,src ) == Ity_I64 );
3392 
3393    switch (reg) {
3394    case PPC_GST_FPSCR: {
3395       /* Allow writes to either binary or decimal floating point
3396          Rounding Mode.
3397       */
3398       /* If any part of |mask| covers FPSCR.RN, update the bits of
3399          FPSCR.RN by copying in |src| for locations where the
3400          corresponding bit in |mask| is 1, and leaving it unchanged
3401          for corresponding |mask| zero bits. */
3402       if (mask & MASK_FPSCR_RN) {
3403          stmt(
3404             IRStmt_Put(
3405                OFFB_FPROUND,
3406                unop(
3407                   Iop_32to8,
3408                   binop(
3409                      Iop_Or32,
3410                      binop(
3411                         Iop_And32,
3412                         unop(Iop_64to32, src),
3413                         mkU32(MASK_FPSCR_RN & mask)
3414                      ),
3415                      binop(
3416                         Iop_And32,
3417                         unop(Iop_8Uto32, IRExpr_Get(OFFB_FPROUND,Ity_I8)),
3418                         mkU32(MASK_FPSCR_RN & ~mask)
3419                      )
3420                   )
3421                )
3422             )
3423          );
3424       }
3425 
3426       if (mask & MASK_FPSCR_C_FPCC) {
3427          /* FPCC bits are in [47:51] */
3428          stmt(
3429             IRStmt_Put(
3430                OFFB_C_FPCC,
3431                unop(
3432                     Iop_32to8,
3433                     binop(Iop_Shr32,
3434                           binop(
3435                                 Iop_Or32,
3436                                 binop(
3437                                       Iop_And32,
3438                                       unop(Iop_64to32, src),
3439                                       mkU32(MASK_FPSCR_C_FPCC & mask) ),
3440                                 binop(
3441                                       Iop_And32,
3442                                       unop(Iop_8Uto32,
3443                                            IRExpr_Get(OFFB_C_FPCC,Ity_I8)),
3444                                       mkU32(MASK_FPSCR_C_FPCC & ~mask)
3445                                       ) ),
3446                           mkU8( 12 ) )
3447                     ) ) );
3448       }
3449 
3450       /* Similarly, update FPSCR.DRN if any bits of |mask|
3451          corresponding to FPSCR.DRN are set. */
3452       if (mask & MASK_FPSCR_DRN) {
3453          stmt(
3454             IRStmt_Put(
3455                OFFB_DFPROUND,
3456                unop(
3457                   Iop_32to8,
3458                   binop(
3459                      Iop_Or32,
3460                      binop(
3461                         Iop_And32,
3462                         unop(Iop_64HIto32, src),
3463                         mkU32((MASK_FPSCR_DRN & mask) >> 32)
3464                      ),
3465                      binop(
3466                         Iop_And32,
3467                         unop(Iop_8Uto32, IRExpr_Get(OFFB_DFPROUND,Ity_I8)),
3468                         mkU32((MASK_FPSCR_DRN & ~mask) >> 32)
3469                      )
3470                   )
3471                )
3472             )
3473          );
3474       }
3475 
3476       /* Give EmNote for attempted writes to:
3477          - Exception Controls
3478          - Non-IEEE Mode
3479       */
3480       if (mask & 0xFC) {  // Exception Control, Non-IEE mode
3481          VexEmNote ew = EmWarn_PPCexns;
3482 
3483          /* If any of the src::exception_control bits are actually set,
3484             side-exit to the next insn, reporting the warning,
3485             so that Valgrind's dispatcher sees the warning. */
3486          putGST( PPC_GST_EMWARN, mkU32(ew) );
3487          stmt(
3488             IRStmt_Exit(
3489                binop(Iop_CmpNE32, mkU32(ew), mkU32(EmNote_NONE)),
3490                Ijk_EmWarn,
3491                mkSzConst( ty, nextInsnAddr()), OFFB_CIA ));
3492       }
3493 
3494       /* Ignore all other writes */
3495       break;
3496    }
3497 
3498    default:
3499       vex_printf("putGST_masked(ppc): reg = %u", reg);
3500       vpanic("putGST_masked(ppc)");
3501    }
3502 }
3503 
3504 /* Write the least significant nibble of src to the specified
3505    REG[FLD] (as per IBM/hardware notation). */
putGST_field(PPC_GST reg,IRExpr * src,UInt fld)3506 static void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld )
3507 {
3508    UInt shft;
3509    ULong mask;
3510 
3511    vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 );
3512    vassert( fld < 16 );
3513    vassert( reg < PPC_GST_MAX );
3514 
3515    if (fld < 8)
3516       shft = 4*(7-fld);
3517    else
3518       shft = 4*(15-fld);
3519    mask = 0xF;
3520    mask = mask << shft;
3521 
3522    switch (reg) {
3523    case PPC_GST_CR:
3524       putCR0  (fld, binop(Iop_And8, mkU8(1   ), unop(Iop_32to8, src)));
3525       putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src)));
3526       break;
3527 
3528    default:
3529       {
3530          IRExpr * src64 = unop( Iop_32Uto64, src );
3531 
3532          if (shft == 0) {
3533             putGST_masked( reg, src64, mask );
3534          } else {
3535             putGST_masked( reg,
3536                            binop( Iop_Shl64, src64, mkU8( toUChar( shft ) ) ),
3537                            mask );
3538          }
3539       }
3540    }
3541 }
3542 
putFPCC(IRExpr * e)3543 static void putFPCC ( IRExpr* e )
3544 {
3545    /* The assumption is that the value of the FPCC are passed in the lower
3546     * four bits of a 32 bit value.
3547     *
3548     * Note, the C and FPCC bits which are a field of the FPSCR
3549     * register are stored in their own "register" in
3550     * memory.  The FPCC bits are in the lower 4 bits.  We don't need to
3551     * shift it to the bits to their location in the FPSCR register.  Note,
3552     * not all of the FPSCR register bits are supported.  We are writing all
3553     * of the bits in the FPCC field but not the C field.
3554     */
3555    IRExpr* tmp;
3556 
3557    vassert( typeOfIRExpr( irsb->tyenv, e ) == Ity_I32 );
3558    /* Get the C bit field */
3559    tmp = binop( Iop_And32,
3560                 mkU32( 0x10 ),
3561                 unop( Iop_8Uto32, IRExpr_Get( OFFB_C_FPCC, Ity_I8 ) ) );
3562 
3563    stmt( IRStmt_Put( OFFB_C_FPCC,
3564                      unop( Iop_32to8,
3565                            binop( Iop_Or32, tmp,
3566                                   binop( Iop_And32, mkU32( 0xF ), e ) ) ) ) );
3567 
3568 }
3569 
getC(void)3570 static IRExpr* /* ::Ity_I32 */  getC ( void )
3571 {
3572    /* Note, the Floating-Point Result Class Descriptor (C) bit is a field of
3573     * the FPSCR registered are stored in its own "register" in guest state
3574     * with the FPCC bit field.   C | FPCC
3575     */
3576    IRTemp val = newTemp(Ity_I32);
3577 
3578    assign( val, binop( Iop_Shr32,
3579                        unop( Iop_8Uto32, IRExpr_Get( OFFB_C_FPCC, Ity_I8 ) ),
3580                        mkU8( 4 ) ) );
3581    return mkexpr(val);
3582 }
3583 
getFPCC(void)3584 static IRExpr* /* ::Ity_I32 */  getFPCC ( void )
3585 {
3586    /* Note, the FPCC bits are a field of the FPSCR
3587     * register are stored in their own "register" in
3588     * guest state with the C bit field.   C | FPCC
3589     */
3590    IRTemp val = newTemp( Ity_I32 );
3591 
3592    assign( val, binop( Iop_And32, unop( Iop_8Uto32,
3593                                         IRExpr_Get( OFFB_C_FPCC, Ity_I8 ) ),
3594                        mkU32( 0xF ) ));
3595    return mkexpr(val);
3596 }
3597 
3598 /*------------------------------------------------------------*/
3599 /* Helpers for VSX instructions that do floating point
3600  * operations and need to determine if a src contains a
3601  * special FP value.
3602  *
3603  *------------------------------------------------------------*/
3604 
3605 #define NONZERO_FRAC_MASK 0x000fffffffffffffULL
3606 #define FP_FRAC_PART(x) binop( Iop_And64, \
3607                                mkexpr( x ), \
3608                                mkU64( NONZERO_FRAC_MASK ) )
3609 
3610 #define NONZERO_FRAC_MASK32 0x007fffffULL
3611 #define FP_FRAC_PART32(x) binop( Iop_And32,   \
3612                                  mkexpr( x ), \
3613                                  mkU32( NONZERO_FRAC_MASK32 ) )
3614 
3615 // Returns exponent part of floating point src as I32
fp_exp_part(IRType size,IRTemp src)3616 static IRExpr * fp_exp_part( IRType size, IRTemp src )
3617 {
3618    IRExpr *shift_by, *mask, *tsrc;
3619 
3620    vassert( ( size == Ity_I16 ) || ( size == Ity_I32 )
3621             || ( size == Ity_I64 ) );
3622 
3623    if( size == Ity_I16 ) {
3624       /* The 16-bit floating point value is in the lower 16-bits
3625        * of the 32-bit input value.
3626        */
3627       tsrc  = mkexpr( src );
3628       mask  = mkU32( 0x1F );
3629       shift_by = mkU8( 10 );
3630 
3631    } else if( size == Ity_I32 ) {
3632       tsrc  = mkexpr( src );
3633       mask  = mkU32( 0xFF );
3634       shift_by = mkU8( 23 );
3635 
3636    } else if( size == Ity_I64 ) {
3637       tsrc  = unop( Iop_64HIto32, mkexpr( src ) );
3638       mask  = mkU32( 0x7FF );
3639       shift_by = mkU8( 52 - 32 );
3640 
3641    } else {
3642       /*NOTREACHED*/
3643       vassert(0); // Stops gcc complaining at "-Og"
3644    }
3645 
3646    return binop( Iop_And32, binop( Iop_Shr32, tsrc, shift_by ), mask );
3647 }
3648 
3649 /* The following functions check the floating point value to see if it
3650    is zero, infinity, NaN, Normalized, Denormalized.
3651 */
3652 /* 16-bit floating point number is stored in the lower 16-bits of 32-bit value */
3653 #define I16_EXP_MASK       0x7C00
3654 #define I16_FRACTION_MASK  0x03FF
3655 #define I16_MSB_FRACTION_MASK  0x0200
3656 #define I32_EXP_MASK       0x7F800000
3657 #define I32_FRACTION_MASK  0x007FFFFF
3658 #define I32_MSB_FRACTION_MASK  0x00400000
3659 #define I64_EXP_MASK       0x7FF0000000000000ULL
3660 #define I64_FRACTION_MASK  0x000FFFFFFFFFFFFFULL
3661 #define I64_MSB_FRACTION_MASK  0x0008000000000000ULL
3662 #define V128_EXP_MASK      0x7FFF000000000000ULL
3663 #define V128_FRACTION_MASK 0x0000FFFFFFFFFFFFULL  /* upper 64-bit fractional mask */
3664 #define V128_MSB_FRACTION_MASK 0x0000800000000000ULL  /* upper 64-bit fractional mask */
3665 
3666 void setup_value_check_args( IRType size, IRTemp *exp_mask, IRTemp *frac_mask,
3667                              IRTemp *msb_frac_mask, IRTemp *zero );
3668 
setup_value_check_args(IRType size,IRTemp * exp_mask,IRTemp * frac_mask,IRTemp * msb_frac_mask,IRTemp * zero)3669 void setup_value_check_args( IRType size, IRTemp *exp_mask, IRTemp *frac_mask,
3670                              IRTemp *msb_frac_mask, IRTemp *zero ) {
3671 
3672    vassert( ( size == Ity_I16 ) || ( size == Ity_I32 )
3673             || ( size == Ity_I64 ) || ( size == Ity_V128 ) );
3674 
3675    if( size == Ity_I16 ) {
3676       /* The 16-bit floating point value is in the lower 16-bits of
3677          the 32-bit input value */
3678       *frac_mask = newTemp( Ity_I32 );
3679       *msb_frac_mask = newTemp( Ity_I32 );
3680       *exp_mask  = newTemp( Ity_I32 );
3681       *zero  = newTemp( Ity_I32 );
3682       assign( *exp_mask, mkU32( I16_EXP_MASK ) );
3683       assign( *frac_mask, mkU32( I16_FRACTION_MASK ) );
3684       assign( *msb_frac_mask, mkU32( I16_MSB_FRACTION_MASK ) );
3685       assign( *zero, mkU32( 0 ) );
3686 
3687    } else if( size == Ity_I32 ) {
3688       *frac_mask = newTemp( Ity_I32 );
3689       *msb_frac_mask = newTemp( Ity_I32 );
3690       *exp_mask  = newTemp( Ity_I32 );
3691       *zero  = newTemp( Ity_I32 );
3692       assign( *exp_mask, mkU32( I32_EXP_MASK ) );
3693       assign( *frac_mask, mkU32( I32_FRACTION_MASK ) );
3694       assign( *msb_frac_mask, mkU32( I32_MSB_FRACTION_MASK ) );
3695       assign( *zero, mkU32( 0 ) );
3696 
3697    } else if( size == Ity_I64 ) {
3698       *frac_mask = newTemp( Ity_I64 );
3699       *msb_frac_mask = newTemp( Ity_I64 );
3700       *exp_mask  = newTemp( Ity_I64 );
3701       *zero  = newTemp( Ity_I64 );
3702       assign( *exp_mask, mkU64( I64_EXP_MASK ) );
3703       assign( *frac_mask, mkU64( I64_FRACTION_MASK ) );
3704       assign( *msb_frac_mask, mkU64( I64_MSB_FRACTION_MASK ) );
3705       assign( *zero, mkU64( 0 ) );
3706 
3707    } else {
3708       /* V128 is converted to upper and lower 64 bit values, */
3709       /* uses 64-bit operators and temps */
3710       *frac_mask = newTemp( Ity_I64 );
3711       *msb_frac_mask = newTemp( Ity_I64 );
3712       *exp_mask  = newTemp( Ity_I64 );
3713       *zero  = newTemp( Ity_I64 );
3714       assign( *exp_mask, mkU64( V128_EXP_MASK ) );
3715       /* upper 64-bit fractional mask */
3716       assign( *frac_mask, mkU64( V128_FRACTION_MASK ) );
3717       assign( *msb_frac_mask, mkU64( V128_MSB_FRACTION_MASK ) );
3718       assign( *zero, mkU64( 0 ) );
3719    }
3720 }
3721 
3722 /* Helper function for the various function which check the value of
3723    the floating point value.
3724 */
exponent_compare(IRType size,IRTemp src,IRTemp exp_mask,IRExpr * exp_val)3725 static IRExpr * exponent_compare( IRType size, IRTemp src,
3726                                   IRTemp exp_mask, IRExpr *exp_val )
3727 {
3728    IROp opAND, opCmpEQ;
3729 
3730    if( ( size == Ity_I16 ) || ( size == Ity_I32 ) )  {
3731       /* The 16-bit floating point value is in the lower 16-bits of
3732          the 32-bit input value */
3733       opAND = Iop_And32;
3734       opCmpEQ = Iop_CmpEQ32;
3735 
3736    } else {
3737       opAND = Iop_And64;
3738       opCmpEQ = Iop_CmpEQ64;
3739    }
3740 
3741    if( size == Ity_V128 ) {
3742       return binop( opCmpEQ,
3743                     binop ( opAND,
3744                             unop( Iop_V128HIto64, mkexpr( src ) ),
3745                             mkexpr( exp_mask ) ),
3746                     exp_val );
3747 
3748    } else if( ( size == Ity_I16 ) || ( size == Ity_I32 ) )  {
3749       return binop( opCmpEQ,
3750                     binop ( opAND, mkexpr( src ), mkexpr( exp_mask ) ),
3751                     exp_val );
3752    } else {
3753       /* 64-bit operands */
3754 
3755       if (mode64) {
3756          return binop( opCmpEQ,
3757                        binop ( opAND, mkexpr( src ), mkexpr( exp_mask ) ),
3758                        exp_val );
3759       } else {
3760          /* No support for 64-bit compares in 32-bit mode, need to do upper
3761           * and lower parts using 32-bit compare operators.
3762           */
3763          return
3764             mkAND1( binop( Iop_CmpEQ32,
3765                            binop ( Iop_And32,
3766                                    unop(Iop_64HIto32, mkexpr( src ) ),
3767                                    unop(Iop_64HIto32, mkexpr( exp_mask ) ) ),
3768                            unop(Iop_64HIto32, exp_val ) ),
3769                     binop( Iop_CmpEQ32,
3770                            binop ( Iop_And32,
3771                                    unop(Iop_64to32, mkexpr( src ) ),
3772                                    unop(Iop_64to32, mkexpr( exp_mask ) ) ),
3773                            unop(Iop_64to32, exp_val ) ) );
3774       }
3775    }
3776 }
3777 
fractional_part_compare(IRType size,IRTemp src,IRTemp frac_mask,IRExpr * zero)3778 static IRExpr *fractional_part_compare( IRType size, IRTemp src,
3779                                         IRTemp frac_mask, IRExpr *zero )
3780 {
3781    IROp opAND, opCmpEQ;
3782 
3783    if( ( size == Ity_I16 ) || ( size == Ity_I32 ) )  {
3784       /*The 16-bit floating point value is in the lower 16-bits of
3785         the 32-bit input value */
3786       opAND = Iop_And32;
3787       opCmpEQ = Iop_CmpEQ32;
3788 
3789    } else {
3790       opAND = Iop_And64;
3791       opCmpEQ = Iop_CmpEQ64;
3792    }
3793 
3794    if( size == Ity_V128 ) {
3795       /* 128-bit, note we only care if the fractional part is zero so take upper
3796          52-bits of fractional part and lower 64-bits and OR them together and test
3797          for zero.  This keeps the temp variables and operators all 64-bit.
3798       */
3799       return binop( opCmpEQ,
3800                     binop( Iop_Or64,
3801                            binop( opAND,
3802                                   unop( Iop_V128HIto64, mkexpr( src ) ),
3803                                   mkexpr( frac_mask ) ),
3804                            unop( Iop_V128to64, mkexpr( src ) ) ),
3805                     zero );
3806 
3807    } else if( ( size == Ity_I16 ) || ( size == Ity_I32 ) )  {
3808          return binop( opCmpEQ,
3809                        binop( opAND,  mkexpr( src ), mkexpr( frac_mask ) ),
3810                        zero );
3811    } else {
3812       if (mode64) {
3813          return binop( opCmpEQ,
3814                        binop( opAND,  mkexpr( src ), mkexpr( frac_mask ) ),
3815                        zero );
3816       } else {
3817          /* No support for 64-bit compares in 32-bit mode, need to do upper
3818           * and lower parts using 32-bit compare operators.
3819           */
3820          return
3821             mkAND1( binop( Iop_CmpEQ32,
3822                            binop ( Iop_And32,
3823                                    unop(Iop_64HIto32, mkexpr( src ) ),
3824                                    unop(Iop_64HIto32, mkexpr( frac_mask ) ) ),
3825                            mkU32 ( 0 ) ),
3826                     binop( Iop_CmpEQ32,
3827                            binop ( Iop_And32,
3828                                    unop(Iop_64to32, mkexpr( src ) ),
3829                                    unop(Iop_64to32, mkexpr( frac_mask ) ) ),
3830                            mkU32 ( 0 ) ) );
3831       }
3832    }
3833 }
3834 
3835 // Infinity: exp has all bits set, and fraction is zero; s = 0/1
is_Inf(IRType size,IRTemp src)3836 static IRExpr * is_Inf( IRType size, IRTemp src )
3837 {
3838    IRExpr *max_exp, *zero_frac;
3839    IRTemp exp_mask, frac_mask, msb_frac_mask, zero;
3840 
3841    setup_value_check_args( size, &exp_mask, &frac_mask, &msb_frac_mask,
3842                            &zero );
3843 
3844    /* check exponent is all ones, i.e. (exp AND exp_mask) = exp_mask */
3845    max_exp = exponent_compare( size, src, exp_mask, mkexpr( exp_mask ) );
3846 
3847    /* check fractional part is all zeros */
3848    zero_frac = fractional_part_compare( size, src, frac_mask, mkexpr( zero ) );
3849 
3850    return  mkAND1( max_exp, zero_frac );
3851 }
3852 
3853 // Zero: exp is zero and fraction is zero; s = 0/1
is_Zero(IRType size,IRTemp src)3854 static IRExpr * is_Zero( IRType size, IRTemp src )
3855 {
3856    IRExpr *zero_exp, *zero_frac;
3857    IRTemp exp_mask, frac_mask, msb_frac_mask, zero;
3858 
3859    setup_value_check_args( size, &exp_mask, &frac_mask, &msb_frac_mask,
3860                            &zero );
3861 
3862    /* check the exponent is all zeros, i.e. (exp AND exp_mask) = zero */
3863    zero_exp = exponent_compare( size, src, exp_mask, mkexpr( zero ) );
3864 
3865    /* check fractional part is all zeros */
3866    zero_frac = fractional_part_compare( size, src, frac_mask, mkexpr( zero ) );
3867 
3868    return  mkAND1( zero_exp, zero_frac );
3869 }
3870 
3871 /*  SNAN: s = 1/0; exp all 1's; fraction is nonzero, with highest bit '1'
3872  *  QNAN: s = 1/0; exp all 1's; fraction is nonzero, with highest bit '0'
3873  */
is_NaN(IRType size,IRTemp src)3874 static IRExpr * is_NaN( IRType size, IRTemp src )
3875 {
3876    IRExpr *max_exp, *not_zero_frac;
3877    IRTemp exp_mask, frac_mask, msb_frac_mask, zero;
3878 
3879    setup_value_check_args( size, &exp_mask, &frac_mask, &msb_frac_mask,
3880                            &zero );
3881 
3882    /* check exponent is all ones, i.e. (exp AND exp_mask) = exp_mask */
3883    max_exp = exponent_compare( size, src, exp_mask, mkexpr( exp_mask ) );
3884 
3885    /* check fractional part is not zero */
3886    not_zero_frac = unop( Iop_Not1,
3887                          fractional_part_compare( size, src, frac_mask,
3888                                                   mkexpr( zero ) ) );
3889 
3890    return  mkAND1( max_exp, not_zero_frac );
3891 }
3892 
is_sNaN(IRType size,IRTemp src)3893 static IRExpr * is_sNaN( IRType size, IRTemp src )
3894 {
3895    IRExpr *max_exp, *not_zero_frac, *msb_zero;
3896    IRTemp exp_mask, frac_mask, msb_frac_mask, zero;
3897 
3898    setup_value_check_args( size, &exp_mask, &frac_mask, &msb_frac_mask,
3899                            &zero );
3900 
3901    /* check exponent is all ones, i.e. (exp AND exp_mask) = exp_mask */
3902    max_exp = exponent_compare( size, src, exp_mask, mkexpr( exp_mask ) );
3903 
3904    /* Most significant fractional bit is zero for sNaN */
3905    msb_zero = fractional_part_compare ( size, src, msb_frac_mask,
3906                                         mkexpr( zero ) );
3907 
3908    /* check fractional part is not zero */
3909    not_zero_frac = unop( Iop_Not1,
3910                          fractional_part_compare( size, src, frac_mask,
3911                                                   mkexpr( zero ) ) );
3912 
3913    return  mkAND1( msb_zero, mkAND1( max_exp, not_zero_frac ) );
3914 }
3915 
3916 /* Denormalized number has a zero exponent and non zero fraction. */
is_Denorm(IRType size,IRTemp src)3917 static IRExpr * is_Denorm( IRType size, IRTemp src )
3918 {
3919    IRExpr *zero_exp, *not_zero_frac;
3920    IRTemp exp_mask, frac_mask, msb_frac_mask, zero;
3921 
3922    setup_value_check_args( size, &exp_mask, &frac_mask, &msb_frac_mask,
3923                            &zero );
3924 
3925    /* check exponent is all zeros */
3926    zero_exp = exponent_compare( size, src, exp_mask, mkexpr( zero ) );
3927 
3928    /* check fractional part is not zero */
3929    not_zero_frac = unop( Iop_Not1,
3930                          fractional_part_compare( size, src, frac_mask,
3931                                                   mkexpr( zero ) ) );
3932 
3933    return  mkAND1( zero_exp, not_zero_frac );
3934 }
3935 
3936 #if 0
3937 /* Normalized number has exponent between 1 and max_exp -1, or in other words
3938    the exponent is not zero and not equal to the max exponent value. */
3939  Currently not needed since generate_C_FPCC is now done with a C helper.
3940  Keep it around, might be useful in the future.
3941 static IRExpr * is_Norm( IRType size, IRTemp src )
3942 {
3943    IRExpr *not_zero_exp, *not_max_exp;
3944    IRTemp exp_mask, zero;
3945 
3946    vassert( ( size == Ity_I16 ) || ( size == Ity_I32 )
3947             || ( size == Ity_I64 ) || ( size == Ity_V128 ) );
3948 
3949    if( size == Ity_I16 ) {
3950       /* The 16-bit floating point value is in the lower 16-bits of
3951          the 32-bit input value */
3952       exp_mask = newTemp( Ity_I32 );
3953       zero = newTemp( Ity_I32 );
3954       assign( exp_mask, mkU32( I16_EXP_MASK ) );
3955       assign( zero,  mkU32( 0 ) );
3956 
3957    } else if( size == Ity_I32 ) {
3958       exp_mask = newTemp( Ity_I32 );
3959       zero = newTemp( Ity_I32 );
3960       assign( exp_mask, mkU32( I32_EXP_MASK ) );
3961       assign( zero, mkU32( 0 ) );
3962 
3963    } else if( size == Ity_I64 ) {
3964       exp_mask = newTemp( Ity_I64 );
3965       zero = newTemp( Ity_I64 );
3966       assign( exp_mask, mkU64( I64_EXP_MASK ) );
3967       assign( zero, mkU64( 0 ) );
3968 
3969    } else {
3970       /* V128 is converted to upper and lower 64 bit values, */
3971       /* uses 64-bit operators and temps */
3972       exp_mask = newTemp( Ity_I64 );
3973       zero = newTemp( Ity_I64 );
3974       assign( exp_mask, mkU64( V128_EXP_MASK ) );
3975       assign( zero, mkU64( 0 ) );
3976    }
3977 
3978    not_zero_exp = unop( Iop_Not1,
3979                         exponent_compare( size, src,
3980                                           exp_mask, mkexpr( zero ) ) );
3981    not_max_exp = unop( Iop_Not1,
3982                        exponent_compare( size, src,
3983                                          exp_mask, mkexpr( exp_mask ) ) );
3984 
3985    return  mkAND1( not_zero_exp, not_max_exp );
3986 }
3987 #endif
3988 
generate_store_FPRF(IRType size,IRTemp src,const VexAbiInfo * vbi)3989 static void generate_store_FPRF( IRType size, IRTemp src,
3990 				 const VexAbiInfo* vbi )
3991 {
3992 
3993   /* This function was originally written using IR code.  It has been
3994    * replaced with a clean helper due to the large amount of IR code
3995    * needed by this function.
3996    */
3997 
3998    IRTemp tmp = newTemp( Ity_I64 );
3999    vassert( ( size == Ity_I16 ) || ( size == Ity_I32 )
4000             || ( size == Ity_I64 ) || ( size == Ity_F128 ) );
4001 
4002    vassert( ( typeOfIRExpr(irsb->tyenv, mkexpr( src ) )   == Ity_I32 )
4003             || ( typeOfIRExpr(irsb->tyenv, mkexpr( src ) ) == Ity_I64 )
4004             || ( typeOfIRExpr(irsb->tyenv, mkexpr( src ) ) == Ity_F128 ) );
4005 
4006    if( size == Ity_I16 ) {
4007       assign( tmp,
4008               mkIRExprCCall( Ity_I64, 0 /*regparms*/,
4009                              "generate_store_C_FPCC_helper",
4010                              fnptr_to_fnentry( vbi, &generate_C_FPCC_helper ),
4011                              mkIRExprVec_3( mkU64( size ), mkU64( 0 ),
4012                                             mkexpr( src ) ) ) );
4013    } else if( size == Ity_I32 ) {
4014       assign( tmp,
4015               mkIRExprCCall( Ity_I64, 0 /*regparms*/,
4016                              "generate_store_C_FPCC_helper",
4017                              fnptr_to_fnentry( vbi, &generate_C_FPCC_helper ),
4018                              mkIRExprVec_3( mkU64( size ), mkU64( 0 ),
4019                                             mkexpr( src ) ) ) );
4020    } else if( size == Ity_I64 ) {
4021       assign( tmp,
4022               mkIRExprCCall( Ity_I64, 0 /*regparms*/,
4023                              "generate_store_C_FPCC_helper",
4024                              fnptr_to_fnentry( vbi, &generate_C_FPCC_helper ),
4025                              mkIRExprVec_3( mkU64( size ), mkU64( 0 ),
4026                                             mkexpr( src ) ) ) );
4027    } else if( size == Ity_F128 ) {
4028       assign( tmp,
4029               mkIRExprCCall( Ity_I64, 0 /*regparms*/,
4030                              "generate_store_C_FPCC_helper",
4031                              fnptr_to_fnentry( vbi, &generate_C_FPCC_helper ),
4032                              mkIRExprVec_3( mkU64( size ),
4033                                             unop( Iop_ReinterpF64asI64,
4034                                                   unop( Iop_F128HItoF64,
4035                                                         mkexpr( src ) ) ),
4036                                             unop( Iop_ReinterpF64asI64,
4037                                                   unop( Iop_F128LOtoF64,
4038                                                         mkexpr( src ) ) ) ) ) );
4039    }
4040 
4041    /* C is in the upper 32-bits, FPCC is in the lower 32-bits of the
4042     * value returned by the helper function
4043     */
4044    putC( unop(  Iop_64HIto32, mkexpr( tmp) ) );
4045    putFPCC( unop(  Iop_64to32, mkexpr( tmp) ) );
4046 }
4047 
4048 /* This function takes an Ity_I32 input argument interpreted
4049    as a single-precision floating point value. If src is a
4050    SNaN, it is changed to a QNaN and returned; otherwise,
4051    the original value is returned. */
handle_SNaN_to_QNaN_32(IRExpr * src)4052 static IRExpr * handle_SNaN_to_QNaN_32(IRExpr * src)
4053 {
4054 #define SNAN_MASK32 0x00400000
4055    IRTemp tmp = newTemp(Ity_I32);
4056    IRTemp mask = newTemp(Ity_I32);
4057    IRTemp is_SNAN = newTemp(Ity_I1);
4058 
4059    vassert( typeOfIRExpr(irsb->tyenv, src ) == Ity_I32 );
4060    assign(tmp, src);
4061 
4062    /* check if input is SNaN, if it is convert to QNaN */
4063    assign( is_SNAN,
4064            mkAND1( is_NaN( Ity_I32, tmp ),
4065                    binop( Iop_CmpEQ32,
4066                           binop( Iop_And32, mkexpr( tmp ),
4067                                  mkU32( SNAN_MASK32 ) ),
4068                           mkU32( 0 ) ) ) );
4069    /* create mask with QNaN bit set to make it a QNaN if tmp is SNaN */
4070    assign ( mask, binop( Iop_And32,
4071                          unop( Iop_1Sto32, mkexpr( is_SNAN ) ),
4072                          mkU32( SNAN_MASK32 ) ) );
4073    return binop( Iop_Or32, mkexpr( mask ), mkexpr( tmp) );
4074 }
4075 
4076 
4077 /* This helper function performs the negation part of operations of the form:
4078  *    "Negate Multiply-<op>"
4079  *  where "<op>" is either "Add" or "Sub".
4080  *
4081  * This function takes one argument -- the floating point intermediate result (converted to
4082  * Ity_I64 via Iop_ReinterpF64asI64) that was obtained from the "Multip-<op>" part of
4083  * the operation described above.
4084  */
getNegatedResult(IRTemp intermediateResult)4085 static IRTemp getNegatedResult(IRTemp intermediateResult)
4086 {
4087    ULong signbit_mask = 0x8000000000000000ULL;
4088    IRTemp signbit_32 = newTemp(Ity_I32);
4089    IRTemp resultantSignbit = newTemp(Ity_I1);
4090    IRTemp negatedResult = newTemp(Ity_I64);
4091    assign( signbit_32, binop( Iop_Shr32,
4092                           unop( Iop_64HIto32,
4093                                  binop( Iop_And64, mkexpr( intermediateResult ),
4094                                         mkU64( signbit_mask ) ) ),
4095                                  mkU8( 31 ) ) );
4096    /* We negate the signbit if and only if the intermediate result from the
4097     * multiply-<op> was NOT a NaN.  This is an XNOR predicate.
4098     */
4099    assign( resultantSignbit,
4100         unop( Iop_Not1,
4101               binop( Iop_CmpEQ32,
4102                      binop( Iop_Xor32,
4103                             mkexpr( signbit_32 ),
4104                             unop( Iop_1Uto32, is_NaN( Ity_I64,
4105                                                       intermediateResult ) ) ),
4106                      mkU32( 1 ) ) ) );
4107 
4108    assign( negatedResult,
4109         binop( Iop_Or64,
4110                binop( Iop_And64,
4111                       mkexpr( intermediateResult ),
4112                       mkU64( ~signbit_mask ) ),
4113                binop( Iop_32HLto64,
4114                       binop( Iop_Shl32,
4115                              unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
4116                              mkU8( 31 ) ),
4117                       mkU32( 0 ) ) ) );
4118 
4119    return negatedResult;
4120 }
4121 
4122 /* This helper function performs the negation part of operations of the form:
4123  *    "Negate Multiply-<op>"
4124  *  where "<op>" is either "Add" or "Sub".
4125  *
4126  * This function takes one argument -- the floating point intermediate result (converted to
4127  * Ity_I32 via Iop_ReinterpF32asI32) that was obtained from the "Multip-<op>" part of
4128  * the operation described above.
4129  */
getNegatedResult_32(IRTemp intermediateResult)4130 static IRTemp getNegatedResult_32(IRTemp intermediateResult)
4131 {
4132    UInt signbit_mask = 0x80000000;
4133    IRTemp signbit_32 = newTemp(Ity_I32);
4134    IRTemp resultantSignbit = newTemp(Ity_I1);
4135    IRTemp negatedResult = newTemp(Ity_I32);
4136    assign( signbit_32, binop( Iop_Shr32,
4137                                  binop( Iop_And32, mkexpr( intermediateResult ),
4138                                         mkU32( signbit_mask ) ),
4139                                  mkU8( 31 ) ) );
4140    /* We negate the signbit if and only if the intermediate result from the
4141     * multiply-<op> was NOT a NaN.  This is an XNOR predicate.
4142     */
4143    assign( resultantSignbit,
4144         unop( Iop_Not1,
4145               binop( Iop_CmpEQ32,
4146                      binop( Iop_Xor32,
4147                             mkexpr( signbit_32 ),
4148                             unop( Iop_1Uto32, is_NaN( Ity_I32,
4149                                                       intermediateResult ) ) ),
4150                      mkU32( 1 ) ) ) );
4151 
4152    assign( negatedResult,
4153            binop( Iop_Or32,
4154                   binop( Iop_And32,
4155                          mkexpr( intermediateResult ),
4156                          mkU32( ~signbit_mask ) ),
4157                   binop( Iop_Shl32,
4158                          unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
4159                          mkU8( 31 ) ) ) );
4160 
4161    return negatedResult;
4162 }
4163 
4164 /* This function takes two quad_precision floating point numbers of type
4165    V128 and return 1 if src_A > src_B, 0 otherwise. */
Quad_precision_gt(IRTemp src_A,IRTemp src_B)4166 static IRExpr * Quad_precision_gt ( IRTemp src_A, IRTemp  src_B )
4167 {
4168 #define FRAC_MASK64Hi 0x0000ffffffffffffULL
4169 #define MASK 0x7FFFFFFFFFFFFFFFULL    /* exclude sign bit in upper 64 bits */
4170 #define EXP_MASK 0x7fff
4171 
4172    IRType ty = Ity_I64;
4173    IRTemp sign_A = newTemp( ty );
4174    IRTemp sign_B = newTemp( ty );
4175    IRTemp exp_A = newTemp( ty );
4176    IRTemp exp_B = newTemp( ty );
4177    IRTemp frac_A_hi = newTemp( ty );
4178    IRTemp frac_B_hi = newTemp( ty );
4179    IRTemp frac_A_lo = newTemp( ty );
4180    IRTemp frac_B_lo = newTemp( ty );
4181 
4182 
4183    /* extract exponents, and fractional parts so they can be compared */
4184    assign( sign_A, binop( Iop_Shr64,
4185                           unop( Iop_V128HIto64, mkexpr( src_A ) ),
4186                           mkU8( 63 ) ) );
4187    assign( sign_B, binop( Iop_Shr64,
4188                           unop( Iop_V128HIto64, mkexpr( src_B ) ),
4189                           mkU8( 63 ) ) );
4190    assign( exp_A, binop( Iop_And64,
4191                          binop( Iop_Shr64,
4192                                 unop( Iop_V128HIto64, mkexpr( src_A ) ),
4193                                 mkU8( 48 ) ),
4194                          mkU64( EXP_MASK ) ) );
4195    assign( exp_B, binop( Iop_And64,
4196                          binop( Iop_Shr64,
4197                                 unop( Iop_V128HIto64, mkexpr( src_B ) ),
4198                                 mkU8( 48 ) ),
4199                          mkU64( EXP_MASK ) ) );
4200    assign( frac_A_hi, binop( Iop_And64,
4201                              unop( Iop_V128HIto64, mkexpr( src_A ) ),
4202                              mkU64( FRAC_MASK64Hi ) ) );
4203    assign( frac_B_hi, binop( Iop_And64,
4204                              unop( Iop_V128HIto64, mkexpr( src_B ) ),
4205                              mkU64( FRAC_MASK64Hi ) ) );
4206    assign( frac_A_lo, unop( Iop_V128to64, mkexpr( src_A ) ) );
4207    assign( frac_B_lo, unop( Iop_V128to64, mkexpr( src_B ) ) );
4208 
4209    IRExpr * A_zero =  mkAND1( binop( Iop_CmpEQ64,
4210                                      binop( Iop_And64,
4211                                             unop( Iop_V128HIto64,
4212                                                   mkexpr( src_A ) ),
4213                                             mkU64( MASK ) ),
4214                                      mkU64( 0 ) ),
4215                               binop( Iop_CmpEQ64,
4216                                      unop( Iop_V128to64, mkexpr( src_A ) ),
4217                                      mkU64( 0 ) ) );
4218    IRExpr * B_zero =  mkAND1( binop( Iop_CmpEQ64,
4219                                      binop( Iop_And64,
4220                                             unop( Iop_V128HIto64,
4221                                                   mkexpr( src_B ) ),
4222                                             mkU64( MASK ) ),
4223                                      mkU64( 0 ) ),
4224                               binop( Iop_CmpEQ64,
4225                                      unop( Iop_V128to64, mkexpr( src_B ) ),
4226                                      mkU64( 0 ) ) );
4227    IRExpr * A_B_zero = mkAND1( A_zero, B_zero );
4228 
4229    /* Compare numbers */
4230    IRExpr * both_pos = mkAND1( binop( Iop_CmpEQ64, mkexpr( sign_A ),
4231                                       mkU64( 0 ) ),
4232                                binop( Iop_CmpEQ64, mkexpr( sign_B ),
4233                                       mkU64( 0 ) ) );
4234    IRExpr * both_neg = mkAND1( binop( Iop_CmpEQ64, mkexpr( sign_A ),
4235                                       mkU64( 1 ) ),
4236                                binop( Iop_CmpEQ64, mkexpr( sign_B ),
4237                                       mkU64( 1 ) ) );
4238    IRExpr * sign_eq = binop( Iop_CmpEQ64, mkexpr( sign_A ), mkexpr( sign_B ) );
4239    IRExpr * sign_gt = binop( Iop_CmpLT64U, mkexpr( sign_A ),
4240                              mkexpr( sign_B ) ); /* A pos, B neg */
4241 
4242    IRExpr * exp_eq = binop( Iop_CmpEQ64, mkexpr( exp_A ), mkexpr( exp_B ) );
4243    IRExpr * exp_gt = binop( Iop_CmpLT64U, mkexpr( exp_B ), mkexpr( exp_A ) );
4244    IRExpr * exp_lt = binop( Iop_CmpLT64U, mkexpr( exp_A ), mkexpr( exp_B ) );
4245 
4246    IRExpr * frac_hi_eq = binop( Iop_CmpEQ64, mkexpr( frac_A_hi),
4247                                 mkexpr( frac_B_hi ) );
4248    IRExpr * frac_hi_gt = binop( Iop_CmpLT64U, mkexpr( frac_B_hi ),
4249                                 mkexpr( frac_A_hi ) );
4250    IRExpr * frac_hi_lt = binop( Iop_CmpLT64U, mkexpr( frac_A_hi ),
4251                                 mkexpr( frac_B_hi ) );
4252 
4253    IRExpr * frac_lo_gt = binop( Iop_CmpLT64U, mkexpr( frac_B_lo ),
4254                                 mkexpr( frac_A_lo ) );
4255    IRExpr * frac_lo_lt = binop( Iop_CmpLT64U, mkexpr( frac_A_lo ),
4256                                 mkexpr( frac_B_lo ) );
4257 
4258    /* src_A and src_B both positive */
4259    IRExpr *pos_cmp = mkOR1( exp_gt,
4260                             mkAND1( exp_eq,
4261                                     mkOR1( frac_hi_gt,
4262                                            mkAND1( frac_hi_eq, frac_lo_gt ) )
4263                                     ) );
4264 
4265    /* src_A and src_B both negative */
4266    IRExpr *neg_cmp = mkOR1( exp_lt,
4267                             mkAND1( exp_eq,
4268                                     mkOR1( frac_hi_lt,
4269                                            mkAND1( frac_hi_eq, frac_lo_lt ) )
4270                                     ) );
4271 
4272    /* Need to check the case where one value is a positive
4273     * zero and the other value is a negative zero
4274     */
4275    return mkAND1( mkNOT1( A_B_zero ),
4276                   mkOR1( sign_gt,
4277                          mkAND1( sign_eq,
4278                                  mkOR1( mkAND1( both_pos, pos_cmp ),
4279                                         mkAND1( both_neg, neg_cmp ) ) ) ) );
4280 }
4281 
4282 /*-----------------------------------------------------------
4283  * Helpers for VX instructions that work on National decimal values,
4284  * Zoned decimal values and BCD values.
4285  *
4286  *------------------------------------------------------------*/
is_National_decimal(IRTemp src)4287 static IRExpr * is_National_decimal (IRTemp src)
4288 {
4289    /* The src is a 128-bit value containing a sign code in half word 7
4290     * and seven digits in halfwords 0 to 6 (IBM numbering).  A valid
4291     * national decimal value has the following:
4292     *   - the sign code must be 0x002B (positive) or 0x002D (negative)
4293     *   - the digits must be in the range 0x0030 to 0x0039
4294     */
4295    Int i;
4296    IRExpr * valid_pos_sign;
4297    IRExpr * valid_neg_sign;
4298    IRTemp valid_num[8];
4299    IRTemp digit[7];
4300 
4301    valid_pos_sign = binop( Iop_CmpEQ64,
4302                            binop( Iop_And64,
4303                                   mkU64( 0xFFFF ),
4304                                   unop( Iop_V128to64, mkexpr( src ) ) ),
4305                            mkU64( 0x002B ) );
4306 
4307    valid_neg_sign = binop( Iop_CmpEQ64,
4308                            binop( Iop_And64,
4309                                   mkU64( 0xFFFF ),
4310                                   unop( Iop_V128to64, mkexpr( src ) ) ),
4311                            mkU64( 0x002D ) );
4312 
4313    valid_num[0] = newTemp( Ity_I1 );
4314    digit[0] = newTemp( Ity_I64 );
4315    assign( valid_num[0], mkU1( 1 ) );   // Assume true to start
4316 
4317    for(i = 0; i < 7; i++) {
4318       valid_num[i+1] = newTemp( Ity_I1 );
4319       digit[i] = newTemp( Ity_I64 );
4320       assign( digit[i], binop( Iop_And64,
4321                                unop( Iop_V128to64,
4322                                      binop( Iop_ShrV128,
4323                                             mkexpr( src ),
4324                                             mkU8( (7-i)*16 ) ) ),
4325                                mkU64( 0xFFFF ) ) );
4326 
4327       assign( valid_num[i+1],
4328               mkAND1( mkexpr( valid_num[i] ),
4329                       mkAND1( binop( Iop_CmpLE64U,
4330                                      mkexpr( digit[i] ),
4331                                      mkU64( 0x39 ) ),
4332                               binop( Iop_CmpLE64U,
4333                                      mkU64( 0x30 ),
4334                                      mkexpr( digit[i] ) ) ) ) );
4335    }
4336 
4337    return mkAND1( mkOR1( valid_pos_sign, valid_neg_sign),
4338                   mkexpr( valid_num[7] ) );
4339 }
4340 
is_Zoned_decimal(IRTemp src,UChar ps)4341 static IRExpr * is_Zoned_decimal (IRTemp src, UChar ps)
4342 {
4343    /* The src is a 128-bit value containing a sign code the least significant
4344     * two bytes. The upper pairs of bytes contain digits.  A valid Zoned
4345     * decimal value has the following:
4346     *   - the sign code must be between 0x0X to 0xFX inclusive (X - don't care)
4347     *   - bits [0:3] of each digit must be equal to 0x3
4348     *   - bits [4:7] of each digit must be between 0x0 and 0x9
4349     *
4350     *  If ps = 0
4351     *     Positive sign codes are: 0x0, 0x1, 0x2, 0x3, 0x8, 0x9, 0xA, 0xB
4352     *       (note 0bX0XX XXXX  is positive)
4353     *
4354     *     Negative sign codes are 0x4, 0x5, 0x6, 0x7, 0xC, 0xD, 0xE, 0xF
4355     *       (note 0bX1XX XXXX  is negative)
4356     *
4357     *  If ps = 1, then the sign code must be in the range 0xA to 0xF
4358     *     Positive sign codes are: 0xA, 0xC, 0xE, 0xF
4359     *
4360     *     Negative sign codes are 0xB, 0xD
4361     */
4362    Int i, mask_hi, mask_lo;
4363    IRExpr *valid_range;
4364    IRTemp valid_num[16];
4365    IRTemp digit[15];
4366 
4367    /* check the range of the sign value based on the value of ps */
4368    valid_range = mkOR1(
4369                        mkAND1( binop( Iop_CmpEQ64,
4370                                       mkU64( 1 ),
4371                                       mkU64( ps ) ),
4372                                mkAND1( binop( Iop_CmpLE64U,
4373                                               binop( Iop_And64,
4374                                                      mkU64( 0xF0 ),
4375                                                      unop( Iop_V128to64,
4376                                                            mkexpr( src ) ) ),
4377 
4378                                               mkU64( 0xF0 ) ),
4379                                        binop( Iop_CmpLE64U,
4380                                               mkU64( 0xA0 ),
4381                                               binop( Iop_And64,
4382                                                      mkU64( 0xF0 ),
4383                                                      unop( Iop_V128to64,
4384                                                            mkexpr( src ) ))))),
4385                        binop( Iop_CmpEQ64,
4386                               mkU64( 0 ),
4387                               mkU64( ps ) ) );
4388 
4389    valid_num[0] = newTemp( Ity_I1 );
4390    assign( valid_num[0], mkU1( 1) );   // Assume true to start
4391 
4392    if (ps == 0) {
4393       mask_hi = 0x39;
4394       mask_lo = 0x30;
4395    } else {
4396       mask_hi = 0xF9;
4397       mask_lo = 0xF0;
4398    }
4399 
4400    for(i = 0; i < 15; i++) {
4401       valid_num[i+1] = newTemp( Ity_I1 );
4402       digit[i] = newTemp( Ity_I64 );
4403       assign( digit[i], binop( Iop_And64,
4404                                unop( Iop_V128to64,
4405                                      binop( Iop_ShrV128,
4406                                             mkexpr( src ),
4407                                             mkU8( (15-i)*8 ) ) ),
4408                                mkU64( 0xFF ) ) );
4409 
4410       assign( valid_num[i+1],
4411               mkAND1( mkexpr( valid_num[i] ),
4412                       mkAND1( binop( Iop_CmpLE64U,
4413                                      mkexpr( digit[i] ),
4414                                      mkU64( mask_hi ) ),
4415                               binop( Iop_CmpLE64U,
4416                                      mkU64( mask_lo ),
4417                                      mkexpr( digit[i] ) ) ) ) );
4418    }
4419 
4420    return mkAND1( valid_range, mkexpr( valid_num[15] ) );
4421 }
4422 
CmpGT128U(IRExpr * src1,IRExpr * src2)4423 static IRExpr * CmpGT128U ( IRExpr *src1, IRExpr *src2 )
4424 {
4425    /* Unsigend compare of two 128-bit values */
4426    IRExpr *pos_upper_gt, *pos_upper_eq, *pos_lower_gt;
4427 
4428    pos_upper_gt = binop( Iop_CmpLT64U,
4429                          unop( Iop_V128HIto64, src2 ),
4430                          unop( Iop_V128HIto64, src1 ) );
4431    pos_upper_eq = binop( Iop_CmpEQ64,
4432                          unop( Iop_V128HIto64, src1 ),
4433                          unop( Iop_V128HIto64, src2 ) );
4434    pos_lower_gt = binop( Iop_CmpLT64U,
4435                          unop( Iop_V128to64, src2),
4436                          unop( Iop_V128to64, src1) );
4437    return mkOR1( pos_upper_gt,
4438                  mkAND1( pos_upper_eq,
4439                          pos_lower_gt ) );
4440 }
4441 
4442 
is_BCDstring128(const VexAbiInfo * vbi,UInt Signed,IRExpr * src)4443 static IRExpr * is_BCDstring128 ( const VexAbiInfo* vbi,
4444                                   UInt Signed, IRExpr *src )
4445 {
4446 
4447    IRTemp valid = newTemp( Ity_I64 );
4448 
4449    /* The src is a 128-bit value containing a MAX_DIGITS BCD digits and
4450     * a sign. The upper bytes are BCD values between 0x0 and 0x9.  The sign
4451     * byte is the least significant byte. This function returns 64-bit 1
4452     * value if sign and digits are valid, 0 otherwise.
4453     *
4454     * This function was originally written using IR code.  It has been
4455     * replaced with a clean helper due to the large amount of IR code
4456     * needed by this function.
4457     */
4458    assign( valid,
4459            mkIRExprCCall( Ity_I64, 0 /*regparms*/,
4460                           "is_BCDstring128_helper",
4461                           fnptr_to_fnentry( vbi, &is_BCDstring128_helper ),
4462                           mkIRExprVec_3( mkU64( Signed ),
4463                                          unop( Iop_V128HIto64, src ),
4464                                          unop( Iop_V128to64, src ) ) ) );
4465    return mkexpr( valid );
4466 }
4467 
BCDstring_zero(IRExpr * src)4468 static IRExpr * BCDstring_zero (IRExpr *src)
4469 {
4470    /* The src is a 128-bit value containing a BCD string.  The function
4471     * returns a 1 if the BCD string values are all zero, 0 otherwise.
4472     */
4473    IRTemp tsrc = newTemp( Ity_V128 );
4474    assign( tsrc, src);
4475 
4476    if ( mode64 ) {
4477       return mkAND1( binop( Iop_CmpEQ64,
4478                             mkU64( 0 ),
4479                             unop( Iop_V128HIto64,
4480                                   mkexpr( tsrc ) ) ),
4481                      binop( Iop_CmpEQ64,
4482                             mkU64( 0 ),
4483                             unop( Iop_V128to64,
4484                                   mkexpr( tsrc ) ) ) );
4485    } else {
4486       /* make this work in 32-bit mode */
4487       return mkAND1(
4488                     mkAND1( binop( Iop_CmpEQ32,
4489                                    mkU32( 0 ),
4490                                    unop( Iop_64HIto32,
4491                                          unop( Iop_V128HIto64,
4492                                                mkexpr( tsrc ) ) ) ),
4493                             binop( Iop_CmpEQ32,
4494                                    mkU32( 0 ),
4495                                    unop( Iop_64to32,
4496                                          unop( Iop_V128HIto64,
4497                                                mkexpr( tsrc ) ) ) ) ),
4498                     mkAND1( binop( Iop_CmpEQ32,
4499                                    mkU32( 0 ),
4500                                    unop( Iop_64HIto32,
4501                                          unop( Iop_V128to64,
4502                                                mkexpr( tsrc ) ) ) ),
4503                             binop( Iop_CmpEQ32,
4504                                    mkU32( 0 ),
4505                                    unop( Iop_64to32,
4506                                          unop( Iop_V128to64,
4507                                                mkexpr( tsrc ) ) ) ) ) );
4508    }
4509 }
4510 
check_BCD_round(IRExpr * src,IRTemp shift)4511 static IRExpr * check_BCD_round (IRExpr *src, IRTemp shift)
4512 {
4513    /* The src is a 128-bit value containing 31 BCD digits with the sign in
4514     * the least significant byte. The bytes are BCD values between 0x0 and 0x9.
4515     * This routine checks the BCD digit in position shift (counting from
4516     * the least significant digit). If the digit is greater then five,
4517     * a 1 is returned indicating the string needs to be rounded up,
4518     * otherwise, 0 is returned.  The value of shift (I64) is the index of
4519     * the BCD digit times four bits.
4520     */
4521    return  binop( Iop_CmpLE64U,
4522                   mkU64( 6 ),
4523                   binop( Iop_And64,
4524                          unop( Iop_V128to64,
4525                                binop( Iop_ShrV128,
4526                                       src,
4527                                       unop( Iop_64to8, mkexpr( shift ) ) ) ),
4528                          mkU64( 0xF ) ) );
4529 }
4530 
increment_BCDstring(const VexAbiInfo * vbi,IRExpr * src,IRExpr * carry_in)4531 static IRTemp increment_BCDstring ( const VexAbiInfo* vbi,
4532                                     IRExpr *src, IRExpr *carry_in )
4533 {
4534    /* The src is a 128-bit value containing 31 BCD digits with the sign in
4535     * the least significant byte. The bytes are BCD values between 0x0 and 0x9.
4536     * This function returns the BCD string incremented by 1.
4537     *
4538     * Call a clean helper to do the computation as it requires a lot of
4539     * IR code to do this.
4540     *
4541     * The helper function takes a 32-bit BCD string, in a 64-bit value, and
4542     * increments the string by the 32-bi carry in value.
4543     *
4544     * The incremented value is returned in the lower 32-bits of the result.
4545     * The carry out is returned in bits [35:32] of the result.  The
4546     * helper function will be called for each of the four 32-bit strings
4547     * that make up the src string passing the returned carry out to the
4548     * next call.
4549     */
4550    IRTemp bcd_result  = newTemp( Ity_V128 );
4551    IRTemp bcd_result0 = newTemp( Ity_I64 );
4552    IRTemp bcd_result1 = newTemp( Ity_I64 );
4553    IRTemp bcd_result2 = newTemp( Ity_I64 );
4554    IRTemp bcd_result3 = newTemp( Ity_I64 );
4555    IRExpr *bcd_string0, *bcd_string1, *bcd_string2, *bcd_string3;
4556 
4557    bcd_string0 = binop( Iop_And64,
4558                         mkU64( 0xFFFFFFFF ), unop( Iop_V128to64, src ) );
4559    bcd_string1 = binop( Iop_Shr64, unop( Iop_V128to64, src ), mkU8( 32 ) );
4560    bcd_string2 = binop( Iop_And64,
4561                         mkU64( 0xFFFFFFFF ), unop( Iop_V128HIto64, src ) );
4562    bcd_string3 = binop( Iop_Shr64, unop( Iop_V128HIto64, src ), mkU8( 32 ) );
4563 
4564    assign( bcd_result0,
4565            mkIRExprCCall( Ity_I64, 0 /*regparms*/,
4566                           "increment_BCDstring32_helper",
4567                           fnptr_to_fnentry( vbi,
4568                                             &increment_BCDstring32_helper ),
4569                           mkIRExprVec_3( mkU64( True /*Signed*/ ),
4570                                          bcd_string0,
4571                                          binop( Iop_32HLto64, mkU32( 0 ),
4572                                                 carry_in ) ) ) );
4573 
4574    assign( bcd_result1,
4575            mkIRExprCCall( Ity_I64, 0 /*regparms*/,
4576                           "increment_BCDstring32_helper",
4577                           fnptr_to_fnentry( vbi,
4578                                             &increment_BCDstring32_helper ),
4579                           mkIRExprVec_3( mkU64( False /*Unsigned*/ ),
4580                                          bcd_string1,
4581                                          binop( Iop_Shr64,
4582                                                 mkexpr( bcd_result0 ),
4583                                                 mkU8( 32 ) ) ) ) );
4584    assign( bcd_result2,
4585            mkIRExprCCall( Ity_I64, 0 /*regparms*/,
4586                           "increment_BCDstring32_helper",
4587                           fnptr_to_fnentry( vbi,
4588                                             &increment_BCDstring32_helper ),
4589                           mkIRExprVec_3( mkU64( False /*Unsigned*/ ),
4590                                          bcd_string2,
4591                                          binop( Iop_Shr64,
4592                                                 mkexpr( bcd_result1 ),
4593                                                 mkU8( 32 ) ) ) ) );
4594    assign( bcd_result3,
4595            mkIRExprCCall( Ity_I64, 0 /*regparms*/,
4596                           "increment_BCDstring32_helper",
4597                           fnptr_to_fnentry( vbi,
4598                                             &increment_BCDstring32_helper ),
4599                           mkIRExprVec_3( mkU64( False /*Unsigned*/ ),
4600                                          bcd_string3,
4601                                          binop( Iop_Shr64,
4602                                                 mkexpr( bcd_result2 ),
4603                                                 mkU8( 32 ) ) ) ) );
4604 
4605    /* Put the 128-bit result together from the intermediate results. Remember
4606     * to mask out the carry out from the upper 32 bits of the results.
4607     */
4608    assign( bcd_result,
4609            binop( Iop_64HLtoV128,
4610                   binop( Iop_Or64,
4611                          binop( Iop_And64,
4612                                 mkU64( 0xFFFFFFFF ), mkexpr (bcd_result2 ) ),
4613                          binop( Iop_Shl64,
4614                                 mkexpr (bcd_result3 ), mkU8( 32 ) ) ),
4615                   binop( Iop_Or64,
4616                          binop( Iop_And64,
4617                                 mkU64( 0xFFFFFFFF ), mkexpr (bcd_result0 ) ),
4618                          binop( Iop_Shl64,
4619                                 mkexpr (bcd_result1 ), mkU8( 32 ) ) ) ) );
4620    return bcd_result;
4621 }
4622 
convert_to_zoned(const VexAbiInfo * vbi,IRExpr * src,IRExpr * upper_byte)4623 static IRExpr * convert_to_zoned ( const VexAbiInfo* vbi,
4624                                    IRExpr *src, IRExpr *upper_byte )
4625 {
4626    /* The function takes a V128 packed decimal value and returns
4627     * the value in zoned format.  Note, the sign of the value is ignored.
4628     */
4629    IRTemp result_low = newTemp( Ity_I64 );
4630    IRTemp result_hi  = newTemp( Ity_I64 );
4631    IRTemp result     = newTemp( Ity_V128 );
4632 
4633    /* Since we can only return 64-bits from a clean helper, we will
4634     * have to get the lower and upper 64-bits separately.
4635     */
4636 
4637    assign( result_low,
4638            mkIRExprCCall( Ity_I64, 0 /*regparms*/,
4639                           "convert_to_zoned_helper",
4640                           fnptr_to_fnentry( vbi, &convert_to_zoned_helper ),
4641                           mkIRExprVec_4( unop( Iop_V128HIto64, src ),
4642                                          unop( Iop_V128to64, src ),
4643                                          upper_byte,
4644                                          mkU64( 0 ) ) ) );
4645 
4646    assign( result_hi,
4647            mkIRExprCCall( Ity_I64, 0 /*regparms*/,
4648                           "convert_to_zoned_helper",
4649                           fnptr_to_fnentry( vbi, &convert_to_zoned_helper ),
4650                           mkIRExprVec_4( unop( Iop_V128HIto64, src ),
4651                                          unop( Iop_V128to64, src ),
4652                                          upper_byte,
4653                                          mkU64( 1 ) ) ) );
4654 
4655 
4656    assign( result,
4657            binop( Iop_64HLtoV128, mkexpr( result_hi ), mkexpr( result_low ) ) );
4658 
4659    return mkexpr( result );
4660 }
4661 
convert_to_national(const VexAbiInfo * vbi,IRExpr * src)4662 static IRExpr * convert_to_national ( const VexAbiInfo* vbi,  IRExpr *src ) {
4663    /* The function takes 128-bit value which has a 64-bit packed decimal
4664     * value in the lower 64-bits of the source.  The packed decimal is
4665     * converted to the national format via a clean helper.  The clean
4666     * helper is used to to the large amount of IR code needed to do the
4667     * conversion.  The helper returns the upper 64-bits of the 128-bit
4668     * result if return_upper != 0.  Otherwise, the lower 64-bits of the
4669     * result is returned.
4670     */
4671    IRTemp result_low = newTemp( Ity_I64 );
4672    IRTemp result_hi  = newTemp( Ity_I64 );
4673    IRTemp result     = newTemp( Ity_V128 );
4674 
4675    /* Since we can only return 64-bits from a clean helper, we will
4676     * have to get the lower and upper 64-bits separately.
4677     */
4678 
4679    assign( result_low,
4680            mkIRExprCCall( Ity_I64, 0 /*regparms*/,
4681                           "convert_to_national_helper",
4682                           fnptr_to_fnentry( vbi, &convert_to_national_helper ),
4683                           mkIRExprVec_2( unop( Iop_V128to64, src ),
4684                                          mkU64( 0 ) ) ) );
4685 
4686    assign( result_hi,
4687            mkIRExprCCall( Ity_I64, 0 /*regparms*/,
4688                           "convert_to_national_helper",
4689                           fnptr_to_fnentry( vbi, &convert_to_national_helper ),
4690                           mkIRExprVec_2( unop( Iop_V128to64, src ),
4691                                          mkU64( 1 ) ) ) );
4692 
4693    assign( result,
4694            binop( Iop_64HLtoV128, mkexpr( result_hi ), mkexpr( result_low ) ) );
4695 
4696    return mkexpr( result );
4697 }
4698 
convert_from_zoned(const VexAbiInfo * vbi,IRExpr * src)4699 static IRExpr * convert_from_zoned ( const VexAbiInfo* vbi, IRExpr *src ) {
4700    /* The function takes 128-bit zoned value and returns a signless 64-bit
4701     * packed decimal value in the lower 64-bits of the 128-bit result.
4702     */
4703    IRTemp result = newTemp( Ity_V128 );
4704 
4705    assign( result,
4706            binop( Iop_ShlV128,
4707                   binop( Iop_64HLtoV128,
4708                          mkU64( 0 ),
4709                          mkIRExprCCall( Ity_I64, 0 /*regparms*/,
4710                                         "convert_from_zoned_helper",
4711                                         fnptr_to_fnentry( vbi,
4712                                                           &convert_from_zoned_helper ),
4713                                         mkIRExprVec_2( unop( Iop_V128HIto64,
4714                                                              src ),
4715                                                        unop( Iop_V128to64,
4716                                                              src ) ) ) ),
4717                   mkU8( 4 ) ) );
4718 
4719    return mkexpr( result );
4720 }
4721 
convert_from_national(const VexAbiInfo * vbi,IRExpr * src)4722 static IRExpr * convert_from_national ( const VexAbiInfo* vbi, IRExpr *src ) {
4723    /* The function takes 128-bit national value and returns a 64-bit
4724     * packed decimal value.
4725     */
4726    IRTemp result = newTemp( Ity_I64);
4727 
4728    assign( result,
4729            mkIRExprCCall( Ity_I64, 0 /*regparms*/,
4730                           "convert_from_national_helper",
4731                           fnptr_to_fnentry( vbi,
4732                                             &convert_from_national_helper ),
4733                           mkIRExprVec_2( unop( Iop_V128HIto64,
4734                                                src ),
4735                                          unop( Iop_V128to64,
4736                                                src ) ) ) );
4737 
4738    return mkexpr( result );
4739 }
4740 
UNSIGNED_CMP_GT_V128(IRExpr * vA,IRExpr * vB)4741 static IRExpr * UNSIGNED_CMP_GT_V128 ( IRExpr *vA, IRExpr *vB ) {
4742    /* This function does an unsigned compare of two V128 values. The
4743     * function is for use in 32-bit mode only as it is expensive.  The
4744     * issue is that compares (GT, LT, EQ) are not supported for operands
4745     * larger then 32-bits when running in 32-bit mode.  The function returns
4746     * a 1-bit expression, 1 for TRUE and 0 for FALSE.
4747     */
4748    IRTemp vA_word0 = newTemp( Ity_I32);
4749    IRTemp vA_word1 = newTemp( Ity_I32);
4750    IRTemp vA_word2 = newTemp( Ity_I32);
4751    IRTemp vA_word3 = newTemp( Ity_I32);
4752    IRTemp vB_word0 = newTemp( Ity_I32);
4753    IRTemp vB_word1 = newTemp( Ity_I32);
4754    IRTemp vB_word2 = newTemp( Ity_I32);
4755    IRTemp vB_word3 = newTemp( Ity_I32);
4756 
4757    IRTemp eq_word1 = newTemp( Ity_I1);
4758    IRTemp eq_word2 = newTemp( Ity_I1);
4759    IRTemp eq_word3 = newTemp( Ity_I1);
4760 
4761 
4762    IRExpr *gt_word0, *gt_word1, *gt_word2, *gt_word3;
4763    IRExpr *eq_word3_2, *eq_word3_2_1;
4764    IRTemp result = newTemp( Ity_I1 );
4765 
4766    assign( vA_word0, unop( Iop_64to32, unop( Iop_V128to64, vA ) ) );
4767    assign( vA_word1, unop( Iop_64HIto32, unop( Iop_V128to64, vA ) ) );
4768    assign( vA_word2, unop( Iop_64to32, unop( Iop_V128HIto64, vA ) ) );
4769    assign( vA_word3, unop( Iop_64HIto32, unop( Iop_V128HIto64, vA ) ) );
4770 
4771    assign( vB_word0, unop( Iop_64to32, unop( Iop_V128to64, vB ) ) );
4772    assign( vB_word1, unop( Iop_64HIto32, unop( Iop_V128to64, vB ) ) );
4773    assign( vB_word2, unop( Iop_64to32, unop( Iop_V128HIto64, vB ) ) );
4774    assign( vB_word3, unop( Iop_64HIto32, unop( Iop_V128HIto64, vB ) ) );
4775 
4776    assign( eq_word3, binop( Iop_CmpEQ32, mkexpr( vA_word3 ),
4777                             mkexpr( vB_word3 ) ) );
4778    assign( eq_word2, binop( Iop_CmpEQ32, mkexpr( vA_word2 ),
4779                             mkexpr( vB_word2 ) ) );
4780    assign( eq_word1, binop( Iop_CmpEQ32, mkexpr( vA_word1 ),
4781                             mkexpr( vB_word1 ) ) );
4782 
4783    gt_word3 = binop( Iop_CmpLT32U, mkexpr( vB_word3 ), mkexpr( vA_word3 ) );
4784    gt_word2 = binop( Iop_CmpLT32U, mkexpr( vB_word2 ), mkexpr( vA_word2 ) );
4785    gt_word1 = binop( Iop_CmpLT32U, mkexpr( vB_word1 ), mkexpr( vA_word1 ) );
4786    gt_word0 = binop( Iop_CmpLT32U, mkexpr( vB_word0 ), mkexpr( vA_word0 ) );
4787 
4788    eq_word3_2   = mkAND1( mkexpr( eq_word3 ), mkexpr( eq_word2 ) );
4789    eq_word3_2_1 = mkAND1( mkexpr( eq_word1 ), eq_word3_2 );
4790 
4791    assign( result, mkOR1(
4792                          mkOR1( gt_word3,
4793                                 mkAND1( mkexpr( eq_word3 ), gt_word2 ) ),
4794                          mkOR1( mkAND1( eq_word3_2, gt_word1 ),
4795                                 mkAND1( eq_word3_2_1, gt_word0 ) ) ) );
4796    return mkexpr( result );
4797 }
4798 
4799 /*------------------------------------------------------------*/
4800 /* Transactional memory helpers
4801  *
4802  *------------------------------------------------------------*/
4803 
generate_TMreason(UInt failure_code,UInt persistant,UInt nest_overflow,UInt tm_exact)4804 static ULong generate_TMreason( UInt failure_code,
4805                                              UInt persistant,
4806                                              UInt nest_overflow,
4807                                              UInt tm_exact )
4808 {
4809    ULong tm_err_code =
4810      ( (ULong) 0) << (63-6)   /* Failure code */
4811      | ( (ULong) persistant) << (63-7)     /* Failure persistant */
4812      | ( (ULong) 0) << (63-8)   /* Disallowed */
4813      | ( (ULong) nest_overflow) << (63-9)   /* Nesting Overflow */
4814      | ( (ULong) 0) << (63-10)  /* Footprint Overflow */
4815      | ( (ULong) 0) << (63-11)  /* Self-Induced Conflict */
4816      | ( (ULong) 0) << (63-12)  /* Non-Transactional Conflict */
4817      | ( (ULong) 0) << (63-13)  /* Transactional Conflict */
4818      | ( (ULong) 0) << (63-14)  /* Translation Invalidation Conflict */
4819      | ( (ULong) 0) << (63-15)  /* Implementation-specific */
4820      | ( (ULong) 0) << (63-16)  /* Instruction Fetch Conflict */
4821      | ( (ULong) 0) << (63-30)  /* Reserved */
4822      | ( (ULong) 0) << (63-31)  /* Abort */
4823      | ( (ULong) 0) << (63-32)  /* Suspend */
4824      | ( (ULong) 0) << (63-33)  /* Reserved */
4825      | ( (ULong) 0) << (63-35)  /* Privilege */
4826      | ( (ULong) 0) << (63-36)  /* Failure Summary */
4827      | ( (ULong) tm_exact) << (63-37)  /* TFIAR Exact */
4828      | ( (ULong) 0) << (63-38)  /* ROT */
4829      | ( (ULong) 0) << (63-51)  /* Reserved */
4830      | ( (ULong) 0) << (63-63);  /* Transaction Level */
4831 
4832      return tm_err_code;
4833 }
4834 
storeTMfailure(Addr64 err_address,ULong tm_reason,Addr64 handler_address)4835 static void storeTMfailure( Addr64 err_address, ULong tm_reason,
4836                             Addr64 handler_address )
4837 {
4838    putGST( PPC_GST_TFIAR,   mkU64( err_address ) );
4839    putGST( PPC_GST_TEXASR,  mkU64( tm_reason ) );
4840    putGST( PPC_GST_TEXASRU, mkU32( 0 ) );
4841    putGST( PPC_GST_TFHAR,   mkU64( handler_address ) );
4842 }
4843 
4844 /*------------------------------------------------------------*/
4845 /*--- Integer Instruction Translation                     --- */
4846 /*------------------------------------------------------------*/
4847 
4848 /*
4849   Integer Arithmetic Instructions
4850 */
dis_int_mult_add(UInt theInstr)4851 static Bool dis_int_mult_add ( UInt theInstr )
4852 {
4853    /* VA-Form */
4854    UChar rD_addr = ifieldRegDS( theInstr );
4855    UChar rA_addr = ifieldRegA( theInstr );
4856    UChar rB_addr = ifieldRegB( theInstr );
4857    UChar rC_addr = ifieldRegC( theInstr );
4858    UInt  opc2    = IFIELD( theInstr, 0, 6 );
4859    IRType ty     = Ity_I64;
4860    IRTemp rA     = newTemp( ty );
4861    IRTemp rB     = newTemp( ty );
4862    IRTemp rC     = newTemp( ty );
4863    IRTemp rD     = newTemp( ty );
4864    IRTemp tmpLo  = newTemp( Ity_I64 );
4865    IRTemp tmpHi  = newTemp( Ity_I64 );
4866    IRTemp tmp2Hi = newTemp( Ity_I64 );
4867    IRTemp result = newTemp( Ity_I128 );
4868    IRTemp resultLo = newTemp( Ity_I64 );
4869    IRExpr* carryout;
4870 
4871    assign( rA, getIReg( rA_addr ) );
4872    assign( rB, getIReg( rB_addr ) );
4873    assign( rC, getIReg( rC_addr ) );
4874 
4875    switch (opc2) {
4876    case 0x30:  // maddhd  multiply-add High doubleword signed
4877       DIP("maddhd r%u,r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr, rC_addr);
4878 
4879       assign( result, binop( Iop_MullS64, mkexpr( rA ), mkexpr( rB ) ) );
4880       assign( tmpLo, unop( Iop_128to64, mkexpr( result ) ) );
4881       assign( tmpHi, unop( Iop_128HIto64, mkexpr( result ) ) );
4882 
4883       /* Multiply rA and rB then add rC.  If the lower 32-bits of the result
4884        * is less then rC and the result rA * rB, a carry out of the lower 32
4885        * bits occurred and the upper 32 bits must be incremented by 1. Sign
4886        * extend rC and do the add to the upper 64 bits to handle the
4887        * negative case for rC.
4888        */
4889       assign( resultLo, binop( Iop_Add64, mkexpr( tmpLo ), mkexpr( rC ) ) );
4890       assign( tmp2Hi, binop( Iop_Add64,
4891                              mkexpr( tmpHi ),
4892                              unop( Iop_1Sto64,
4893                                    unop( Iop_64to1,
4894                                          binop( Iop_Shr64,
4895                                                 mkexpr( rC ),
4896                                                 mkU8( 63 ) ) ) ) ) );
4897 
4898       /* need to do calculation for the upper 32 bit result */
4899       carryout = mkAND1( binop( Iop_CmpLT64U,
4900                                 mkexpr( resultLo ), mkexpr( rC ) ),
4901                          binop( Iop_CmpLT64U,
4902                                 mkexpr( resultLo ), mkexpr( tmpLo ) ) );
4903       assign( rD, binop( Iop_Add64,
4904                          mkexpr( tmp2Hi ),
4905                          unop( Iop_1Uto64, carryout ) ) );
4906       break;
4907 
4908    case 0x31:  // maddhdu   multiply-add High doubleword unsigned
4909       DIP("maddhdu r%u,r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr, rC_addr);
4910 
4911       assign( result, binop( Iop_MullU64, mkexpr( rA ), mkexpr( rB ) ) );
4912       assign( tmpLo, unop( Iop_128to64, mkexpr( result ) ) );
4913       assign( tmpHi, unop( Iop_128HIto64, mkexpr( result ) ) );
4914 
4915       /* Add rC, if the lower 32-bits of the result is less then rC and
4916        * tmpLo, a carry out of the lower 32 bits occurred. Upper 32 bits
4917        * must be incremented by 1.
4918        */
4919       assign( resultLo, binop( Iop_Add64, mkexpr( tmpLo ), mkexpr( rC ) ) );
4920 
4921       /* need to do calculation for the upper 32 bit result */
4922       carryout = mkAND1( binop( Iop_CmpLT64U,
4923                                 mkexpr(resultLo), mkexpr( rC ) ),
4924                          binop( Iop_CmpLT64U,
4925                                 mkexpr(resultLo), mkexpr( tmpLo ) ) );
4926       assign( rD, binop( Iop_Add64,
4927                          mkexpr( tmpHi ),
4928                          unop( Iop_1Uto64, carryout ) ) );
4929       break;
4930 
4931    case 0x33:  // maddld   multiply-add Low doubleword
4932       DIP("maddld r%u,r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr, rC_addr);
4933 
4934       assign( result, binop( Iop_MullS64, mkexpr( rA ), mkexpr( rB ) ) );
4935       assign( tmpLo, unop( Iop_128to64, mkexpr( result ) ) );
4936       assign( tmpHi, unop( Iop_128HIto64, mkexpr( result ) ) );
4937 
4938       assign( rD, binop( Iop_Add64, mkexpr( tmpLo ), mkexpr( rC ) ) );
4939       break;
4940 
4941    default:
4942       vex_printf("dis_int_mult(ppc): unrecognized instruction\n");
4943       return False;
4944    }
4945 
4946    putIReg( rD_addr, mkexpr(rD) );
4947 
4948    return True;
4949 }
4950 
dis_int_arith(UInt theInstr)4951 static Bool dis_int_arith ( UInt theInstr )
4952 {
4953    /* D-Form, XO-Form */
4954    UChar opc1    = ifieldOPC(theInstr);
4955    UChar rD_addr = ifieldRegDS(theInstr);
4956    UChar rA_addr = ifieldRegA(theInstr);
4957    UInt  uimm16  = ifieldUIMM16(theInstr);
4958    UChar rB_addr = ifieldRegB(theInstr);
4959    UChar flag_OE = ifieldBIT10(theInstr);
4960    UInt  opc2    = ifieldOPClo9(theInstr);
4961    UChar flag_rC = ifieldBIT0(theInstr);
4962 
4963    Long   simm16 = extend_s_16to64(uimm16);
4964    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
4965    IRTemp rA     = newTemp(ty);
4966    IRTemp rB     = newTemp(ty);
4967    IRTemp rD     = newTemp(ty);
4968 
4969    Bool do_rc = False;
4970 
4971    assign( rA, getIReg(rA_addr) );
4972    assign( rB, getIReg(rB_addr) );         // XO-Form: rD, rA, rB
4973 
4974    switch (opc1) {
4975    /* D-Form */
4976    case 0x0C: // addic  (Add Immediate Carrying, PPC32 p351
4977       DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
4978       assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
4979                          mkSzExtendS16(ty, uimm16) ) );
4980       set_XER_CA_CA32( ty, PPCG_FLAG_OP_ADD,
4981                        mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
4982                        mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
4983       break;
4984 
4985    case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352)
4986       DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
4987       assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
4988                          mkSzExtendS16(ty, uimm16) ) );
4989       set_XER_CA_CA32( ty, PPCG_FLAG_OP_ADD,
4990                        mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
4991                        mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
4992       do_rc = True;  // Always record to CR
4993       flag_rC = 1;
4994       break;
4995 
4996    case 0x0E: // addi   (Add Immediate, PPC32 p350)
4997       // li rD,val   == addi rD,0,val
4998       // la disp(rA) == addi rD,rA,disp
4999       if ( rA_addr == 0 ) {
5000          DIP("li r%u,%d\n", rD_addr, (Int)simm16);
5001          assign( rD, mkSzExtendS16(ty, uimm16) );
5002       } else {
5003          DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
5004          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
5005                             mkSzExtendS16(ty, uimm16) ) );
5006       }
5007       break;
5008 
5009    case 0x0F: // addis  (Add Immediate Shifted, PPC32 p353)
5010       // lis rD,val == addis rD,0,val
5011       if ( rA_addr == 0 ) {
5012          DIP("lis r%u,%d\n", rD_addr, (Int)simm16);
5013          assign( rD, mkSzExtendS32(ty, uimm16 << 16) );
5014       } else {
5015          DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (UInt)simm16);
5016          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
5017                             mkSzExtendS32(ty, uimm16 << 16) ) );
5018       }
5019       break;
5020 
5021    case 0x07: // mulli    (Multiply Low Immediate, PPC32 p490)
5022       DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
5023       if (mode64)
5024          assign( rD, unop(Iop_128to64,
5025                           binop(Iop_MullS64, mkexpr(rA),
5026                                 mkSzExtendS16(ty, uimm16))) );
5027       else
5028          assign( rD, unop(Iop_64to32,
5029                           binop(Iop_MullS32, mkexpr(rA),
5030                                 mkSzExtendS16(ty, uimm16))) );
5031       break;
5032 
5033    case 0x08: // subfic   (Subtract from Immediate Carrying, PPC32 p540)
5034       DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
5035       // rD = simm16 - rA
5036       assign( rD, binop( mkSzOp(ty, Iop_Sub8),
5037                          mkSzExtendS16(ty, uimm16),
5038                          mkexpr(rA)) );
5039       set_XER_CA_CA32( ty, PPCG_FLAG_OP_SUBFI,
5040                        mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
5041                        mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
5042       break;
5043 
5044    /* XO-Form */
5045    case 0x1F:
5046       do_rc = True;    // All below record to CR
5047 
5048       switch (opc2) {
5049       case 0x10A: // add  (Add, PPC32 p347)
5050          DIP("add%s%s r%u,r%u,r%u\n",
5051              flag_OE ? "o" : "", flag_rC ? ".":"",
5052              rD_addr, rA_addr, rB_addr);
5053          assign( rD, binop( mkSzOp(ty, Iop_Add8),
5054                             mkexpr(rA), mkexpr(rB) ) );
5055          if (flag_OE) {
5056             set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_ADD,
5057                                 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
5058          }
5059          break;
5060 
5061       case 0x00A: // addc      (Add Carrying, PPC32 p348)
5062          DIP("addc%s%s r%u,r%u,r%u\n",
5063              flag_OE ? "o" : "", flag_rC ? ".":"",
5064              rD_addr, rA_addr, rB_addr);
5065          assign( rD, binop( mkSzOp(ty, Iop_Add8),
5066                             mkexpr(rA), mkexpr(rB)) );
5067          set_XER_CA_CA32( ty, PPCG_FLAG_OP_ADD,
5068                           mkexpr(rD), mkexpr(rA), mkexpr(rB),
5069                           mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
5070          if (flag_OE) {
5071             set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_ADD,
5072                                 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
5073          }
5074          break;
5075 
5076       case 0x08A: { // adde      (Add Extended, PPC32 p349)
5077          IRTemp old_xer_ca = newTemp(ty);
5078          DIP("adde%s%s r%u,r%u,r%u\n",
5079              flag_OE ? "o" : "", flag_rC ? ".":"",
5080              rD_addr, rA_addr, rB_addr);
5081          // rD = rA + rB + XER[CA]
5082          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA_32(), False) );
5083          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
5084                             binop( mkSzOp(ty, Iop_Add8),
5085                                    mkexpr(rB), mkexpr(old_xer_ca))) );
5086          set_XER_CA_CA32( ty, PPCG_FLAG_OP_ADDE,
5087                           mkexpr(rD), mkexpr(rA), mkexpr(rB),
5088                           mkexpr(old_xer_ca) );
5089          if (flag_OE) {
5090             set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_ADDE,
5091                                 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
5092          }
5093          break;
5094       }
5095 
5096       case 0xAA: {// addex (Add Extended alternate carry bit Z23-form)
5097          DIP("addex r%u,r%u,r%u,%d\n", rD_addr, rA_addr, rB_addr, (Int)flag_OE);
5098          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
5099                             binop( mkSzOp(ty, Iop_Add8), mkexpr(rB),
5100                                    mkWidenFrom8( ty, getXER_OV(), False ) ) ) );
5101 
5102          /* CY bit is same as OE bit */
5103          if (flag_OE == 0) {
5104             /* Exception, do not set SO bit */
5105             set_XER_OV_OV32( ty, PPCG_FLAG_OP_ADDE,
5106                              mkexpr(rD), mkexpr(rA), mkexpr(rB) );
5107          } else {
5108             /* CY=1, 2 and 3 (AKA flag_OE) are reserved */
5109             vex_printf("addex instruction, CY = %d is reserved.\n", flag_OE);
5110             vpanic("addex instruction\n");
5111          }
5112          break;
5113       }
5114 
5115       case 0x0EA: { // addme     (Add to Minus One Extended, PPC32 p354)
5116          IRTemp old_xer_ca = newTemp(ty);
5117          IRExpr *min_one;
5118          if (rB_addr != 0) {
5119             vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n");
5120             return False;
5121          }
5122          DIP("addme%s%s r%u,r%u,r%u\n",
5123              flag_OE ? "o" : "", flag_rC ? ".":"",
5124              rD_addr, rA_addr, rB_addr);
5125          // rD = rA + (-1) + XER[CA]
5126          // => Just another form of adde
5127          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA_32(), False) );
5128          min_one = mkSzImm(ty, (Long)-1);
5129          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
5130                             binop( mkSzOp(ty, Iop_Add8),
5131                                    min_one, mkexpr(old_xer_ca)) ));
5132          set_XER_CA_CA32( ty, PPCG_FLAG_OP_ADDE,
5133                           mkexpr(rD), mkexpr(rA), min_one,
5134                           mkexpr(old_xer_ca) );
5135          if (flag_OE) {
5136             set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_ADDE,
5137                                 mkexpr(rD), mkexpr(rA), min_one );
5138          }
5139          break;
5140       }
5141 
5142       case 0x0CA: { // addze      (Add to Zero Extended, PPC32 p355)
5143          IRTemp old_xer_ca = newTemp(ty);
5144          if (rB_addr != 0) {
5145             vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n");
5146             return False;
5147          }
5148          DIP("addze%s%s r%u,r%u,r%u\n",
5149              flag_OE ? "o" : "", flag_rC ? ".":"",
5150              rD_addr, rA_addr, rB_addr);
5151          // rD = rA + (0) + XER[CA]
5152          // => Just another form of adde
5153          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA_32(), False) );
5154          assign( rD, binop( mkSzOp(ty, Iop_Add8),
5155                             mkexpr(rA), mkexpr(old_xer_ca)) );
5156          set_XER_CA_CA32( ty, PPCG_FLAG_OP_ADDE,
5157                           mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
5158                           mkexpr(old_xer_ca) );
5159          if (flag_OE) {
5160             set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_ADDE,
5161                                 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
5162          }
5163          break;
5164       }
5165 
5166       case 0x1EB: // divw       (Divide Word, PPC32 p388)
5167          DIP("divw%s%s r%u,r%u,r%u\n",
5168              flag_OE ? "o" : "", flag_rC ? ".":"",
5169              rD_addr, rA_addr, rB_addr);
5170          if (mode64) {
5171             /* Note:
5172                XER settings are mode independent, and reflect the
5173                overflow of the low-order 32bit result
5174                CR0[LT|GT|EQ] are undefined if flag_rC && mode64
5175             */
5176             /* rD[hi32] are undefined: setting them to sign of lo32
5177                 - makes set_CR0 happy */
5178             IRExpr* dividend = mk64lo32Sto64( mkexpr(rA) );
5179             IRExpr* divisor  = mk64lo32Sto64( mkexpr(rB) );
5180             assign( rD, mk64lo32Uto64( binop(Iop_DivS64, dividend,
5181                                                          divisor) ) );
5182             if (flag_OE) {
5183                set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVW,
5184                                    mkexpr(rD), dividend, divisor );
5185             }
5186          } else {
5187             assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) );
5188             if (flag_OE) {
5189                set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVW,
5190                                    mkexpr(rD), mkexpr(rA), mkexpr(rB) );
5191             }
5192          }
5193          /* Note:
5194             if (0x8000_0000 / -1) or (x / 0)
5195             => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
5196             => But _no_ exception raised. */
5197          break;
5198 
5199       case 0x1CB: // divwu      (Divide Word Unsigned, PPC32 p389)
5200          DIP("divwu%s%s r%u,r%u,r%u\n",
5201              flag_OE ? "o" : "", flag_rC ? ".":"",
5202              rD_addr, rA_addr, rB_addr);
5203          if (mode64) {
5204             /* Note:
5205                XER settings are mode independent, and reflect the
5206                overflow of the low-order 32bit result
5207                CR0[LT|GT|EQ] are undefined if flag_rC && mode64
5208             */
5209             IRExpr* dividend = mk64lo32Uto64( mkexpr(rA) );
5210             IRExpr* divisor  = mk64lo32Uto64( mkexpr(rB) );
5211             assign( rD, mk64lo32Uto64( binop(Iop_DivU64, dividend,
5212                                                          divisor) ) );
5213             if (flag_OE) {
5214                set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVWU,
5215                                    mkexpr(rD), dividend, divisor );
5216             }
5217          } else {
5218             assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) );
5219             if (flag_OE) {
5220                set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVWU,
5221                                    mkexpr(rD), mkexpr(rA), mkexpr(rB) );
5222             }
5223          }
5224          /* Note: ditto comment divw, for (x / 0) */
5225          break;
5226 
5227       case 0x04B: // mulhw      (Multiply High Word, PPC32 p488)
5228          if (flag_OE != 0) {
5229             vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n");
5230             return False;
5231          }
5232          DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
5233              rD_addr, rA_addr, rB_addr);
5234          if (mode64) {
5235             /* rD[hi32] are undefined: setting them to sign of lo32
5236                 - makes set_CR0 happy */
5237             assign( rD, binop(Iop_Sar64,
5238                            binop(Iop_Mul64,
5239                                  mk64lo32Sto64( mkexpr(rA) ),
5240                                  mk64lo32Sto64( mkexpr(rB) )),
5241                               mkU8(32)) );
5242          } else {
5243             assign( rD, unop(Iop_64HIto32,
5244                              binop(Iop_MullS32,
5245                                    mkexpr(rA), mkexpr(rB))) );
5246          }
5247          break;
5248 
5249       case 0x00B: // mulhwu    (Multiply High Word Unsigned, PPC32 p489)
5250          if (flag_OE != 0) {
5251             vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n");
5252             return False;
5253          }
5254          DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
5255              rD_addr, rA_addr, rB_addr);
5256          if (mode64) {
5257             /* rD[hi32] are undefined: setting them to sign of lo32
5258                 - makes set_CR0 happy */
5259             assign( rD, binop(Iop_Sar64,
5260                            binop(Iop_Mul64,
5261                                  mk64lo32Uto64( mkexpr(rA) ),
5262                                  mk64lo32Uto64( mkexpr(rB) ) ),
5263                               mkU8(32)) );
5264          } else {
5265             assign( rD, unop(Iop_64HIto32,
5266                              binop(Iop_MullU32,
5267                                    mkexpr(rA), mkexpr(rB))) );
5268          }
5269          break;
5270 
5271       case 0x0EB: // mullw      (Multiply Low Word, PPC32 p491)
5272          DIP("mullw%s%s r%u,r%u,r%u\n",
5273              flag_OE ? "o" : "", flag_rC ? ".":"",
5274              rD_addr, rA_addr, rB_addr);
5275          if (mode64) {
5276             /* rD[hi32] are undefined: setting them to sign of lo32
5277                 - set_XER_OV() and set_CR0() depend on this */
5278             IRExpr *a = unop(Iop_64to32, mkexpr(rA) );
5279             IRExpr *b = unop(Iop_64to32, mkexpr(rB) );
5280             assign( rD, binop(Iop_MullS32, a, b) );
5281             if (flag_OE) {
5282                set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_MULLW,
5283                                 mkexpr(rD),
5284                                 unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) );
5285             }
5286          } else {
5287             assign( rD, unop(Iop_64to32,
5288                              binop(Iop_MullU32,
5289                                    mkexpr(rA), mkexpr(rB))) );
5290             if (flag_OE) {
5291                set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_MULLW,
5292                                    mkexpr(rD), mkexpr(rA), mkexpr(rB) );
5293             }
5294          }
5295          break;
5296 
5297       case 0x068: // neg        (Negate, PPC32 p493)
5298          if (rB_addr != 0) {
5299             vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n");
5300             return False;
5301          }
5302          DIP("neg%s%s r%u,r%u\n",
5303              flag_OE ? "o" : "", flag_rC ? ".":"",
5304              rD_addr, rA_addr);
5305          // rD = (~rA) + 1
5306          assign( rD, binop( mkSzOp(ty, Iop_Add8),
5307                             unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ),
5308                             mkSzImm(ty, 1)) );
5309          if (flag_OE) {
5310             set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_NEG,
5311                                 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
5312          }
5313          break;
5314 
5315       case 0x028: // subf       (Subtract From, PPC32 p537)
5316          DIP("subf%s%s r%u,r%u,r%u\n",
5317              flag_OE ? "o" : "", flag_rC ? ".":"",
5318              rD_addr, rA_addr, rB_addr);
5319          // rD = rB - rA
5320          assign( rD, binop( mkSzOp(ty, Iop_Sub8),
5321                             mkexpr(rB), mkexpr(rA)) );
5322          if (flag_OE) {
5323             set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_SUBF,
5324                                 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
5325          }
5326          break;
5327 
5328       case 0x008: // subfc      (Subtract from Carrying, PPC32 p538)
5329          DIP("subfc%s%s r%u,r%u,r%u\n",
5330              flag_OE ? "o" : "", flag_rC ? ".":"",
5331              rD_addr, rA_addr, rB_addr);
5332          // rD = rB - rA
5333          assign( rD, binop( mkSzOp(ty, Iop_Sub8),
5334                             mkexpr(rB), mkexpr(rA)) );
5335          set_XER_CA_CA32( ty, PPCG_FLAG_OP_SUBFC,
5336                           mkexpr(rD), mkexpr(rA), mkexpr(rB),
5337                           mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
5338          if (flag_OE) {
5339             set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_SUBFC,
5340                                 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
5341          }
5342          break;
5343 
5344       case 0x088: {// subfe      (Subtract from Extended, PPC32 p539)
5345          IRTemp old_xer_ca = newTemp(ty);
5346          DIP("subfe%s%s r%u,r%u,r%u\n",
5347              flag_OE ? "o" : "", flag_rC ? ".":"",
5348              rD_addr, rA_addr, rB_addr);
5349          // rD = (log not)rA + rB + XER[CA]
5350          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA_32(), False) );
5351          assign( rD, binop( mkSzOp(ty, Iop_Add8),
5352                             unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
5353                             binop( mkSzOp(ty, Iop_Add8),
5354                                    mkexpr(rB), mkexpr(old_xer_ca))) );
5355          set_XER_CA_CA32( ty, PPCG_FLAG_OP_SUBFE,
5356                           mkexpr(rD), mkexpr(rA), mkexpr(rB),
5357                           mkexpr(old_xer_ca) );
5358          if (flag_OE) {
5359             set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_SUBFE,
5360                                 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
5361          }
5362          break;
5363       }
5364 
5365       case 0x0E8: { // subfme    (Subtract from -1 Extended, PPC32 p541)
5366          IRTemp old_xer_ca = newTemp(ty);
5367          IRExpr *min_one;
5368          if (rB_addr != 0) {
5369             vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n");
5370             return False;
5371          }
5372          DIP("subfme%s%s r%u,r%u\n",
5373              flag_OE ? "o" : "", flag_rC ? ".":"",
5374              rD_addr, rA_addr);
5375          // rD = (log not)rA + (-1) + XER[CA]
5376          // => Just another form of subfe
5377          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA_32(), False) );
5378          min_one = mkSzImm(ty, (Long)-1);
5379          assign( rD, binop( mkSzOp(ty, Iop_Add8),
5380                             unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
5381                             binop( mkSzOp(ty, Iop_Add8),
5382                                    min_one, mkexpr(old_xer_ca))) );
5383          set_XER_CA_CA32( ty, PPCG_FLAG_OP_SUBFE,
5384                           mkexpr(rD), mkexpr(rA), min_one,
5385                           mkexpr(old_xer_ca) );
5386          if (flag_OE) {
5387             set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_SUBFE,
5388                                 mkexpr(rD), mkexpr(rA), min_one );
5389          }
5390          break;
5391       }
5392 
5393       case 0x0C8: { // subfze  (Subtract from Zero Extended, PPC32 p542)
5394          IRTemp old_xer_ca = newTemp(ty);
5395          if (rB_addr != 0) {
5396             vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n");
5397             return False;
5398          }
5399          DIP("subfze%s%s r%u,r%u\n",
5400              flag_OE ? "o" : "", flag_rC ? ".":"",
5401              rD_addr, rA_addr);
5402          // rD = (log not)rA + (0) + XER[CA]
5403          // => Just another form of subfe
5404          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA_32(), False) );
5405          assign( rD, binop( mkSzOp(ty, Iop_Add8),
5406                            unop( mkSzOp(ty, Iop_Not8),
5407                                  mkexpr(rA)), mkexpr(old_xer_ca)) );
5408          set_XER_CA_CA32( ty, PPCG_FLAG_OP_SUBFE,
5409                           mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
5410                           mkexpr(old_xer_ca) );
5411          if (flag_OE) {
5412             set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_SUBFE,
5413                                 mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
5414          }
5415          break;
5416       }
5417 
5418 
5419       /* 64bit Arithmetic */
5420       case 0x49:  // mulhd (Multiply High DWord, PPC64 p539)
5421          if (flag_OE != 0) {
5422             vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n");
5423             return False;
5424          }
5425          DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? ".":"",
5426              rD_addr, rA_addr, rB_addr);
5427          assign( rD, unop(Iop_128HIto64,
5428                           binop(Iop_MullS64,
5429                                 mkexpr(rA), mkexpr(rB))) );
5430 
5431          break;
5432 
5433       case 0x9:   // mulhdu  (Multiply High DWord Unsigned, PPC64 p540)
5434          if (flag_OE != 0) {
5435             vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n");
5436             return False;
5437          }
5438          DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
5439              rD_addr, rA_addr, rB_addr);
5440          assign( rD, unop(Iop_128HIto64,
5441                           binop(Iop_MullU64,
5442                                 mkexpr(rA), mkexpr(rB))) );
5443          break;
5444 
5445       case 0xE9:  // mulld (Multiply Low DWord, PPC64 p543)
5446          DIP("mulld%s%s r%u,r%u,r%u\n",
5447              flag_OE ? "o" : "", flag_rC ? ".":"",
5448              rD_addr, rA_addr, rB_addr);
5449          assign( rD, binop(Iop_Mul64, mkexpr(rA), mkexpr(rB)) );
5450          if (flag_OE) {
5451             set_XER_OV_64( PPCG_FLAG_OP_MULLD,
5452                            mkexpr(rD), mkexpr(rA), mkexpr(rB) );
5453             /* OV is set to 1 if product isn't representable.
5454              * In this case also need to set OV32 and SO to 1,
5455              * i.e. copy OV to OV32 and SO.
5456              */
5457             copy_OV_to_OV32();
5458             update_SO();
5459          }
5460          break;
5461 
5462       case 0x1E9: // divd (Divide DWord, PPC64 p419)
5463          DIP("divd%s%s r%u,r%u,r%u\n",
5464              flag_OE ? "o" : "", flag_rC ? ".":"",
5465              rD_addr, rA_addr, rB_addr);
5466          assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) );
5467          if (flag_OE) {
5468             set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVW,
5469                                 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
5470          }
5471          break;
5472          /* Note:
5473             if (0x8000_0000_0000_0000 / -1) or (x / 0)
5474             => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
5475             => But _no_ exception raised. */
5476 
5477       case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420)
5478          DIP("divdu%s%s r%u,r%u,r%u\n",
5479              flag_OE ? "o" : "", flag_rC ? ".":"",
5480              rD_addr, rA_addr, rB_addr);
5481          assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) );
5482          if (flag_OE) {
5483             set_XER_OV_OV32_SO( ty, PPCG_FLAG_OP_DIVWU,
5484                                 mkexpr(rD), mkexpr(rA), mkexpr(rB) );
5485          }
5486          break;
5487          /* Note: ditto comment divd, for (x / 0) */
5488 
5489       case 0x18B: // divweu (Divide Word Extended Unsigned)
5490       {
5491         /*
5492          *  If (RA) >= (RB), or if an attempt is made to perform the division
5493          *         <anything> / 0
5494          * then the contents of register RD are undefined as are (if Rc=1) the contents of
5495          * the LT, GT, and EQ bits of CR Field 0. In these cases, if OE=1 then OV is set
5496          * to 1.
5497          */
5498          IRTemp res = newTemp(Ity_I32);
5499          IRExpr * dividend, * divisor;
5500          DIP("divweu%s%s r%u,r%u,r%u\n",
5501              flag_OE ? "o" : "", flag_rC ? ".":"",
5502                                          rD_addr, rA_addr, rB_addr);
5503          if (mode64) {
5504             dividend = unop( Iop_64to32, mkexpr( rA ) );
5505             divisor = unop( Iop_64to32, mkexpr( rB ) );
5506             assign( res, binop( Iop_DivU32E, dividend, divisor ) );
5507             assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
5508          } else {
5509             dividend = mkexpr( rA );
5510             divisor =  mkexpr( rB );
5511             assign( res, binop( Iop_DivU32E, dividend, divisor ) );
5512             assign( rD, mkexpr( res) );
5513          }
5514 
5515          if (flag_OE) {
5516             set_XER_OV_OV32_32( PPCG_FLAG_OP_DIVWEU,
5517                                 mkexpr(res), dividend, divisor );
5518             update_SO( );
5519          }
5520          break;
5521       }
5522 
5523       case 0x1AB: // divwe (Divide Word Extended)
5524       {
5525          /*
5526           * If the quotient cannot be represented in 32 bits, or if an
5527           * attempt is made to perform the division
5528           *      <anything> / 0
5529           * then the contents of register RD are undefined as are (if
5530           * Rc=1) the contents of the LT, GT, and EQ bits of CR
5531           * Field 0. In these cases, if OE=1 then OV is set to 1.
5532           */
5533 
5534          IRTemp res = newTemp(Ity_I32);
5535          IRExpr * dividend, * divisor;
5536          DIP("divwe%s%s r%u,r%u,r%u\n",
5537              flag_OE ? "o" : "", flag_rC ? ".":"",
5538                                          rD_addr, rA_addr, rB_addr);
5539          if (mode64) {
5540             dividend = unop( Iop_64to32, mkexpr( rA ) );
5541             divisor = unop( Iop_64to32, mkexpr( rB ) );
5542             assign( res, binop( Iop_DivS32E, dividend, divisor ) );
5543             assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
5544          } else {
5545             dividend = mkexpr( rA );
5546             divisor =  mkexpr( rB );
5547             assign( res, binop( Iop_DivS32E, dividend, divisor ) );
5548             assign( rD, mkexpr( res) );
5549          }
5550 
5551          if (flag_OE) {
5552             set_XER_OV_OV32_32( PPCG_FLAG_OP_DIVWE,
5553                                 mkexpr(res), dividend, divisor );
5554             update_SO( );
5555          }
5556          break;
5557       }
5558 
5559 
5560       case 0x1A9: // divde (Divide Doubleword Extended)
5561         /*
5562          * If the quotient cannot be represented in 64 bits, or if an
5563          * attempt is made to perform the division
5564          *      <anything> / 0
5565          * then the contents of register RD are undefined as are (if
5566          * Rc=1) the contents of the LT, GT, and EQ bits of CR
5567          * Field 0. In these cases, if OE=1 then OV is set to 1.
5568          */
5569          DIP("divde%s%s r%u,r%u,r%u\n",
5570              flag_OE ? "o" : "", flag_rC ? ".":"",
5571              rD_addr, rA_addr, rB_addr);
5572          assign( rD, binop(Iop_DivS64E, mkexpr(rA), mkexpr(rB)) );
5573          if (flag_OE) {
5574             set_XER_OV_64( PPCG_FLAG_OP_DIVDE, mkexpr( rD ),
5575                            mkexpr( rA ), mkexpr( rB ) );
5576            copy_OV_to_OV32();
5577            update_SO();
5578          }
5579          break;
5580 
5581       case 0x189: //  divdeuo (Divide Doubleword Extended Unsigned)
5582         // Same CR and OV rules as given for divweu above
5583         DIP("divdeu%s%s r%u,r%u,r%u\n",
5584             flag_OE ? "o" : "", flag_rC ? ".":"",
5585             rD_addr, rA_addr, rB_addr);
5586         assign( rD, binop(Iop_DivU64E, mkexpr(rA), mkexpr(rB)) );
5587         if (flag_OE) {
5588            set_XER_OV_64( PPCG_FLAG_OP_DIVDEU, mkexpr( rD ),
5589                           mkexpr( rA ), mkexpr( rB ) );
5590            copy_OV_to_OV32();
5591            update_SO();
5592         }
5593         break;
5594 
5595       default:
5596          vex_printf("dis_int_arith(ppc)(opc2)\n");
5597          return False;
5598       }
5599       break;
5600 
5601    default:
5602       vex_printf("dis_int_arith(ppc)(opc1)\n");
5603       return False;
5604    }
5605 
5606    putIReg( rD_addr, mkexpr(rD) );
5607 
5608    if (do_rc && flag_rC) {
5609       set_CR0( mkexpr(rD) );
5610    }
5611    return True;
5612 }
5613 
dis_modulo_int(UInt theInstr)5614 static Bool dis_modulo_int ( UInt theInstr )
5615 {
5616    /* X-Form */
5617    UChar opc1    = ifieldOPC( theInstr );
5618    UInt  opc2    = ifieldOPClo10( theInstr );
5619    UChar rA_addr = ifieldRegA( theInstr );
5620    UChar rB_addr = ifieldRegB( theInstr );
5621    UChar rD_addr = ifieldRegDS( theInstr );
5622    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
5623    IRTemp rD     = newTemp( ty );
5624 
5625    switch (opc1) {
5626    /* X-Form */
5627    case 0x1F:
5628       switch (opc2) {
5629       case 0x109: // modud  Modulo Unsigned Double Word
5630          {
5631             IRTemp rA = newTemp( Ity_I64 );
5632             IRTemp rB = newTemp( Ity_I64 );
5633             IRTemp quotient = newTemp( Ity_I64 );
5634             IRTemp quotientTimesDivisor = newTemp( Ity_I64 );
5635             IRTemp remainder = newTemp( Ity_I64 );
5636             IRTemp rB_0   = newTemp( Ity_I64 );    /* all 1's if rB = 0 */
5637 
5638             DIP("modud r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5639 
5640             assign( rA, getIReg( rA_addr ) );
5641             assign( rB, getIReg( rB_addr ) );
5642 
5643             assign( quotient,
5644                     binop( Iop_DivU64, mkexpr( rA ), mkexpr( rB ) ) );
5645 
5646             assign( quotientTimesDivisor,
5647                     binop( Iop_Mul64,
5648                            mkexpr( quotient ),
5649                            mkexpr( rB ) ) );
5650 
5651             assign( remainder,
5652                     binop( Iop_Sub64,
5653                            mkexpr( rA ),
5654                            mkexpr( quotientTimesDivisor ) ) );
5655 
5656             /* Need to match the HW for these special cases
5657              * rB = 0         result all zeros
5658              */
5659             assign( rB_0, unop( Iop_1Sto64,
5660                                 binop( Iop_CmpEQ64,
5661                                        mkexpr( rB ),
5662                                        mkU64( 0x0 ) ) ) );
5663 
5664             assign (rD, binop( Iop_And64,
5665                                unop( Iop_Not64, mkexpr( rB_0 ) ),
5666                                mkexpr( remainder ) ) );
5667             break;
5668          }
5669 
5670       case 0x10B: // moduw  Modulo Unsigned Word
5671          {
5672             IRTemp quotient = newTemp( Ity_I32 );
5673             IRTemp quotientTimesDivisor = newTemp( Ity_I32 );
5674             IRTemp remainder = newTemp( Ity_I32 );
5675 
5676             IRTemp rA     = newTemp( Ity_I32 );
5677             IRTemp rB     = newTemp( Ity_I32 );
5678             IRTemp rB_0   = newTemp( Ity_I32 );     /* all 1's if rB = 0 */
5679 
5680             DIP("moduw r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5681 
5682             if ( ty == Ity_I64 ) {
5683                /* rA and rB are 32 bit values in bits 32:63 of the
5684                 * 64-bit register.
5685                 */
5686                assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) );
5687                assign( rB, unop( Iop_64to32, getIReg( rB_addr ) ) );
5688 
5689             } else {
5690                assign( rA, getIReg( rA_addr ) );
5691                assign( rB, getIReg( rB_addr ) );
5692             }
5693 
5694             assign( quotient,
5695                     binop( Iop_DivU32, mkexpr( rA ), mkexpr( rB ) ) );
5696 
5697             assign( quotientTimesDivisor,
5698                     unop( Iop_64to32,
5699                           binop( Iop_MullU32,
5700                                  mkexpr( quotient ),
5701                                  mkexpr( rB ) ) ) );
5702 
5703             assign( remainder,
5704                     binop( Iop_Sub32,
5705                            mkexpr( rA ),
5706                            mkexpr( quotientTimesDivisor ) ) );
5707 
5708             /* Need to match the HW for these special cases
5709              * rB = 0         result all zeros
5710              */
5711             assign( rB_0, unop( Iop_1Sto32,
5712                                 binop( Iop_CmpEQ32,
5713                                        mkexpr( rB ),
5714                                        mkU32( 0x0 ) ) ) );
5715 
5716             assign (rD, binop( Iop_32HLto64,
5717                                mkU32( 0 ),
5718                                binop( Iop_And32,
5719                                       unop( Iop_Not32, mkexpr( rB_0 ) ),
5720                                       mkexpr( remainder ) ) ) );
5721             break;
5722          }
5723 
5724       case 0x21A: // cnttzw, cnttzw.   Count Trailing Zero Word
5725          {
5726             /* Note cnttzw RA, RS  - RA is dest, RS is source.  But the
5727              * order of the operands in theInst is opc1 RS RA opc2 which has
5728              * the operand fields backwards to what the standard order.
5729              */
5730             UChar rA_address = ifieldRegA(theInstr);
5731             UChar rS_address = ifieldRegDS(theInstr);
5732             IRTemp rA     = newTemp(Ity_I64);
5733             IRTemp rS     = newTemp(Ity_I64);
5734             UChar flag_rC = ifieldBIT0(theInstr);
5735             IRTemp result = newTemp(Ity_I32);
5736 
5737             DIP("cnttzw%s r%u,r%u\n",  flag_rC ? "." : "",
5738                 rA_address, rS_address);
5739 
5740             assign( rS, getIReg( rS_address ) );
5741             assign( result, unop( Iop_CtzNat32,
5742                                   unop( Iop_64to32, mkexpr( rS ) ) ) );
5743             assign( rA, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( result ) ) );
5744 
5745             if ( flag_rC )
5746                set_CR0( mkexpr( rA ) );
5747 
5748             putIReg( rA_address, mkexpr( rA ) );
5749 
5750             return True;  /* Return here since this inst is not consistent
5751                            * with the other instructions
5752                            */
5753          }
5754          break;
5755 
5756       case 0x23A: // cnttzd, cnttzd.   Count Trailing Zero Double word
5757          {
5758             /* Note cnttzd RA, RS  - RA is dest, RS is source.  But the
5759              * order of the operands in theInst is opc1 RS RA opc2 which has
5760              * the operand order listed backwards to what is standard.
5761              */
5762             UChar rA_address = ifieldRegA(theInstr);
5763             UChar rS_address = ifieldRegDS(theInstr);
5764             IRTemp rA     = newTemp(Ity_I64);
5765             IRTemp rS     = newTemp(Ity_I64);
5766             UChar flag_rC = ifieldBIT0(theInstr);
5767 
5768             DIP("cnttzd%s r%u,r%u\n",  flag_rC ? "." : "",
5769                 rA_address, rS_address);
5770 
5771             assign( rS, getIReg( rS_address ) );
5772             assign( rA, unop( Iop_CtzNat64, mkexpr( rS ) ) );
5773 
5774             if ( flag_rC == 1 )
5775                set_CR0( mkexpr( rA ) );
5776 
5777             putIReg( rA_address, mkexpr( rA ) );
5778 
5779             return True;  /* Return here since this inst is not consistent
5780                            * with the other instructions
5781                            */
5782          }
5783          break;
5784 
5785       case 0x309: // modsd  Modulo Signed Double Word
5786          {
5787             IRTemp rA     = newTemp( Ity_I64 );
5788             IRTemp rB     = newTemp( Ity_I64 );
5789             IRTemp rA2_63 = newTemp( Ity_I64 );    /* all 1's if rA != -2^63 */
5790             IRTemp rB_0   = newTemp( Ity_I1 );     /* 1 if rB = 0 */
5791             IRTemp rB_1   = newTemp( Ity_I1 );     /* 1 if rB = -1 */
5792             IRTemp rA_1   = newTemp( Ity_I1 );     /* 1 if rA = -1 */
5793             IRTemp resultis0   = newTemp( Ity_I64 );
5794             IRTemp resultisF   = newTemp( Ity_I64 );
5795             IRTemp quotient = newTemp( Ity_I64 );
5796             IRTemp quotientTimesDivisor = newTemp( Ity_I64 );
5797             IRTemp remainder = newTemp( Ity_I64 );
5798             IRTemp tmp  = newTemp( Ity_I64 );
5799 
5800             DIP("modsd r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5801 
5802             assign( rA, getIReg( rA_addr ) );
5803             assign( rB, getIReg( rB_addr ) );
5804 
5805             assign( rA2_63, unop ( Iop_1Sto64,
5806                                    binop( Iop_CmpNE64,
5807                                           mkexpr( rA ),
5808                                           mkU64( 0x8000000000000000 ) ) ) );
5809             assign( rB_0, binop( Iop_CmpEQ64,
5810                                  mkexpr( rB ),
5811                                  mkU64( 0x0 ) ) );
5812 
5813             assign( rB_1, binop( Iop_CmpEQ64,
5814                                  mkexpr( rB ),
5815                                  mkU64( 0xFFFFFFFFFFFFFFFF ) ) );
5816 
5817             assign( rA_1, binop( Iop_CmpEQ64,
5818                                  mkexpr( rA ),
5819                                  mkU64( 0xFFFFFFFFFFFFFFFF ) ) );
5820 
5821             /* Need to match the HW for these special cases
5822              * rA = -2^31 and rB = -1              result all zeros
5823              * rA =  -1 and rB = -1                result all zeros
5824              * rA =  -1 and (rB != -1 AND rB != 0) result all 1's
5825              */
5826             assign( resultis0,
5827                     binop( Iop_Or64,
5828                            mkexpr( rA2_63 ),
5829                            unop ( Iop_1Sto64, mkexpr( rB_1 ) ) ) );
5830             assign( resultisF,
5831                     binop( Iop_And64,
5832                            unop( Iop_1Sto64, mkexpr( rA_1 ) ),
5833                            binop( Iop_And64,
5834                                   unop( Iop_Not64,
5835                                         unop( Iop_1Sto64, mkexpr( rB_0 ) ) ),
5836                                   unop( Iop_Not64,
5837                                         unop( Iop_1Sto64, mkexpr( rB_1 ) ) )
5838                                   ) ) );
5839 
5840             /* The following remainder computation works as long as
5841              * rA != -2^63 and rB != -1.
5842              */
5843             assign( quotient,
5844                     binop( Iop_DivS64, mkexpr( rA ), mkexpr( rB ) ) );
5845 
5846             assign( quotientTimesDivisor,
5847                     binop( Iop_Mul64,
5848                            mkexpr( quotient ),
5849                            mkexpr( rB ) ) );
5850 
5851             assign( remainder,
5852                     binop( Iop_Sub64,
5853                            mkexpr( rA ),
5854                            mkexpr( quotientTimesDivisor ) ) );
5855 
5856             assign( tmp, binop( Iop_And64,
5857                                 mkexpr( remainder ),
5858                                 unop( Iop_Not64,
5859                                       mkexpr( resultis0 ) ) ) );
5860 
5861             assign( rD, binop( Iop_Or64,
5862                                binop( Iop_And64,
5863                                       unop (Iop_Not64,
5864                                             mkexpr( resultisF ) ),
5865                                       mkexpr( tmp ) ),
5866                                mkexpr( resultisF ) ) );
5867             break;
5868          }
5869       case 0x30B: // modsw  Modulo Signed Word
5870          {
5871             IRTemp rA     = newTemp( Ity_I32 );
5872             IRTemp rB     = newTemp( Ity_I32 );
5873             IRTemp rA2_32 = newTemp( Ity_I32 );    /* all 1's if rA = -2^32 */
5874             IRTemp rB_0   = newTemp( Ity_I1 );     /* 1 if rB = 0 */
5875             IRTemp rB_1   = newTemp( Ity_I1 );     /* 1 if rB = -1 */
5876             IRTemp rA_1   = newTemp( Ity_I1 );     /* 1 if rA = -1 */
5877             IRTemp resultis0   = newTemp( Ity_I32 );
5878             IRTemp resultisF   = newTemp( Ity_I64 );
5879             IRTemp quotient = newTemp( Ity_I32 );
5880             IRTemp quotientTimesDivisor = newTemp( Ity_I32 );
5881             IRTemp remainder = newTemp( Ity_I32 );
5882             IRTemp tmp  = newTemp( Ity_I64 );
5883 
5884             DIP("modsw r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5885 
5886             if ( ty == Ity_I64 ) {
5887                /* rA and rB are 32 bit values in bits 32:63 of the
5888                 * 64-bit register.
5889                 */
5890                assign( rA, unop(Iop_64to32, getIReg(rA_addr) ) );
5891                assign( rB, unop(Iop_64to32, getIReg(rB_addr) ) );
5892 
5893             } else {
5894                assign( rA, getIReg(rA_addr) );
5895                assign( rB, getIReg(rB_addr) );
5896             }
5897 
5898             assign( rA2_32, unop( Iop_1Sto32,
5899                                   binop( Iop_CmpEQ32,
5900                                          mkexpr( rA ),
5901                                          mkU32( 0x80000000 ) ) ) );
5902             /* If the divisor is zero, then the result is undefined.
5903              * However, we will make the result be zero to match what
5904              * the hardware does.
5905              */
5906             assign( rB_0, binop( Iop_CmpEQ32,
5907                                  mkexpr( rB ),
5908                                  mkU32( 0x0 ) ) );
5909 
5910             assign( rB_1, binop( Iop_CmpEQ32,
5911                                  mkexpr( rB ),
5912                                  mkU32( 0xFFFFFFFF ) ) );
5913 
5914             assign( rA_1, binop( Iop_CmpEQ32,
5915                                  mkexpr( rA ),
5916                                  mkU32( 0xFFFFFFFF ) ) );
5917 
5918             /* Need to match the HW for these special cases
5919              * rA = -2^31 and rB = -1              result all zeros
5920              * rA =  -1 and rB = -1                result all zeros
5921              * rA =  -1 and (rB != -1 AND rB != 0) result all 1's
5922              */
5923             assign( resultis0,
5924                     binop( Iop_Or32,
5925                            unop( Iop_Not32,
5926                                  binop( Iop_And32,
5927                                         mkexpr( rA2_32 ),
5928                                         unop( Iop_1Sto32,
5929                                               mkexpr( rB_1 ) ) ) ),
5930                            binop( Iop_And32,
5931                                   unop( Iop_1Sto32, mkexpr( rA_1 ) ),
5932                                   unop( Iop_1Sto32, mkexpr( rB_1 ) ) ) ) );
5933             assign( resultisF,
5934                     binop( Iop_And64,
5935                            unop( Iop_1Sto64, mkexpr( rA_1 ) ),
5936                            binop( Iop_And64,
5937                                   unop( Iop_Not64,
5938                                         unop( Iop_1Sto64, mkexpr( rB_0 ) ) ),
5939                                   unop( Iop_Not64,
5940                                         unop( Iop_1Sto64, mkexpr( rB_1 ) ) )
5941                                   ) ) );
5942 
5943             /* The following remainder computation works as long as
5944              * rA != -2^31 and rB != -1.
5945              */
5946             assign( quotient,
5947                     binop( Iop_DivS32, mkexpr( rA ), mkexpr( rB ) ) );
5948 
5949             assign( quotientTimesDivisor,
5950                     unop( Iop_64to32,
5951                           binop( Iop_MullS32,
5952                                  mkexpr( quotient ),
5953                                  mkexpr( rB ) ) ) );
5954 
5955             assign( remainder,
5956                     binop( Iop_Sub32,
5957                            mkexpr( rA ),
5958                            mkexpr( quotientTimesDivisor ) ) );
5959 
5960             assign( tmp, binop( Iop_32HLto64,
5961                                 mkU32( 0 ),
5962                                 binop( Iop_And32,
5963                                        mkexpr( remainder ),
5964                                        unop( Iop_Not32,
5965                                              mkexpr( resultis0 ) ) ) ) );
5966 
5967             assign( rD, binop( Iop_Or64,
5968                                binop( Iop_And64,
5969                                       unop ( Iop_Not64,
5970                                              mkexpr( resultisF ) ),
5971                                       mkexpr( tmp ) ),
5972                                mkexpr( resultisF ) ) );
5973             break;
5974          }
5975 
5976       default:
5977          vex_printf("dis_modulo_int(ppc)(opc2)\n");
5978          return False;
5979       }
5980       break;
5981 
5982    default:
5983       vex_printf("dis_modulo_int(ppc)(opc1)\n");
5984       return False;
5985    }
5986 
5987    putIReg( rD_addr, mkexpr( rD ) );
5988 
5989    return True;
5990 }
5991 
5992 
5993 /*
5994   Byte Compare Instructions
5995 */
dis_byte_cmp(UInt theInstr)5996 static Bool dis_byte_cmp ( UInt theInstr )
5997 {
5998    /* X-Form */
5999    UChar opc1 = ifieldOPC(theInstr);
6000    UInt  opc2 = ifieldOPClo10(theInstr);
6001    UChar rA_addr = ifieldRegA(theInstr);
6002    UChar rB_addr = ifieldRegB(theInstr);
6003    IRTemp rA     = newTemp(Ity_I64);
6004    IRTemp rB     = newTemp(Ity_I64);
6005    UChar L    = toUChar( IFIELD( theInstr, 21, 1 ) );
6006    UChar BF   = toUChar( IFIELD( theInstr, 23, 3 ) );
6007 
6008    assign( rA, getIReg(rA_addr) );
6009    assign( rB, getIReg(rB_addr) );
6010 
6011    if (opc1 != 0x1F) {
6012       vex_printf("dis_byte_cmp(ppc)(opc1)\n");
6013       return False;
6014    }
6015 
6016    switch (opc2) {
6017    case 0xc0: // cmprb (Compare Ranged Byte)
6018       {
6019          IRExpr *value;
6020          IRExpr *hi_1, *lo_1, *hi_2, *lo_2;
6021          IRExpr *inrange_1, *inrange_2;
6022 
6023          DIP("cmprb %u,%u,r%u,r%u\n", BF, L, rA_addr, rB_addr);
6024 
6025          hi_1 = binop( Iop_Shr64,
6026                        binop( Iop_And64,
6027                               mkexpr( rB ),
6028                               mkU64( 0xFF000000 ) ),
6029                        mkU8( 24 ) );
6030          lo_1 = binop( Iop_Shr64,
6031                        binop( Iop_And64,
6032                               mkexpr( rB ),
6033                               mkU64( 0xFF0000 ) ) ,
6034                        mkU8( 16 ) );
6035          hi_2 = binop( Iop_Shr64,
6036                        binop( Iop_And64,
6037                               mkexpr( rB ),
6038                               mkU64( 0xFF00 ) ),
6039                        mkU8( 8 ) );
6040          lo_2 = binop( Iop_And64,
6041                        mkexpr( rB ),
6042                        mkU64( 0xFF ) );
6043          value = binop( Iop_And64,
6044                         mkexpr( rA ),
6045                         mkU64( 0xFF ) );
6046 
6047          inrange_1 = mkAND1( binop( Iop_CmpLE64U, value, hi_1 ),
6048                              mkNOT1( binop( Iop_CmpLT64U, value, lo_1 ) ) );
6049          inrange_2 = mkAND1( binop( Iop_CmpLE64U, value, hi_2 ),
6050                              mkNOT1( binop( Iop_CmpLT64U, value, lo_2 ) ) );
6051 
6052          putGST_field( PPC_GST_CR,
6053                        binop( Iop_Shl32,
6054                               binop( Iop_Or32,
6055                                      unop( Iop_1Uto32, inrange_2 ),
6056                                      binop( Iop_And32,
6057                                             mkU32 ( L ),
6058                                             unop( Iop_1Uto32, inrange_1 ) ) ),
6059                               mkU8( 2 ) ),
6060                        BF );
6061       }
6062       break;
6063 
6064    case 0xE0: // cmpeqb (Compare Equal Byte)
6065       {
6066          Int i;
6067          IRTemp tmp[9];
6068          IRExpr *value;
6069 
6070          DIP("cmpeqb %u,r%u,r%u\n", BF, rA_addr, rB_addr);
6071 
6072          value = binop( Iop_And64,
6073                         mkexpr( rA ),
6074                         mkU64( 0xFF ) );
6075 
6076          tmp[0] = newTemp(Ity_I32);
6077          assign( tmp[0], mkU32( 0 ) );
6078 
6079          for(i = 0; i < 8; i++) {
6080             tmp[i+1] = newTemp(Ity_I32);
6081             assign( tmp[i+1], binop( Iop_Or32,
6082                                      unop( Iop_1Uto32,
6083                                            binop( Iop_CmpEQ64,
6084                                                   value,
6085                                                   binop( Iop_And64,
6086                                                          binop( Iop_Shr64,
6087                                                                 mkexpr( rB ),
6088                                                                 mkU8( i*8 ) ),
6089                                                          mkU64( 0xFF ) ) ) ),
6090                                      mkexpr( tmp[i] ) ) );
6091          }
6092 
6093          putGST_field( PPC_GST_CR,
6094                        binop( Iop_Shl32,
6095                               unop( Iop_1Uto32,
6096                                     mkNOT1( binop( Iop_CmpEQ32,
6097                                                    mkexpr( tmp[8] ),
6098                                                    mkU32( 0 ) ) ) ),
6099                               mkU8( 2 ) ),
6100                        BF );
6101       }
6102       break;
6103 
6104    default:
6105       vex_printf("dis_byte_cmp(ppc)(opc2)\n");
6106       return False;
6107    }
6108    return True;
6109 }
6110 
6111 /*
6112  * Integer Miscellaneous instructions
6113  */
dis_int_misc(UInt theInstr)6114 static Bool dis_int_misc ( UInt theInstr )
6115 {
6116    Int wc = IFIELD(theInstr, 21, 2);
6117    UChar opc1 = ifieldOPC(theInstr);
6118    UInt  opc2 = ifieldOPClo10(theInstr);
6119 
6120    if ( opc1 != 0x1F ) {
6121       vex_printf("dis_modulo_int(ppc)(opc1)\n");
6122       return False;
6123    }
6124 
6125    switch (opc2) {
6126    case 0x01E: // wait, (X-from)
6127       DIP("wait %u\n", wc);
6128 
6129       /* The wait instruction causes instruction fetching and execution
6130        * to be suspended.  Instruction fetching and execution are resumed
6131        * when the events specified by the WC field occur.
6132        *
6133        *    0b00   Resume instruction fetching and execution when an
6134        *           exception or an event-based branch exception occurs,
6135        *           or a resume signal from the platform is recieved.
6136        *
6137        *    0b01   Reserved.
6138        *
6139        *  For our purposes, we will just assume the contition is always
6140        * immediately satisfied.
6141        */
6142       break;
6143    default:
6144       vex_printf("dis_int_misc(ppc)(opc2)\n");
6145       return False;
6146 }
6147 
6148    return True;
6149 }
6150 
6151 /*
6152   Integer Compare Instructions
6153 */
dis_int_cmp(UInt theInstr)6154 static Bool dis_int_cmp ( UInt theInstr )
6155 {
6156    /* D-Form, X-Form */
6157    UChar opc1    = ifieldOPC(theInstr);
6158    UChar crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
6159    UChar b22     = toUChar( IFIELD( theInstr, 22, 1 ) );
6160    UChar flag_L  = toUChar( IFIELD( theInstr, 21, 1 ) );
6161    UChar rA_addr = ifieldRegA(theInstr);
6162    UInt  uimm16  = ifieldUIMM16(theInstr);
6163    UChar rB_addr = ifieldRegB(theInstr);
6164    UInt  opc2    = ifieldOPClo10(theInstr);
6165    UChar b0      = ifieldBIT0(theInstr);
6166 
6167    IRType ty = mode64 ? Ity_I64 : Ity_I32;
6168    IRExpr *a = getIReg(rA_addr);
6169    IRExpr *b;
6170 
6171    if (!mode64 && flag_L==1) {  // L==1 invalid for 32 bit.
6172       vex_printf("dis_int_cmp(ppc)(flag_L)\n");
6173       return False;
6174    }
6175 
6176    if (( b22 != 0 ) && ( opc2 != 0x080 ) ) {   // setb case exception
6177       vex_printf("dis_int_cmp(ppc)(b22)\n");
6178       return False;
6179    }
6180 
6181    switch (opc1) {
6182    case 0x0B: // cmpi (Compare Immediate, PPC32 p368)
6183       DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr,
6184           (Int)extend_s_16to32(uimm16));
6185       b = mkSzExtendS16( ty, uimm16 );
6186       if (flag_L == 1) {
6187          putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
6188       } else {
6189          a = mkNarrowTo32( ty, a );
6190          b = mkNarrowTo32( ty, b );
6191          putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b)));
6192       }
6193       putCR0( crfD, getXER_SO() );
6194       break;
6195 
6196    case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370)
6197       DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16);
6198       b = mkSzImm( ty, uimm16 );
6199       if (flag_L == 1) {
6200          putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
6201       } else {
6202          a = mkNarrowTo32( ty, a );
6203          b = mkNarrowTo32( ty, b );
6204          putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
6205       }
6206       putCR0( crfD, getXER_SO() );
6207       break;
6208 
6209    /* X Form */
6210    case 0x1F:
6211       if (b0 != 0) {
6212          vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n");
6213          return False;
6214       }
6215       b = getIReg(rB_addr);
6216 
6217       switch (opc2) {
6218       case 0x000: // cmp (Compare, PPC32 p367)
6219          DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
6220          /* Comparing a reg with itself produces a result which
6221             doesn't depend on the contents of the reg.  Therefore
6222             remove the false dependency, which has been known to cause
6223             memcheck to produce false errors. */
6224          if (rA_addr == rB_addr)
6225             a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
6226                     ? mkU64(0)  : mkU32(0);
6227          if (flag_L == 1) {
6228             putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
6229          } else {
6230             a = mkNarrowTo32( ty, a );
6231             b = mkNarrowTo32( ty, b );
6232             putCR321(crfD, unop(Iop_32to8,binop(Iop_CmpORD32S, a, b)));
6233          }
6234          putCR0( crfD, getXER_SO() );
6235          break;
6236 
6237       case 0x020: // cmpl (Compare Logical, PPC32 p369)
6238          DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
6239          /* Comparing a reg with itself produces a result which
6240             doesn't depend on the contents of the reg.  Therefore
6241             remove the false dependency, which has been known to cause
6242             memcheck to produce false errors. */
6243          if (rA_addr == rB_addr)
6244             a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
6245                     ? mkU64(0)  : mkU32(0);
6246          if (flag_L == 1) {
6247             putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
6248          } else {
6249             a = mkNarrowTo32( ty, a );
6250             b = mkNarrowTo32( ty, b );
6251             putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
6252          }
6253          putCR0( crfD, getXER_SO() );
6254          break;
6255 
6256       case 0x080: // setb (Set Boolean)
6257          {
6258             UChar rT_addr = ifieldRegDS(theInstr);
6259             Int bfa = IFIELD(theInstr, 18, 3);
6260             IRTemp cr = newTemp(Ity_I32);
6261             IRTemp cr0 = newTemp(Ity_I32);
6262             IRTemp cr1 = newTemp(Ity_I32);
6263             IRTemp result = newTemp(Ity_I64);
6264 
6265             DIP("setb r%u,%d\n", rT_addr, bfa);
6266 
6267             /* Fetch the entire condition code value */
6268             assign( cr, getGST( PPC_GST_CR ) );
6269 
6270             /* Get bit zero (IBM numbering) of the CR field specified
6271              * by bfa.
6272              */
6273             assign( cr0, binop( Iop_And32,
6274                                 binop( Iop_Shr32,
6275                                        mkexpr( cr ),
6276                                        mkU8( (7-bfa)*4 ) ),
6277                                 mkU32( 0x8 ) ) );
6278             assign( cr1, binop( Iop_And32,
6279                                 binop( Iop_Shr32,
6280                                        mkexpr( cr ),
6281                                        mkU8( (7-bfa)*4 ) ),
6282                                 mkU32( 0x4 ) ) );
6283             assign( result, binop( Iop_Or64,
6284                                    unop( Iop_1Sto64,
6285                                        binop( Iop_CmpEQ32,
6286                                               mkexpr( cr0 ),
6287                                               mkU32( 0x8 ) ) ),
6288                                    binop( Iop_32HLto64,
6289                                           mkU32( 0 ),
6290                                           unop( Iop_1Uto32,
6291                                                 binop( Iop_CmpEQ32,
6292                                                        mkexpr( cr1 ),
6293                                                        mkU32( 0x4 ) ) ) ) ) );
6294             if ( ty == Ity_I64 )
6295                putIReg( rT_addr, mkexpr( result ) );
6296             else
6297                putIReg( rT_addr, unop( Iop_64to32, mkexpr(result ) ) );
6298          }
6299          break;
6300       default:
6301          vex_printf("dis_int_cmp(ppc)(opc2)\n");
6302          return False;
6303       }
6304       break;
6305 
6306    default:
6307       vex_printf("dis_int_cmp(ppc)(opc1)\n");
6308       return False;
6309    }
6310 
6311    return True;
6312 }
6313 
6314 
6315 /*
6316   Integer Logical Instructions
6317 */
dis_int_logic(UInt theInstr)6318 static Bool dis_int_logic ( UInt theInstr )
6319 {
6320    /* D-Form, X-Form */
6321    UChar opc1    = ifieldOPC(theInstr);
6322    UChar rS_addr = ifieldRegDS(theInstr);
6323    UChar rA_addr = ifieldRegA(theInstr);
6324    UInt  uimm16  = ifieldUIMM16(theInstr);
6325    UChar rB_addr = ifieldRegB(theInstr);
6326    UInt  opc2    = ifieldOPClo10(theInstr);
6327    UChar flag_rC = ifieldBIT0(theInstr);
6328 
6329    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
6330    IRTemp rS     = newTemp(ty);
6331    IRTemp rA     = newTemp(ty);
6332    IRTemp rB     = newTemp(ty);
6333    Bool do_rc    = False;
6334 
6335    assign( rS, getIReg(rS_addr) );
6336    assign( rB, getIReg(rB_addr) );
6337 
6338    switch (opc1) {
6339    case 0x1C: // andi. (AND Immediate, PPC32 p358)
6340       DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
6341       assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
6342                          mkSzImm(ty, uimm16)) );
6343       do_rc = True;  // Always record to CR
6344       flag_rC = 1;
6345       break;
6346 
6347    case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359)
6348       DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
6349       assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
6350                          mkSzImm(ty, uimm16 << 16)) );
6351       do_rc = True;  // Always record to CR
6352       flag_rC = 1;
6353       break;
6354 
6355    case 0x18: // ori (OR Immediate, PPC32 p497)
6356       DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
6357       assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
6358                          mkSzImm(ty, uimm16)) );
6359       break;
6360 
6361    case 0x19: // oris (OR Immediate Shifted, PPC32 p498)
6362       DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
6363       assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
6364                          mkSzImm(ty, uimm16 << 16)) );
6365       break;
6366 
6367    case 0x1A: // xori (XOR Immediate, PPC32 p550)
6368       DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
6369       assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
6370                          mkSzImm(ty, uimm16)) );
6371       break;
6372 
6373    case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551)
6374       DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
6375       assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
6376                          mkSzImm(ty, uimm16 << 16)) );
6377       break;
6378 
6379    /* X Form */
6380    case 0x1F:
6381 
6382       opc2 = IFIELD( theInstr, 2, 9 );
6383 
6384       switch ( opc2 ) {
6385       case 0x1BD: // extswsli (Extend Sign Word shift left)
6386          {
6387             /* sh[5] is in bit 1, sh[0:4] is in bits [14:10] of theInstr */
6388             UChar sh = IFIELD( theInstr, 11, 5 ) | (IFIELD(theInstr, 1, 1) << 5);
6389             IRTemp temp = newTemp( ty );
6390 
6391             DIP("extswsli%s r%u,r%u,%u\n", flag_rC ? ".":"",
6392                 rA_addr, rS_addr, sh);
6393 
6394             assign( temp, unop( Iop_32Sto64,
6395                                 unop( Iop_64to32, mkexpr( rS ) ) ) );
6396             assign( rA, binop( Iop_Shl64, mkexpr( temp ), mkU8( sh ) ) );
6397             putIReg( rA_addr, mkexpr( rA ) );
6398 
6399             if ( flag_rC ) {
6400                set_CR0( mkexpr( rA ) );
6401             }
6402             return True;
6403          }
6404       default:
6405          break;  // drop to next opc2 check
6406       }
6407 
6408       do_rc = True; // All below record to CR, except for where we return at case end.
6409 
6410       opc2 = ifieldOPClo10( theInstr );
6411 
6412       switch (opc2) {
6413       case 0x01C: // and (AND, PPC32 p356)
6414          DIP("and%s r%u,r%u,r%u\n",
6415              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6416          assign(rA, binop( mkSzOp(ty, Iop_And8),
6417                            mkexpr(rS), mkexpr(rB)));
6418          break;
6419 
6420       case 0x03C: // andc (AND with Complement, PPC32 p357)
6421          DIP("andc%s r%u,r%u,r%u\n",
6422              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6423          assign(rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
6424                            unop( mkSzOp(ty, Iop_Not8),
6425                                  mkexpr(rB))));
6426          break;
6427 
6428       case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371)
6429          if (rB_addr!=0) {
6430             vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n");
6431             return False;
6432          }
6433          DIP("cntlzw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr);
6434 
6435          // mode64: count in low word only
6436          IRExpr* lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS);
6437          IRExpr* res32 = unop(Iop_ClzNat32, lo32);
6438          assign(rA, mode64 ? unop(Iop_32Uto64, res32) : res32);
6439          break;
6440       }
6441 
6442       case 0x11C: // eqv (Equivalent, PPC32 p396)
6443          DIP("eqv%s r%u,r%u,r%u\n",
6444              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6445          assign( rA, unop( mkSzOp(ty, Iop_Not8),
6446                            binop( mkSzOp(ty, Iop_Xor8),
6447                                   mkexpr(rS), mkexpr(rB))) );
6448          break;
6449 
6450       case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397
6451          if (rB_addr!=0) {
6452             vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n");
6453             return False;
6454          }
6455          DIP("extsb%s r%u,r%u\n",
6456              flag_rC ? ".":"", rA_addr, rS_addr);
6457          if (mode64)
6458             assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) );
6459          else
6460             assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) );
6461          break;
6462 
6463       case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398)
6464          if (rB_addr!=0) {
6465             vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n");
6466             return False;
6467          }
6468          DIP("extsh%s r%u,r%u\n",
6469              flag_rC ? ".":"", rA_addr, rS_addr);
6470          if (mode64)
6471             assign( rA, unop(Iop_16Sto64,
6472                              unop(Iop_64to16, mkexpr(rS))) );
6473          else
6474             assign( rA, unop(Iop_16Sto32,
6475                              unop(Iop_32to16, mkexpr(rS))) );
6476          break;
6477 
6478       case 0x1DC: // nand (NAND, PPC32 p492)
6479          DIP("nand%s r%u,r%u,r%u\n",
6480              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6481          assign( rA, unop( mkSzOp(ty, Iop_Not8),
6482                            binop( mkSzOp(ty, Iop_And8),
6483                                   mkexpr(rS), mkexpr(rB))) );
6484          break;
6485 
6486       case 0x07C: // nor (NOR, PPC32 p494)
6487          DIP("nor%s r%u,r%u,r%u\n",
6488              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6489          assign( rA, unop( mkSzOp(ty, Iop_Not8),
6490                            binop( mkSzOp(ty, Iop_Or8),
6491                                   mkexpr(rS), mkexpr(rB))) );
6492          break;
6493 
6494       case 0x1BC: // or (OR, PPC32 p495)
6495          if ((!flag_rC) && rS_addr == rB_addr) {
6496             DIP("mr r%u,r%u\n", rA_addr, rS_addr);
6497             assign( rA, mkexpr(rS) );
6498          } else {
6499             DIP("or%s r%u,r%u,r%u\n",
6500                 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6501             assign( rA, binop( mkSzOp(ty, Iop_Or8),
6502                                mkexpr(rS), mkexpr(rB)) );
6503          }
6504          break;
6505 
6506       case 0x19C: // orc  (OR with Complement, PPC32 p496)
6507          DIP("orc%s r%u,r%u,r%u\n",
6508              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6509          assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
6510                             unop(mkSzOp(ty, Iop_Not8), mkexpr(rB))));
6511          break;
6512 
6513       case 0x13C: // xor (XOR, PPC32 p549)
6514          DIP("xor%s r%u,r%u,r%u\n",
6515              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6516          assign( rA, binop( mkSzOp(ty, Iop_Xor8),
6517                             mkexpr(rS), mkexpr(rB)) );
6518          break;
6519 
6520 
6521       /* 64bit Integer Logical Instructions */
6522       case 0x3DA: // extsw (Extend Sign Word, PPC64 p430)
6523          if (rB_addr!=0) {
6524             vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n");
6525             return False;
6526          }
6527          DIP("extsw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr);
6528          assign(rA, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(rS))));
6529          break;
6530 
6531       case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401)
6532          if (rB_addr!=0) {
6533             vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n");
6534             return False;
6535          }
6536          DIP("cntlzd%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr);
6537          assign(rA, unop(Iop_ClzNat64, mkexpr(rS)));
6538          break;
6539 
6540       case 0x1FC: // cmpb (Power6: compare bytes)
6541          DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
6542 
6543          if (mode64)
6544             assign( rA, unop( Iop_V128to64,
6545                               binop( Iop_CmpEQ8x16,
6546                                      binop( Iop_64HLtoV128, mkU64(0), mkexpr(rS) ),
6547                                      binop( Iop_64HLtoV128, mkU64(0), mkexpr(rB) )
6548                                      )) );
6549          else
6550             assign( rA, unop( Iop_V128to32,
6551                               binop( Iop_CmpEQ8x16,
6552                                      unop( Iop_32UtoV128, mkexpr(rS) ),
6553                                      unop( Iop_32UtoV128, mkexpr(rB) )
6554                                      )) );
6555          break;
6556 
6557       case 0x2DF: { // mftgpr (move floating-point to general purpose register)
6558          IRTemp frB = newTemp(Ity_F64);
6559          DIP("mftgpr r%u,fr%u\n", rS_addr, rB_addr);
6560 
6561          assign( frB, getFReg(rB_addr));  // always F64
6562          if (mode64)
6563             assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
6564          else
6565             assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) );
6566 
6567          putIReg( rS_addr, mkexpr(rA));
6568          return True;
6569       }
6570 
6571       case 0x25F: { // mffgpr (move floating-point from general purpose register)
6572          IRTemp frA = newTemp(Ity_F64);
6573          DIP("mffgpr fr%u,r%u\n", rS_addr, rB_addr);
6574 
6575          if (mode64)
6576             assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) );
6577          else
6578             assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) );
6579 
6580          putFReg( rS_addr, mkexpr(frA));
6581          return True;
6582       }
6583       case 0x1FA: // popcntd (population count doubleword)
6584       {
6585           vassert(mode64);
6586     	  DIP("popcntd r%u,r%u\n", rA_addr, rS_addr);
6587     	  IRTemp result = gen_POPCOUNT(ty, rS, DWORD);
6588     	  putIReg( rA_addr, mkexpr(result) );
6589     	  return True;
6590       }
6591       case 0x17A: // popcntw (Population Count Words)
6592       {
6593          DIP("popcntw r%u,r%u\n", rA_addr, rS_addr);
6594          if (mode64) {
6595             IRTemp resultHi, resultLo;
6596             IRTemp argLo = newTemp(Ity_I32);
6597             IRTemp argHi = newTemp(Ity_I32);
6598             assign(argLo, unop(Iop_64to32, mkexpr(rS)));
6599             assign(argHi, unop(Iop_64HIto32, mkexpr(rS)));
6600             resultLo = gen_POPCOUNT(Ity_I32, argLo, WORD);
6601             resultHi = gen_POPCOUNT(Ity_I32, argHi, WORD);
6602             putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), mkexpr(resultLo)));
6603          } else {
6604             IRTemp result = gen_POPCOUNT(ty, rS, WORD);
6605             putIReg( rA_addr, mkexpr(result) );
6606          }
6607          return True;
6608       }
6609       case 0x7A: // popcntb (Population Count Byte)
6610       {
6611          DIP("popcntb r%u,r%u\n", rA_addr, rS_addr);
6612 
6613          if (mode64) {
6614             IRTemp resultHi, resultLo;
6615             IRTemp argLo = newTemp(Ity_I32);
6616             IRTemp argHi = newTemp(Ity_I32);
6617             assign(argLo, unop(Iop_64to32, mkexpr(rS)));
6618             assign(argHi, unop(Iop_64HIto32, mkexpr(rS)));
6619             resultLo = gen_POPCOUNT(Ity_I32, argLo, BYTE);
6620             resultHi = gen_POPCOUNT(Ity_I32, argHi, BYTE);
6621             putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi),
6622                                     mkexpr(resultLo)));
6623          } else {
6624             IRTemp result = gen_POPCOUNT(ty, rS, BYTE);
6625             putIReg( rA_addr, mkexpr(result) );
6626          }
6627          return True;
6628       }
6629        case 0x0FC: // bpermd (Bit Permute Doubleword)
6630        {
6631           /* This is a lot of rigmarole to emulate bpermd like this, as it
6632            * could be done much faster by implementing a call to the native
6633            * instruction.  However, where possible I want to avoid using new
6634            * native instructions so that we can use valgrind to emulate those
6635            * instructions on older PPC64 hardware.
6636            */
6637  #define BPERMD_IDX_MASK 0x00000000000000FFULL
6638  #define BPERMD_BIT_MASK 0x8000000000000000ULL
6639           int i;
6640           IRExpr * rS_expr = mkexpr(rS);
6641           IRExpr * res = binop(Iop_And64, mkU64(0), mkU64(0));
6642           DIP("bpermd r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
6643           for (i = 0; i < 8; i++) {
6644              IRTemp idx_tmp = newTemp( Ity_I64 );
6645              IRTemp perm_bit = newTemp( Ity_I64 );
6646              IRTemp idx = newTemp( Ity_I8 );
6647              IRTemp idx_LT64 = newTemp( Ity_I1 );
6648              IRTemp idx_LT64_ity64 = newTemp( Ity_I64 );
6649 
6650              assign( idx_tmp,
6651                      binop( Iop_And64, mkU64( BPERMD_IDX_MASK ), rS_expr ) );
6652              assign( idx_LT64,
6653                            binop( Iop_CmpLT64U, mkexpr( idx_tmp ), mkU64( 64 ) ) );
6654              assign( idx,
6655                            binop( Iop_And8,
6656                                   unop( Iop_1Sto8,
6657                                         mkexpr(idx_LT64) ),
6658                                   unop( Iop_64to8, mkexpr( idx_tmp ) ) ) );
6659              /* If idx_LT64 == 0, we must force the perm bit to '0'. Below, we se idx
6660               * to determine which bit of rB to use for the perm bit, and then we shift
6661               * that bit to the MSB position.  We AND that with a 64-bit-ized idx_LT64
6662               * to set the final perm bit.
6663               */
6664              assign( idx_LT64_ity64,
6665                            unop( Iop_32Uto64, unop( Iop_1Uto32, mkexpr(idx_LT64 ) ) ) );
6666              assign( perm_bit,
6667                            binop( Iop_And64,
6668                                   mkexpr( idx_LT64_ity64 ),
6669                                   binop( Iop_Shr64,
6670                                          binop( Iop_And64,
6671                                                 mkU64( BPERMD_BIT_MASK ),
6672                                                 binop( Iop_Shl64,
6673                                                        mkexpr( rB ),
6674                                                        mkexpr( idx ) ) ),
6675                                          mkU8( 63 ) ) ) );
6676              res = binop( Iop_Or64,
6677                                 res,
6678                                 binop( Iop_Shl64,
6679                                        mkexpr( perm_bit ),
6680                                        mkU8( i ) ) );
6681              rS_expr = binop( Iop_Shr64, rS_expr, mkU8( 8 ) );
6682           }
6683           putIReg(rA_addr, res);
6684           return True;
6685        }
6686 
6687       default:
6688          vex_printf("dis_int_logic(ppc)(opc2)\n");
6689          return False;
6690       }
6691       break;
6692 
6693    default:
6694       vex_printf("dis_int_logic(ppc)(opc1)\n");
6695       return False;
6696    }
6697 
6698    putIReg( rA_addr, mkexpr(rA) );
6699 
6700    if (do_rc && flag_rC) {
6701       set_CR0( mkexpr(rA) );
6702    }
6703    return True;
6704 }
6705 
6706 /*
6707   Integer Parity Instructions
6708 */
dis_int_parity(UInt theInstr)6709 static Bool dis_int_parity ( UInt theInstr )
6710 {
6711    /* X-Form */
6712    UChar opc1    = ifieldOPC(theInstr);
6713    UChar rS_addr = ifieldRegDS(theInstr);
6714    UChar rA_addr = ifieldRegA(theInstr);
6715    UChar rB_addr = ifieldRegB(theInstr);
6716    UInt  opc2    = ifieldOPClo10(theInstr);
6717    UChar b0      = ifieldBIT0(theInstr);
6718    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
6719 
6720    IRTemp rS     = newTemp(ty);
6721    IRTemp rA     = newTemp(ty);
6722    IRTemp iTot1  = newTemp(Ity_I32);
6723    IRTemp iTot2  = newTemp(Ity_I32);
6724    IRTemp iTot3  = newTemp(Ity_I32);
6725    IRTemp iTot4  = newTemp(Ity_I32);
6726    IRTemp iTot5  = newTemp(Ity_I32);
6727    IRTemp iTot6  = newTemp(Ity_I32);
6728    IRTemp iTot7  = newTemp(Ity_I32);
6729    IRTemp iTot8  = newTemp(Ity_I32);
6730    IRTemp rS1    = newTemp(ty);
6731    IRTemp rS2    = newTemp(ty);
6732    IRTemp rS3    = newTemp(ty);
6733    IRTemp rS4    = newTemp(ty);
6734    IRTemp rS5    = newTemp(ty);
6735    IRTemp rS6    = newTemp(ty);
6736    IRTemp rS7    = newTemp(ty);
6737    IRTemp iHi    = newTemp(Ity_I32);
6738    IRTemp iLo    = newTemp(Ity_I32);
6739    IROp to_bit   = (mode64 ? Iop_64to1 : Iop_32to1);
6740    IROp shr_op   = (mode64 ? Iop_Shr64 : Iop_Shr32);
6741 
6742    if (opc1 != 0x1f || rB_addr || b0) {
6743       vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n");
6744       return False;
6745    }
6746 
6747    assign( rS, getIReg(rS_addr) );
6748 
6749    switch (opc2) {
6750    case 0xba:  // prtyd (Parity Doubleword, ISA 2.05 p320)
6751       DIP("prtyd r%u,r%u\n", rA_addr, rS_addr);
6752       assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
6753       assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
6754       assign( iTot2, binop(Iop_Add32,
6755                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
6756                            mkexpr(iTot1)) );
6757       assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
6758       assign( iTot3, binop(Iop_Add32,
6759                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
6760                            mkexpr(iTot2)) );
6761       assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
6762       assign( iTot4, binop(Iop_Add32,
6763                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
6764                            mkexpr(iTot3)) );
6765       if (mode64) {
6766          assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
6767          assign( iTot5, binop(Iop_Add32,
6768                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))),
6769                               mkexpr(iTot4)) );
6770          assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
6771          assign( iTot6, binop(Iop_Add32,
6772                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
6773                               mkexpr(iTot5)) );
6774          assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
6775          assign( iTot7, binop(Iop_Add32,
6776                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
6777                               mkexpr(iTot6)) );
6778          assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)) );
6779          assign( iTot8, binop(Iop_Add32,
6780                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
6781                               mkexpr(iTot7)) );
6782          assign( rA, unop(Iop_32Uto64,
6783                           binop(Iop_And32, mkexpr(iTot8), mkU32(1))) );
6784       } else
6785          assign( rA, mkexpr(iTot4) );
6786 
6787       break;
6788    case 0x9a:  // prtyw (Parity Word, ISA 2.05 p320)
6789       assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
6790       assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
6791       assign( iTot2, binop(Iop_Add32,
6792                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
6793                            mkexpr(iTot1)) );
6794       assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
6795       assign( iTot3, binop(Iop_Add32,
6796                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
6797                            mkexpr(iTot2)) );
6798       assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
6799       assign( iTot4, binop(Iop_Add32,
6800                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
6801                            mkexpr(iTot3)) );
6802       assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) );
6803 
6804       if (mode64) {
6805          assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
6806          assign( iTot5, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))) );
6807          assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
6808          assign( iTot6, binop(Iop_Add32,
6809                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
6810                               mkexpr(iTot5)) );
6811          assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
6812          assign( iTot7, binop(Iop_Add32,
6813                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
6814                               mkexpr(iTot6)) );
6815          assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)));
6816          assign( iTot8, binop(Iop_Add32,
6817                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
6818                               mkexpr(iTot7)) );
6819          assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ),
6820             assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) );
6821       } else
6822          assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) );
6823       break;
6824    default:
6825       vex_printf("dis_int_parity(ppc)(opc2)\n");
6826       return False;
6827    }
6828 
6829    putIReg( rA_addr, mkexpr(rA) );
6830 
6831    return True;
6832 }
6833 
6834 
6835 /*
6836   Integer Rotate Instructions
6837 */
dis_int_rot(UInt theInstr)6838 static Bool dis_int_rot ( UInt theInstr )
6839 {
6840    /* M-Form, MDS-Form */
6841    UChar opc1    = ifieldOPC(theInstr);
6842    UChar rS_addr = ifieldRegDS(theInstr);
6843    UChar rA_addr = ifieldRegA(theInstr);
6844    UChar rB_addr = ifieldRegB(theInstr);
6845    UChar sh_imm  = rB_addr;
6846    UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) );
6847    UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) );
6848    UChar msk_imm = toUChar( IFIELD( theInstr, 5, 6 ) );
6849    UChar opc2    = toUChar( IFIELD( theInstr, 2, 3 ) );
6850    UChar b1      = ifieldBIT1(theInstr);
6851    UChar flag_rC = ifieldBIT0(theInstr);
6852 
6853    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
6854    IRTemp rS     = newTemp(ty);
6855    IRTemp rA     = newTemp(ty);
6856    IRTemp rB     = newTemp(ty);
6857    IRTemp rot    = newTemp(ty);
6858    IRExpr *r;
6859    UInt   mask32;
6860    ULong  mask64;
6861 
6862    assign( rS, getIReg(rS_addr) );
6863    assign( rB, getIReg(rB_addr) );
6864 
6865    switch (opc1) {
6866    case 0x14: {
6867       // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500)
6868       DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
6869           rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
6870       if (mode64) {
6871          // tmp32 = (ROTL(rS_Lo32, Imm)
6872          // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64)
6873          mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
6874          r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
6875          r = unop(Iop_32Uto64, r);
6876          assign( rot, binop(Iop_Or64, r,
6877                             binop(Iop_Shl64, r, mkU8(32))) );
6878          assign( rA,
6879             binop(Iop_Or64,
6880                   binop(Iop_And64, mkexpr(rot), mkU64(mask64)),
6881                   binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) );
6882       }
6883       else {
6884          // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask);
6885          mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
6886          r = ROTL(mkexpr(rS), mkU8(sh_imm));
6887          assign( rA,
6888             binop(Iop_Or32,
6889                   binop(Iop_And32, mkU32(mask32), r),
6890                   binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) );
6891       }
6892       break;
6893    }
6894 
6895    case 0x15: {
6896       // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501)
6897       vassert(MaskBeg < 32);
6898       vassert(MaskEnd < 32);
6899       vassert(sh_imm  < 32);
6900 
6901       if (mode64) {
6902          IRTemp rTmp = newTemp(Ity_I64);
6903          mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
6904          DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
6905              rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
6906          // tmp32 = (ROTL(rS_Lo32, Imm)
6907          // rA = ((tmp32 || tmp32) & mask64)
6908          r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
6909          r = unop(Iop_32Uto64, r);
6910          assign( rTmp, r );
6911          r = NULL;
6912          assign( rot, binop(Iop_Or64, mkexpr(rTmp),
6913                             binop(Iop_Shl64, mkexpr(rTmp), mkU8(32))) );
6914          assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
6915       }
6916       else {
6917          if (MaskBeg == 0 && sh_imm+MaskEnd == 31) {
6918             /* Special-case the ,n,0,31-n form as that is just n-bit
6919                shift left, PPC32 p501 */
6920             DIP("slwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
6921                 rA_addr, rS_addr, sh_imm);
6922             assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) );
6923          }
6924          else if (MaskEnd == 31 && sh_imm+MaskBeg == 32) {
6925             /* Special-case the ,32-n,n,31 form as that is just n-bit
6926                unsigned shift right, PPC32 p501 */
6927             DIP("srwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
6928                 rA_addr, rS_addr, MaskBeg);
6929             assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) );
6930          }
6931          else {
6932             /* General case. */
6933             mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
6934             DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
6935                 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
6936             // rA = ROTL(rS, Imm) & mask
6937             assign( rA, binop(Iop_And32,
6938                               ROTL(mkexpr(rS), mkU8(sh_imm)),
6939                               mkU32(mask32)) );
6940          }
6941       }
6942       break;
6943    }
6944 
6945    case 0x17: {
6946       // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503
6947       DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? ".":"",
6948           rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd);
6949       if (mode64) {
6950          mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
6951          /* weird insn alert!
6952             tmp32 = (ROTL(rS_Lo32, rB[0-4])
6953             rA = ((tmp32 || tmp32) & mask64)
6954          */
6955          // note, ROTL does the masking, so we don't do it here
6956          r = ROTL( unop(Iop_64to32, mkexpr(rS)),
6957                    unop(Iop_64to8, mkexpr(rB)) );
6958          r = unop(Iop_32Uto64, r);
6959          assign(rot, binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32))));
6960          assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
6961       } else {
6962          mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
6963          // rA = ROTL(rS, rB[0-4]) & mask
6964          // note, ROTL does the masking, so we don't do it here
6965          assign( rA, binop(Iop_And32,
6966                            ROTL(mkexpr(rS),
6967                                 unop(Iop_32to8, mkexpr(rB))),
6968                            mkU32(mask32)) );
6969       }
6970       break;
6971    }
6972 
6973    /* 64bit Integer Rotates */
6974    case 0x1E: {
6975       msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1);
6976       sh_imm |= b1 << 5;
6977 
6978       vassert( msk_imm < 64 );
6979       vassert( sh_imm < 64 );
6980 
6981       switch (opc2) {
6982       case 0x4: {
6983          /* r = ROTL64( rS, rB_lo6) */
6984          r = ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) );
6985 
6986          if (b1 == 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555)
6987             DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
6988                 rA_addr, rS_addr, rB_addr, msk_imm);
6989             // note, ROTL does the masking, so we don't do it here
6990             mask64 = MASK64(0, 63-msk_imm);
6991             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
6992             break;
6993          } else {       // rldcr (Rotl DWord, Clear Right, PPC64 p556)
6994             DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
6995                 rA_addr, rS_addr, rB_addr, msk_imm);
6996             mask64 = MASK64(63-msk_imm, 63);
6997             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
6998             break;
6999          }
7000          break;
7001       }
7002       case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557)
7003          DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
7004              rA_addr, rS_addr, sh_imm, msk_imm);
7005          r = ROTL(mkexpr(rS), mkU8(sh_imm));
7006          mask64 = MASK64(sh_imm, 63-msk_imm);
7007          assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
7008          break;
7009          // later: deal with special case: (msk_imm==0) => SHL(sh_imm)
7010          /*
7011            Hmm... looks like this'll do the job more simply:
7012            r = SHL(rS, sh_imm)
7013            m = ~(1 << (63-msk_imm))
7014            assign(rA, r & m);
7015          */
7016 
7017       case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558)
7018          if (mode64
7019              && sh_imm + msk_imm == 64 && msk_imm >= 1 && msk_imm <= 63) {
7020             /* special-case the ,64-n,n form as that is just
7021                unsigned shift-right by n */
7022             DIP("srdi%s r%u,r%u,%u\n",
7023                 flag_rC ? ".":"", rA_addr, rS_addr, msk_imm);
7024             assign( rA, binop(Iop_Shr64, mkexpr(rS), mkU8(msk_imm)) );
7025          } else {
7026             DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
7027                 rA_addr, rS_addr, sh_imm, msk_imm);
7028             r = ROTL(mkexpr(rS), mkU8(sh_imm));
7029             mask64 = MASK64(0, 63-msk_imm);
7030             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
7031          }
7032          break;
7033 
7034       case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559)
7035          if (mode64
7036              && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) {
7037             /* special-case the ,n,63-n form as that is just
7038                shift-left by n */
7039             DIP("sldi%s r%u,r%u,%u\n",
7040                 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
7041             assign( rA, binop(Iop_Shl64, mkexpr(rS), mkU8(sh_imm)) );
7042          } else {
7043             DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
7044                 rA_addr, rS_addr, sh_imm, msk_imm);
7045             r = ROTL(mkexpr(rS), mkU8(sh_imm));
7046             mask64 = MASK64(63-msk_imm, 63);
7047             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
7048          }
7049          break;
7050 
7051       case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560)
7052          IRTemp rA_orig = newTemp(ty);
7053          DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
7054              rA_addr, rS_addr, sh_imm, msk_imm);
7055          r = ROTL(mkexpr(rS), mkU8(sh_imm));
7056          mask64 = MASK64(sh_imm, 63-msk_imm);
7057          assign( rA_orig, getIReg(rA_addr) );
7058          assign( rA, binop(Iop_Or64,
7059                            binop(Iop_And64, mkU64(mask64),  r),
7060                            binop(Iop_And64, mkU64(~mask64),
7061                                             mkexpr(rA_orig))) );
7062          break;
7063       }
7064       default:
7065          vex_printf("dis_int_rot(ppc)(opc2)\n");
7066          return False;
7067       }
7068       break;
7069    }
7070 
7071    default:
7072       vex_printf("dis_int_rot(ppc)(opc1)\n");
7073       return False;
7074    }
7075 
7076    putIReg( rA_addr, mkexpr(rA) );
7077 
7078    if (flag_rC) {
7079       set_CR0( mkexpr(rA) );
7080    }
7081    return True;
7082 }
7083 
7084 
7085 /*
7086   Integer Load Instructions
7087 */
dis_int_load(UInt theInstr)7088 static Bool dis_int_load ( UInt theInstr )
7089 {
7090    /* D-Form, X-Form, DS-Form */
7091    UChar opc1     = ifieldOPC(theInstr);
7092    UChar rD_addr  = ifieldRegDS(theInstr);
7093    UChar rA_addr  = ifieldRegA(theInstr);
7094    UInt  uimm16   = ifieldUIMM16(theInstr);
7095    UChar rB_addr  = ifieldRegB(theInstr);
7096    UInt  opc2     = ifieldOPClo10(theInstr);
7097    UChar b1       = ifieldBIT1(theInstr);
7098    UChar b0       = ifieldBIT0(theInstr);
7099 
7100    Int     simm16 = extend_s_16to32(uimm16);
7101    IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
7102    IRTemp  EA     = newTemp(ty);
7103    IRExpr* val;
7104 
7105    switch (opc1) {
7106    case 0x1F: // register offset
7107       assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
7108       break;
7109    case 0x38: // immediate offset: 64bit: lq: maskoff
7110               // lowest 4 bits of immediate before forming EA
7111       simm16 = simm16 & 0xFFFFFFF0;
7112       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
7113       break;
7114    case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off
7115               // lowest 2 bits of immediate before forming EA
7116       simm16 = simm16 & 0xFFFFFFFC;
7117       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
7118       break;
7119    default:   // immediate offset
7120       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
7121       break;
7122    }
7123 
7124    switch (opc1) {
7125    case 0x22: // lbz (Load B & Zero, PPC32 p433)
7126       DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
7127       val = load(Ity_I8, mkexpr(EA));
7128       putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
7129       break;
7130 
7131    case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434)
7132       if (rA_addr == 0 || rA_addr == rD_addr) {
7133          vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n");
7134          return False;
7135       }
7136       DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
7137       val = load(Ity_I8, mkexpr(EA));
7138       putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
7139       putIReg( rA_addr, mkexpr(EA) );
7140       break;
7141 
7142    case 0x2A: // lha (Load HW Alg, PPC32 p445)
7143       DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
7144       val = load(Ity_I16, mkexpr(EA));
7145       putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
7146       break;
7147 
7148    case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446)
7149       if (rA_addr == 0 || rA_addr == rD_addr) {
7150          vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n");
7151          return False;
7152       }
7153       DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
7154       val = load(Ity_I16, mkexpr(EA));
7155       putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
7156       putIReg( rA_addr, mkexpr(EA) );
7157       break;
7158 
7159    case 0x28: // lhz (Load HW & Zero, PPC32 p450)
7160       DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
7161       val = load(Ity_I16, mkexpr(EA));
7162       putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
7163       break;
7164 
7165    case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451)
7166       if (rA_addr == 0 || rA_addr == rD_addr) {
7167          vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n");
7168          return False;
7169       }
7170       DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
7171       val = load(Ity_I16, mkexpr(EA));
7172       putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
7173       putIReg( rA_addr, mkexpr(EA) );
7174       break;
7175 
7176    case 0x20: // lwz (Load W & Zero, PPC32 p460)
7177       DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
7178       val = load(Ity_I32, mkexpr(EA));
7179       putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
7180       break;
7181 
7182    case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461))
7183       if (rA_addr == 0 || rA_addr == rD_addr) {
7184          vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n");
7185          return False;
7186       }
7187       DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
7188       val = load(Ity_I32, mkexpr(EA));
7189       putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
7190       putIReg( rA_addr, mkexpr(EA) );
7191       break;
7192 
7193    /* X Form */
7194    case 0x1F:
7195       if (b0 != 0) {
7196          vex_printf("dis_int_load(ppc)(Ox1F,b0)\n");
7197          return False;
7198       }
7199 
7200       switch (opc2) {
7201       case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435)
7202          DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7203          if (rA_addr == 0 || rA_addr == rD_addr) {
7204             vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
7205             return False;
7206          }
7207          val = load(Ity_I8, mkexpr(EA));
7208          putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
7209          putIReg( rA_addr, mkexpr(EA) );
7210          break;
7211 
7212       case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436)
7213          DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7214          val = load(Ity_I8, mkexpr(EA));
7215          putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
7216          break;
7217 
7218       case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447)
7219          if (rA_addr == 0 || rA_addr == rD_addr) {
7220             vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n");
7221             return False;
7222          }
7223          DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7224          val = load(Ity_I16, mkexpr(EA));
7225          putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
7226          putIReg( rA_addr, mkexpr(EA) );
7227          break;
7228 
7229       case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448)
7230          DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7231          val = load(Ity_I16, mkexpr(EA));
7232          putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
7233          break;
7234 
7235       case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452)
7236          if (rA_addr == 0 || rA_addr == rD_addr) {
7237             vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n");
7238             return False;
7239          }
7240          DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7241          val = load(Ity_I16, mkexpr(EA));
7242          putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
7243          putIReg( rA_addr, mkexpr(EA) );
7244          break;
7245 
7246       case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453)
7247          DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7248          val = load(Ity_I16, mkexpr(EA));
7249          putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
7250          break;
7251 
7252       case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462)
7253          if (rA_addr == 0 || rA_addr == rD_addr) {
7254             vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
7255             return False;
7256          }
7257          DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7258          val = load(Ity_I32, mkexpr(EA));
7259          putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
7260          putIReg( rA_addr, mkexpr(EA) );
7261          break;
7262 
7263       case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463)
7264          DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7265          val = load(Ity_I32, mkexpr(EA));
7266          putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
7267          break;
7268 
7269 
7270       /* 64bit Loads */
7271       case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475)
7272          if (rA_addr == 0 || rA_addr == rD_addr) {
7273             vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n");
7274             return False;
7275          }
7276          DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7277          putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
7278          putIReg( rA_addr, mkexpr(EA) );
7279          break;
7280 
7281       case 0x015: // ldx (Load DWord, Indexed, PPC64 p476)
7282          DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7283          putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
7284          break;
7285 
7286       case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501)
7287          if (rA_addr == 0 || rA_addr == rD_addr) {
7288             vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n");
7289             return False;
7290          }
7291          DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7292          putIReg( rD_addr,
7293                   unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
7294          putIReg( rA_addr, mkexpr(EA) );
7295          break;
7296 
7297       case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502)
7298          DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7299          putIReg( rD_addr,
7300                   unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
7301          break;
7302 
7303       default:
7304          vex_printf("dis_int_load(ppc)(opc2)\n");
7305          return False;
7306       }
7307       break;
7308 
7309    /* DS Form - 64bit Loads.  In each case EA will have been formed
7310       with the lowest 2 bits masked off the immediate offset. */
7311    case 0x3A:
7312       switch ((b1<<1) | b0) {
7313       case 0x0: // ld (Load DWord, PPC64 p472)
7314          DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
7315          putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
7316          break;
7317 
7318       case 0x1: // ldu (Load DWord, Update, PPC64 p474)
7319          if (rA_addr == 0 || rA_addr == rD_addr) {
7320             vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n");
7321             return False;
7322          }
7323          DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
7324          putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
7325          putIReg( rA_addr, mkexpr(EA) );
7326          break;
7327 
7328       case 0x2: // lwa (Load Word Alg, PPC64 p499)
7329          DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
7330          putIReg( rD_addr,
7331                   unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
7332          break;
7333 
7334       default:
7335          vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
7336          return False;
7337       }
7338       break;
7339 
7340    case 0x38: {
7341       IRTemp  high = newTemp(ty);
7342       IRTemp  low  = newTemp(ty);
7343       /* DQ Form - 128bit Loads. Lowest bits [1:0] are the PT field. */
7344       DIP("lq r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
7345       /* NOTE: there are some changes to XER[41:42] that have not been
7346        * implemented.
7347        */
7348       // trap if EA misaligned on 16 byte address
7349       if (mode64) {
7350          if (host_endness == VexEndnessBE) {
7351             assign(high, load(ty, mkexpr( EA ) ) );
7352             assign(low, load(ty, binop( Iop_Add64,
7353                                         mkexpr( EA ),
7354                                         mkU64( 8 ) ) ) );
7355 	 } else {
7356             assign(low, load(ty, mkexpr( EA ) ) );
7357             assign(high, load(ty, binop( Iop_Add64,
7358                                          mkexpr( EA ),
7359                                          mkU64( 8 ) ) ) );
7360 	 }
7361       } else {
7362          assign(high, load(ty, binop( Iop_Add32,
7363                                       mkexpr( EA ),
7364                                       mkU32( 4 ) ) ) );
7365          assign(low, load(ty, binop( Iop_Add32,
7366                                       mkexpr( EA ),
7367                                       mkU32( 12 ) ) ) );
7368       }
7369       gen_SIGBUS_if_misaligned( EA, 16 );
7370       putIReg( rD_addr,  mkexpr( high) );
7371       putIReg( rD_addr+1,  mkexpr( low) );
7372       break;
7373    }
7374    default:
7375       vex_printf("dis_int_load(ppc)(opc1)\n");
7376       return False;
7377    }
7378    return True;
7379 }
7380 
7381 
7382 
7383 /*
7384   Integer Store Instructions
7385 */
dis_int_store(UInt theInstr,const VexAbiInfo * vbi)7386 static Bool dis_int_store ( UInt theInstr, const VexAbiInfo* vbi )
7387 {
7388    /* D-Form, X-Form, DS-Form */
7389    UChar opc1    = ifieldOPC(theInstr);
7390    UInt  rS_addr = ifieldRegDS(theInstr);
7391    UInt  rA_addr = ifieldRegA(theInstr);
7392    UInt  uimm16  = ifieldUIMM16(theInstr);
7393    UInt  rB_addr = ifieldRegB(theInstr);
7394    UInt  opc2    = ifieldOPClo10(theInstr);
7395    UChar b1      = ifieldBIT1(theInstr);
7396    UChar b0      = ifieldBIT0(theInstr);
7397 
7398    Int    simm16 = extend_s_16to32(uimm16);
7399    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
7400    IRTemp rS     = newTemp(ty);
7401    IRTemp rB     = newTemp(ty);
7402    IRTemp EA     = newTemp(ty);
7403 
7404    assign( rB, getIReg(rB_addr) );
7405    assign( rS, getIReg(rS_addr) );
7406 
7407    switch (opc1) {
7408    case 0x1F: // register offset
7409       assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
7410       break;
7411    case 0x3E: // immediate offset: 64bit: std/stdu/stq: mask off
7412               // lowest 2 bits of immediate before forming EA
7413       simm16 = simm16 & 0xFFFFFFFC;
7414    default:   // immediate offset
7415       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
7416       break;
7417    }
7418 
7419    switch (opc1) {
7420    case 0x26: // stb (Store B, PPC32 p509)
7421       DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
7422       store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
7423       break;
7424 
7425    case 0x27: // stbu (Store B, Update, PPC32 p510)
7426       if (rA_addr == 0 ) {
7427          vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n");
7428          return False;
7429       }
7430       DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
7431       putIReg( rA_addr, mkexpr(EA) );
7432       store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
7433       break;
7434 
7435    case 0x2C: // sth (Store HW, PPC32 p522)
7436       DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
7437       store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
7438       break;
7439 
7440    case 0x2D: // sthu (Store HW, Update, PPC32 p524)
7441       if (rA_addr == 0) {
7442          vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n");
7443          return False;
7444       }
7445       DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
7446       putIReg( rA_addr, mkexpr(EA) );
7447       store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
7448       break;
7449 
7450    case 0x24: // stw (Store W, PPC32 p530)
7451       DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
7452       store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
7453       break;
7454 
7455    case 0x25: // stwu (Store W, Update, PPC32 p534)
7456       if (rA_addr == 0) {
7457          vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n");
7458          return False;
7459       }
7460       DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
7461       putIReg( rA_addr, mkexpr(EA) );
7462       store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
7463       break;
7464 
7465    /* X Form : all these use EA_indexed */
7466    case 0x1F:
7467       if (b0 != 0) {
7468          vex_printf("dis_int_store(ppc)(0x1F,b0)\n");
7469          return False;
7470       }
7471 
7472       switch (opc2) {
7473       case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511)
7474          if (rA_addr == 0) {
7475             vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n");
7476             return False;
7477          }
7478          DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7479          putIReg( rA_addr, mkexpr(EA) );
7480          store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
7481          break;
7482 
7483       case 0x0D7: // stbx (Store B Indexed, PPC32 p512)
7484          DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7485          store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
7486          break;
7487 
7488       case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525)
7489          if (rA_addr == 0) {
7490             vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n");
7491             return False;
7492          }
7493          DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7494          putIReg( rA_addr, mkexpr(EA) );
7495          store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
7496          break;
7497 
7498       case 0x197: // sthx (Store HW Indexed, PPC32 p526)
7499          DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7500          store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
7501          break;
7502 
7503       case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535)
7504          if (rA_addr == 0) {
7505             vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n");
7506             return False;
7507          }
7508          DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7509          putIReg( rA_addr, mkexpr(EA) );
7510          store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
7511          break;
7512 
7513       case 0x097: // stwx (Store W Indexed, PPC32 p536)
7514          DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7515          store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
7516          break;
7517 
7518 
7519       /* 64bit Stores */
7520       case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584)
7521          if (rA_addr == 0) {
7522             vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n");
7523             return False;
7524          }
7525          DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7526          putIReg( rA_addr, mkexpr(EA) );
7527          store( mkexpr(EA), mkexpr(rS) );
7528          break;
7529 
7530       case 0x095: // stdx (Store DWord Indexed, PPC64 p585)
7531          DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7532          store( mkexpr(EA), mkexpr(rS) );
7533          break;
7534 
7535       default:
7536          vex_printf("dis_int_store(ppc)(opc2)\n");
7537          return False;
7538       }
7539       break;
7540 
7541    /* DS Form - 64bit Stores.  In each case EA will have been formed
7542       with the lowest 2 bits masked off the immediate offset. */
7543    case 0x3E:
7544       switch ((b1<<1) | b0) {
7545       case 0x0: // std (Store DWord, PPC64 p580)
7546          if (!mode64)
7547             return False;
7548 
7549          DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
7550          store( mkexpr(EA), mkexpr(rS) );
7551          break;
7552 
7553       case 0x1: // stdu (Store DWord, Update, PPC64 p583)
7554          if (!mode64)
7555             return False;
7556 
7557          DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
7558          putIReg( rA_addr, mkexpr(EA) );
7559          store( mkexpr(EA), mkexpr(rS) );
7560          break;
7561 
7562       case 0x2: { // stq (Store QuadWord, Update, PPC64 p583)
7563          IRTemp EA_hi = newTemp(ty);
7564          IRTemp EA_lo = newTemp(ty);
7565          DIP("stq r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
7566 
7567          if (mode64) {
7568             if (host_endness == VexEndnessBE) {
7569 
7570                /* upper 64-bits */
7571                assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) );
7572 
7573                /* lower 64-bits */
7574                assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+8 ) );
7575 	    } else {
7576                /* upper 64-bits */
7577                assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+8 ) );
7578 
7579                /* lower 64-bits */
7580                assign( EA_lo, ea_rAor0_simm( rA_addr, simm16 ) );
7581 	    }
7582          } else {
7583             /* upper half of upper 64-bits */
7584             assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+4 ) );
7585 
7586             /* lower half of upper 64-bits */
7587             assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+12 ) );
7588          }
7589          store( mkexpr(EA_hi), mkexpr(rS) );
7590          store( mkexpr(EA_lo), getIReg( rS_addr+1 ) );
7591          break;
7592       }
7593       default:
7594          vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
7595          return False;
7596       }
7597       break;
7598 
7599    default:
7600       vex_printf("dis_int_store(ppc)(opc1)\n");
7601       return False;
7602    }
7603    return True;
7604 }
7605 
7606 
7607 
7608 /*
7609   Integer Load/Store Multiple Instructions
7610 */
dis_int_ldst_mult(UInt theInstr)7611 static Bool dis_int_ldst_mult ( UInt theInstr )
7612 {
7613    /* D-Form */
7614    UChar opc1     = ifieldOPC(theInstr);
7615    UChar rD_addr  = ifieldRegDS(theInstr);
7616    UChar rS_addr  = rD_addr;
7617    UChar rA_addr  = ifieldRegA(theInstr);
7618    UInt  uimm16   = ifieldUIMM16(theInstr);
7619 
7620    Int     simm16 = extend_s_16to32(uimm16);
7621    IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
7622    IROp    mkAdd  = mode64 ? Iop_Add64 : Iop_Add32;
7623    IRTemp  EA     = newTemp(ty);
7624    UInt    r      = 0;
7625    UInt    ea_off = 0;
7626    IRExpr* irx_addr;
7627 
7628    assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
7629 
7630    switch (opc1) {
7631    case 0x2E: // lmw (Load Multiple Word, PPC32 p454)
7632       if (rA_addr >= rD_addr) {
7633          vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n");
7634          return False;
7635       }
7636       DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
7637       for (r = rD_addr; r <= 31; r++) {
7638          irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off));
7639          putIReg( r, mkWidenFrom32(ty, load(Ity_I32, irx_addr ),
7640                                        False) );
7641          ea_off += 4;
7642       }
7643       break;
7644 
7645    case 0x2F: // stmw (Store Multiple Word, PPC32 p527)
7646       DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
7647       for (r = rS_addr; r <= 31; r++) {
7648          irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off));
7649          store( irx_addr, mkNarrowTo32(ty, getIReg(r)) );
7650          ea_off += 4;
7651       }
7652       break;
7653 
7654    default:
7655       vex_printf("dis_int_ldst_mult(ppc)(opc1)\n");
7656       return False;
7657    }
7658    return True;
7659 }
7660 
7661 
7662 
7663 /*
7664   Integer Load/Store String Instructions
7665 */
7666 static
generate_lsw_sequence(IRTemp tNBytes,IRTemp EA,Int rD,Int maxBytes)7667 void generate_lsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
7668                              IRTemp EA,        // EA
7669                              Int    rD,        // first dst register
7670                              Int    maxBytes ) // 32 or 128
7671 {
7672    Int     i, shift = 24;
7673    IRExpr* e_nbytes = mkexpr(tNBytes);
7674    IRExpr* e_EA     = mkexpr(EA);
7675    IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
7676 
7677    vassert(rD >= 0 && rD < 32);
7678    rD--; if (rD < 0) rD = 31;
7679 
7680    for (i = 0; i < maxBytes; i++) {
7681       /* if (nBytes < (i+1)) goto NIA; */
7682       stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
7683                          Ijk_Boring,
7684                          mkSzConst( ty, nextInsnAddr()), OFFB_CIA ));
7685       /* when crossing into a new dest register, set it to zero. */
7686       if ((i % 4) == 0) {
7687          rD++; if (rD == 32) rD = 0;
7688          putIReg(rD, mkSzImm(ty, 0));
7689          shift = 24;
7690       }
7691       /* rD |=  (8Uto32(*(EA+i))) << shift */
7692       vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
7693       putIReg(
7694          rD,
7695          mkWidenFrom32(
7696             ty,
7697             binop(
7698                Iop_Or32,
7699                mkNarrowTo32(ty, getIReg(rD)),
7700                binop(
7701                   Iop_Shl32,
7702                   unop(
7703                      Iop_8Uto32,
7704                      load( Ity_I8,
7705                            binop( mkSzOp(ty,Iop_Add8),
7706                                   e_EA, mkSzImm(ty,i)))
7707                   ),
7708                   mkU8(toUChar(shift))
7709                )
7710             ),
7711             /*Signed*/False
7712 	 )
7713       );
7714       shift -= 8;
7715    }
7716 }
7717 
7718 static
generate_stsw_sequence(IRTemp tNBytes,IRTemp EA,Int rS,Int maxBytes)7719 void generate_stsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
7720                               IRTemp EA,        // EA
7721                               Int    rS,        // first src register
7722                               Int    maxBytes ) // 32 or 128
7723 {
7724    Int     i, shift = 24;
7725    IRExpr* e_nbytes = mkexpr(tNBytes);
7726    IRExpr* e_EA     = mkexpr(EA);
7727    IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
7728 
7729    vassert(rS >= 0 && rS < 32);
7730    rS--; if (rS < 0) rS = 31;
7731 
7732    for (i = 0; i < maxBytes; i++) {
7733       /* if (nBytes < (i+1)) goto NIA; */
7734       stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
7735                          Ijk_Boring,
7736                          mkSzConst( ty, nextInsnAddr() ), OFFB_CIA ));
7737       /* check for crossing into a new src register. */
7738       if ((i % 4) == 0) {
7739          rS++; if (rS == 32) rS = 0;
7740          shift = 24;
7741       }
7742       /* *(EA+i) = 32to8(rS >> shift) */
7743       vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
7744       store(
7745             binop( mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)),
7746             unop( Iop_32to8,
7747                   binop( Iop_Shr32,
7748                          mkNarrowTo32( ty, getIReg(rS) ),
7749                          mkU8( toUChar(shift) )))
7750       );
7751       shift -= 8;
7752    }
7753 }
7754 
dis_int_ldst_str(UInt theInstr,Bool * stopHere)7755 static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere )
7756 {
7757    /* X-Form */
7758    UChar opc1     = ifieldOPC(theInstr);
7759    UChar rD_addr  = ifieldRegDS(theInstr);
7760    UChar rS_addr  = rD_addr;
7761    UChar rA_addr  = ifieldRegA(theInstr);
7762    UChar rB_addr  = ifieldRegB(theInstr);
7763    UChar NumBytes = rB_addr;
7764    UInt  opc2     = ifieldOPClo10(theInstr);
7765    UChar b0       = ifieldBIT0(theInstr);
7766 
7767    IRType ty      = mode64 ? Ity_I64 : Ity_I32;
7768    IRTemp t_EA    = newTemp(ty);
7769    IRTemp t_nbytes = IRTemp_INVALID;
7770 
7771    *stopHere = False;
7772 
7773    if (opc1 != 0x1F || b0 != 0) {
7774       vex_printf("dis_int_ldst_str(ppc)(opc1)\n");
7775       return False;
7776    }
7777 
7778    switch (opc2) {
7779    case 0x255: // lswi (Load String Word Immediate, PPC32 p455)
7780       /* NB: does not reject the case where RA is in the range of
7781          registers to be loaded.  It should. */
7782       DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes);
7783       assign( t_EA, ea_rAor0(rA_addr) );
7784       if (NumBytes == 8 && !mode64) {
7785          /* Special case hack */
7786          /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */
7787          putIReg( rD_addr,
7788                   load(Ity_I32, mkexpr(t_EA)) );
7789          putIReg( (rD_addr+1) % 32,
7790                   load(Ity_I32,
7791                        binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) );
7792       } else {
7793          t_nbytes = newTemp(Ity_I32);
7794          assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
7795          generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
7796          *stopHere = True;
7797       }
7798       return True;
7799 
7800    case 0x215: // lswx (Load String Word Indexed, PPC32 p456)
7801       /* NB: does not reject the case where RA is in the range of
7802          registers to be loaded.  It should.  Although considering
7803          that that can only be detected at run time, it's not easy to
7804          do so. */
7805       if (rD_addr == rA_addr || rD_addr == rB_addr)
7806          return False;
7807       if (rD_addr == 0 && rA_addr == 0)
7808          return False;
7809       DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7810       t_nbytes = newTemp(Ity_I32);
7811       assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
7812       assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
7813       generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 );
7814       *stopHere = True;
7815       return True;
7816 
7817    case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528)
7818       DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes);
7819       assign( t_EA, ea_rAor0(rA_addr) );
7820       if (NumBytes == 8 && !mode64) {
7821          /* Special case hack */
7822          /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */
7823          store( mkexpr(t_EA),
7824                 getIReg(rD_addr) );
7825          store( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)),
7826                 getIReg((rD_addr+1) % 32) );
7827       } else {
7828          t_nbytes = newTemp(Ity_I32);
7829          assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
7830          generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
7831          *stopHere = True;
7832       }
7833       return True;
7834 
7835    case 0x295: // stswx (Store String Word Indexed, PPC32 p529)
7836       DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7837       t_nbytes = newTemp(Ity_I32);
7838       assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
7839       assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
7840       generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 );
7841       *stopHere = True;
7842       return True;
7843 
7844    default:
7845       vex_printf("dis_int_ldst_str(ppc)(opc2)\n");
7846       return False;
7847    }
7848    return True;
7849 }
7850 
7851 
7852 /* ------------------------------------------------------------------
7853    Integer Branch Instructions
7854    ------------------------------------------------------------------ */
7855 
7856 /*
7857   Branch helper function
7858   ok = BO[2] | ((CTR[0] != 0) ^ BO[1])
7859   Returns an I32 which is 0x00000000 if the ctr condition failed
7860   and 0xFFFFFFFF otherwise.
7861 */
branch_ctr_ok(UInt BO)7862 static IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO )
7863 {
7864    IRType ty = mode64 ? Ity_I64 : Ity_I32;
7865    IRTemp ok = newTemp(Ity_I32);
7866 
7867    if ((BO >> 2) & 1) {     // independent of ctr
7868       assign( ok, mkU32(0xFFFFFFFF) );
7869    } else {
7870       if ((BO >> 1) & 1) {  // ctr == 0 ?
7871          assign( ok, unop( Iop_1Sto32,
7872                            binop( mkSzOp(ty, Iop_CmpEQ8),
7873                                   getGST( PPC_GST_CTR ),
7874                                   mkSzImm(ty,0))) );
7875       } else {              // ctr != 0 ?
7876          assign( ok, unop( Iop_1Sto32,
7877                            binop( mkSzOp(ty, Iop_CmpNE8),
7878                                   getGST( PPC_GST_CTR ),
7879                                   mkSzImm(ty,0))) );
7880       }
7881    }
7882    return mkexpr(ok);
7883 }
7884 
7885 
7886 /*
7887   Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3])
7888   Returns an I32 which is either 0 if the condition failed or
7889   some arbitrary nonzero value otherwise. */
7890 
branch_cond_ok(UInt BO,UInt BI)7891 static IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI )
7892 {
7893    Int where;
7894    IRTemp res   = newTemp(Ity_I32);
7895    IRTemp cr_bi = newTemp(Ity_I32);
7896 
7897    if ((BO >> 4) & 1) {
7898       assign( res, mkU32(1) );
7899    } else {
7900       // ok = (CR[BI] == BO[3]) Note, the following relies on
7901       // getCRbit_anywhere returning a value which
7902       // is either zero or has exactly 1 bit set.
7903       assign( cr_bi, getCRbit_anywhere( BI, &where ) );
7904 
7905       if ((BO >> 3) & 1) {
7906          /* We can use cr_bi as-is. */
7907          assign( res, mkexpr(cr_bi) );
7908       } else {
7909          /* We have to invert the sense of the information held in
7910             cr_bi.  For that we need to know which bit
7911             getCRbit_anywhere regards as significant. */
7912          assign( res, binop(Iop_Xor32, mkexpr(cr_bi),
7913                                        mkU32(1<<where)) );
7914       }
7915    }
7916    return mkexpr(res);
7917 }
7918 
7919 
7920 /*
7921   Integer Branch Instructions
7922 */
dis_branch(UInt theInstr,const VexAbiInfo * vbi,DisResult * dres,Bool (* resteerOkFn)(void *,Addr),void * callback_opaque)7923 static Bool dis_branch ( UInt theInstr,
7924                          const VexAbiInfo* vbi,
7925                          /*OUT*/DisResult* dres,
7926                          Bool (*resteerOkFn)(void*,Addr),
7927                          void* callback_opaque )
7928 {
7929    UChar opc1    = ifieldOPC(theInstr);
7930    UChar BO      = ifieldRegDS(theInstr);
7931    UChar BI      = ifieldRegA(theInstr);
7932    UInt  BD_u16  = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */
7933    UChar b11to15 = ifieldRegB(theInstr);
7934    UInt  opc2    = ifieldOPClo10(theInstr);
7935    UInt  LI_u26  = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */
7936    UChar flag_AA = ifieldBIT1(theInstr);
7937    UChar flag_LK = ifieldBIT0(theInstr);
7938 
7939    IRType   ty        = mode64 ? Ity_I64 : Ity_I32;
7940    Addr64   tgt       = 0;
7941    UInt     BD        = extend_s_16to32(BD_u16);
7942    IRTemp   do_branch = newTemp(Ity_I32);
7943    IRTemp   ctr_ok    = newTemp(Ity_I32);
7944    IRTemp   cond_ok   = newTemp(Ity_I32);
7945    IRExpr*  e_nia     = mkSzImm(ty, nextInsnAddr());
7946    IRConst* c_nia     = mkSzConst(ty, nextInsnAddr());
7947    IRTemp   lr_old    = newTemp(ty);
7948 
7949    /* Hack to pass through code that just wants to read the PC */
7950    if (theInstr == 0x429F0005) {
7951       DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI);
7952       putGST( PPC_GST_LR, e_nia );
7953       return True;
7954    }
7955 
7956    /* The default what-next.  Individual cases can override it. */
7957    dres->whatNext = Dis_StopHere;
7958    vassert(dres->jk_StopHere == Ijk_INVALID);
7959 
7960    switch (opc1) {
7961    case 0x12: // b     (Branch, PPC32 p360)
7962       if (flag_AA) {
7963          tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) );
7964       } else {
7965          tgt = mkSzAddr( ty, guest_CIA_curr_instr +
7966                              (Long)extend_s_26to64(LI_u26) );
7967       }
7968       if (mode64) {
7969          DIP("b%s%s 0x%llx\n",
7970              flag_LK ? "l" : "", flag_AA ? "a" : "", tgt);
7971       } else {
7972          DIP("b%s%s 0x%x\n",
7973              flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt);
7974       }
7975 
7976       if (flag_LK) {
7977          putGST( PPC_GST_LR, e_nia );
7978          if (vbi->guest_ppc_zap_RZ_at_bl
7979              && vbi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) {
7980             IRTemp t_tgt = newTemp(ty);
7981             assign(t_tgt, mode64 ? mkU64(tgt) : mkU32(tgt) );
7982             make_redzone_AbiHint( vbi, t_tgt,
7983                                   "branch-and-link (unconditional call)" );
7984          }
7985       }
7986 
7987       if (resteerOkFn( callback_opaque, tgt )) {
7988          dres->whatNext   = Dis_ResteerU;
7989          dres->continueAt = tgt;
7990       } else {
7991          dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring; ;
7992          putGST( PPC_GST_CIA, mkSzImm(ty, tgt) );
7993       }
7994       break;
7995 
7996    case 0x10: // bc    (Branch Conditional, PPC32 p361)
7997       DIP("bc%s%s 0x%x, 0x%x, 0x%x\n",
7998           flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD);
7999 
8000       if (!(BO & 0x4)) {
8001          putGST( PPC_GST_CTR,
8002                  binop(mkSzOp(ty, Iop_Sub8),
8003                        getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
8004       }
8005 
8006       /* This is a bit subtle.  ctr_ok is either all 0s or all 1s.
8007          cond_ok is either zero or nonzero, since that's the cheapest
8008          way to compute it.  Anding them together gives a value which
8009          is either zero or non zero and so that's what we must test
8010          for in the IRStmt_Exit. */
8011       assign( ctr_ok,  branch_ctr_ok( BO ) );
8012       assign( cond_ok, branch_cond_ok( BO, BI ) );
8013       assign( do_branch,
8014               binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
8015 
8016       if (flag_AA) {
8017          tgt = mkSzAddr(ty, extend_s_16to64(BD_u16));
8018       } else {
8019          tgt = mkSzAddr(ty, guest_CIA_curr_instr +
8020                             (Long)extend_s_16to64(BD_u16));
8021       }
8022       if (flag_LK)
8023          putGST( PPC_GST_LR, e_nia );
8024 
8025       stmt( IRStmt_Exit(
8026                binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)),
8027                flag_LK ? Ijk_Call : Ijk_Boring,
8028                mkSzConst(ty, tgt), OFFB_CIA ) );
8029 
8030       dres->jk_StopHere = Ijk_Boring;
8031       putGST( PPC_GST_CIA, e_nia );
8032       break;
8033 
8034    case 0x13:
8035       /* For bclr and bcctr, it appears that the lowest two bits of
8036          b11to15 are a branch hint, and so we only need to ensure it's
8037          of the form 000XX. */
8038       if ((b11to15 & ~3) != 0) {
8039          vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", b11to15);
8040          return False;
8041       }
8042 
8043       switch (opc2) {
8044       case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363)
8045          if ((BO & 0x4) == 0) { // "decr and test CTR" option invalid
8046             vex_printf("dis_int_branch(ppc)(bcctr,BO)\n");
8047             return False;
8048          }
8049          DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
8050 
8051          assign( cond_ok, branch_cond_ok( BO, BI ) );
8052 
8053          /* FIXME: this is confusing.  lr_old holds the old value
8054             of ctr, not lr :-) */
8055          assign( lr_old, addr_align( getGST( PPC_GST_CTR ), 4 ));
8056 
8057          if (flag_LK)
8058             putGST( PPC_GST_LR, e_nia );
8059 
8060          stmt( IRStmt_Exit(
8061                   binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)),
8062                   Ijk_Boring,
8063                   c_nia, OFFB_CIA ));
8064 
8065          if (flag_LK && vbi->guest_ppc_zap_RZ_at_bl) {
8066             make_redzone_AbiHint( vbi, lr_old,
8067                                   "b-ctr-l (indirect call)" );
8068 	 }
8069 
8070          dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring;;
8071          putGST( PPC_GST_CIA, mkexpr(lr_old) );
8072          break;
8073 
8074       case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365)
8075          Bool vanilla_return = False;
8076          if ((BO & 0x14 /* 1z1zz */) == 0x14 && flag_LK == 0) {
8077             DIP("blr\n");
8078             vanilla_return = True;
8079          } else {
8080             DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
8081          }
8082 
8083          if (!(BO & 0x4)) {
8084             putGST( PPC_GST_CTR,
8085                     binop(mkSzOp(ty, Iop_Sub8),
8086                           getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
8087          }
8088 
8089          /* See comments above for 'bc' about this */
8090          assign( ctr_ok,  branch_ctr_ok( BO ) );
8091          assign( cond_ok, branch_cond_ok( BO, BI ) );
8092          assign( do_branch,
8093                  binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
8094 
8095          assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 ));
8096 
8097          if (flag_LK)
8098             putGST( PPC_GST_LR,  e_nia );
8099 
8100          stmt( IRStmt_Exit(
8101                   binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)),
8102                   Ijk_Boring,
8103                   c_nia, OFFB_CIA ));
8104 
8105          if (vanilla_return && vbi->guest_ppc_zap_RZ_at_blr) {
8106             make_redzone_AbiHint( vbi, lr_old,
8107                                   "branch-to-lr (unconditional return)" );
8108          }
8109 
8110          /* blrl is pretty strange; it's like a return that sets the
8111             return address of its caller to the insn following this
8112             one.  Mark it as a return. */
8113          dres->jk_StopHere = Ijk_Ret;  /* was flag_LK ? Ijk_Call : Ijk_Ret; */
8114          putGST( PPC_GST_CIA, mkexpr(lr_old) );
8115          break;
8116       }
8117       default:
8118          vex_printf("dis_int_branch(ppc)(opc2)\n");
8119          return False;
8120       }
8121       break;
8122 
8123    default:
8124       vex_printf("dis_int_branch(ppc)(opc1)\n");
8125       return False;
8126    }
8127 
8128    return True;
8129 }
8130 
8131 /*
8132  *  PC relative instruction
8133  */
dis_pc_relative(UInt theInstr)8134 static Bool dis_pc_relative ( UInt theInstr )
8135 {
8136    /* DX-Form */
8137    UChar opc1 = ifieldOPC(theInstr);
8138    unsigned long long D;
8139    UInt d0 = IFIELD(theInstr,  6, 10);
8140    UInt d1 = IFIELD(theInstr, 16,  5);
8141    UInt d2 = IFIELD(theInstr,  0,  1);
8142    UChar rT_addr = ifieldRegDS(theInstr);
8143    UInt  opc2    = ifieldOPClo5(theInstr);
8144    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
8145 
8146    if ( opc1 != 0x13) {
8147       vex_printf("dis_pc_relative(ppc)(opc1)\n");
8148       return False;
8149    }
8150 
8151    switch (opc2) {
8152    case 0x002:   // addpcis  (Add PC immediate Shifted DX-form)
8153       {
8154          IRExpr* nia     = mkSzImm(ty, nextInsnAddr());
8155          IRExpr* result;
8156 
8157          D = (d0 << 6) | (d1 << 1) | d2;
8158          DIP("addpcis %u,%llu\n", rT_addr, D);
8159 
8160          if ( (D & 0x8000) == 0x8000 )
8161             D = 0xFFFFFFFFFFFF0000UL | D;  // sign extend
8162 
8163          if ( ty == Ity_I32 ) {
8164             result = binop( Iop_Add32, nia, mkU32( D << 16 ) );
8165          } else {
8166             vassert( ty == Ity_I64 );
8167             result = binop( Iop_Add64, nia, mkU64( D << 16 ) );
8168          }
8169 
8170          putIReg( rT_addr, result);
8171       }
8172       break;
8173 
8174    default:
8175       vex_printf("dis_pc_relative(ppc)(opc2)\n");
8176       return False;
8177    }
8178 
8179    return True;
8180 }
8181 
8182 /*
8183   Condition Register Logical Instructions
8184  */
dis_cond_logic(UInt theInstr)8185 static Bool dis_cond_logic ( UInt theInstr )
8186 {
8187    /* XL-Form */
8188    UChar opc1      = ifieldOPC(theInstr);
8189    UChar crbD_addr = ifieldRegDS(theInstr);
8190    UChar crfD_addr = toUChar( IFIELD(theInstr, 23, 3) );
8191    UChar crbA_addr = ifieldRegA(theInstr);
8192    UChar crfS_addr = toUChar( IFIELD(theInstr, 18, 3) );
8193    UChar crbB_addr = ifieldRegB(theInstr);
8194    UInt  opc2      = ifieldOPClo10(theInstr);
8195    UChar b0        = ifieldBIT0(theInstr);
8196 
8197    IRTemp crbD     = newTemp(Ity_I32);
8198    IRTemp crbA     = newTemp(Ity_I32);
8199    IRTemp crbB     = newTemp(Ity_I32);
8200 
8201    if (opc1 != 19 || b0 != 0) {
8202       vex_printf("dis_cond_logic(ppc)(opc1)\n");
8203       return False;
8204    }
8205 
8206    if (opc2 == 0) {  // mcrf    (Move Cond Reg Field, PPC32 p464)
8207       if (((crbD_addr & 0x3) != 0) ||
8208           ((crbA_addr & 0x3) != 0) || (crbB_addr != 0)) {
8209          vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n");
8210          return False;
8211       }
8212       DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr);
8213       putCR0(   crfD_addr, getCR0(  crfS_addr) );
8214       putCR321( crfD_addr, getCR321(crfS_addr) );
8215    } else {
8216       assign( crbA, getCRbit(crbA_addr) );
8217       if (crbA_addr == crbB_addr)
8218          crbB = crbA;
8219       else
8220          assign( crbB, getCRbit(crbB_addr) );
8221 
8222       switch (opc2) {
8223       case 0x101: // crand   (Cond Reg AND, PPC32 p372)
8224          DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
8225          assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) );
8226          break;
8227       case 0x081: // crandc  (Cond Reg AND w. Complement, PPC32 p373)
8228          DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
8229          assign( crbD, binop(Iop_And32,
8230                              mkexpr(crbA),
8231                              unop(Iop_Not32, mkexpr(crbB))) );
8232          break;
8233       case 0x121: // creqv   (Cond Reg Equivalent, PPC32 p374)
8234          DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
8235          assign( crbD, unop(Iop_Not32,
8236                             binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) );
8237          break;
8238       case 0x0E1: // crnand  (Cond Reg NAND, PPC32 p375)
8239          DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
8240          assign( crbD, unop(Iop_Not32,
8241                             binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) );
8242          break;
8243       case 0x021: // crnor   (Cond Reg NOR, PPC32 p376)
8244          DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
8245          assign( crbD, unop(Iop_Not32,
8246                             binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) );
8247          break;
8248       case 0x1C1: // cror    (Cond Reg OR, PPC32 p377)
8249          DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
8250          assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) );
8251          break;
8252       case 0x1A1: // crorc   (Cond Reg OR w. Complement, PPC32 p378)
8253          DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
8254          assign( crbD, binop(Iop_Or32,
8255                              mkexpr(crbA),
8256                              unop(Iop_Not32, mkexpr(crbB))) );
8257          break;
8258       case 0x0C1: // crxor   (Cond Reg XOR, PPC32 p379)
8259          DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
8260          assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) );
8261          break;
8262       default:
8263          vex_printf("dis_cond_logic(ppc)(opc2)\n");
8264          return False;
8265       }
8266 
8267       putCRbit( crbD_addr, mkexpr(crbD) );
8268    }
8269    return True;
8270 }
8271 
8272 
8273 /*
8274   Trap instructions
8275 */
8276 
8277 /* Do the code generation for a trap.  Returned Bool is true iff
8278    this is an unconditional trap.  If the two arg IRExpr*s are
8279    Ity_I32s then the comparison is 32-bit.  If they are Ity_I64s
8280    then they are 64-bit, and we must be disassembling 64-bit
8281    instructions. */
do_trap(UChar TO,IRExpr * argL0,IRExpr * argR0,Addr64 cia)8282 static Bool do_trap ( UChar TO,
8283                       IRExpr* argL0, IRExpr* argR0, Addr64 cia )
8284 {
8285    IRTemp argL, argR;
8286    IRExpr *argLe, *argRe, *cond, *tmp;
8287 
8288    Bool    is32bit = typeOfIRExpr(irsb->tyenv, argL0 ) == Ity_I32;
8289 
8290    IROp    opAND     = is32bit ? Iop_And32     : Iop_And64;
8291    IROp    opOR      = is32bit ? Iop_Or32      : Iop_Or64;
8292    IROp    opCMPORDS = is32bit ? Iop_CmpORD32S : Iop_CmpORD64S;
8293    IROp    opCMPORDU = is32bit ? Iop_CmpORD32U : Iop_CmpORD64U;
8294    IROp    opCMPNE   = is32bit ? Iop_CmpNE32   : Iop_CmpNE64;
8295    IROp    opCMPEQ   = is32bit ? Iop_CmpEQ32   : Iop_CmpEQ64;
8296    IRExpr* const0    = is32bit ? mkU32(0)      : mkU64(0);
8297    IRExpr* const2    = is32bit ? mkU32(2)      : mkU64(2);
8298    IRExpr* const4    = is32bit ? mkU32(4)      : mkU64(4);
8299    IRExpr* const8    = is32bit ? mkU32(8)      : mkU64(8);
8300 
8301    const UChar b11100 = 0x1C;
8302    const UChar b00111 = 0x07;
8303 
8304    if (is32bit) {
8305       vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 );
8306       vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 );
8307    } else {
8308       vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 );
8309       vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 );
8310       vassert( mode64 );
8311    }
8312 
8313    if ((TO & b11100) == b11100 || (TO & b00111) == b00111) {
8314       /* Unconditional trap.  Just do the exit without
8315          testing the arguments. */
8316       stmt( IRStmt_Exit(
8317                binop(opCMPEQ, const0, const0),
8318                Ijk_SigTRAP,
8319                mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia),
8320                OFFB_CIA
8321       ));
8322       return True; /* unconditional trap */
8323    }
8324 
8325    if (is32bit) {
8326       argL = newTemp(Ity_I32);
8327       argR = newTemp(Ity_I32);
8328    } else {
8329       argL = newTemp(Ity_I64);
8330       argR = newTemp(Ity_I64);
8331    }
8332 
8333    assign( argL, argL0 );
8334    assign( argR, argR0 );
8335 
8336    argLe = mkexpr(argL);
8337    argRe = mkexpr(argR);
8338 
8339    cond = const0;
8340    if (TO & 16) { // L <s R
8341       tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const8);
8342       cond = binop(opOR, tmp, cond);
8343    }
8344    if (TO & 8) { // L >s R
8345       tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4);
8346       cond = binop(opOR, tmp, cond);
8347    }
8348    if (TO & 4) { // L == R
8349       tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2);
8350       cond = binop(opOR, tmp, cond);
8351    }
8352    if (TO & 2) { // L <u R
8353       tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const8);
8354       cond = binop(opOR, tmp, cond);
8355    }
8356    if (TO & 1) { // L >u R
8357       tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4);
8358       cond = binop(opOR, tmp, cond);
8359    }
8360    stmt( IRStmt_Exit(
8361             binop(opCMPNE, cond, const0),
8362             Ijk_SigTRAP,
8363             mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia),
8364             OFFB_CIA
8365    ));
8366    return False; /* not an unconditional trap */
8367 }
8368 
dis_trapi(UInt theInstr,DisResult * dres)8369 static Bool dis_trapi ( UInt theInstr,
8370                         /*OUT*/DisResult* dres )
8371 {
8372    /* D-Form */
8373    UChar  opc1    = ifieldOPC(theInstr);
8374    UChar  TO      = ifieldRegDS(theInstr);
8375    UChar  rA_addr = ifieldRegA(theInstr);
8376    UInt   uimm16  = ifieldUIMM16(theInstr);
8377    ULong  simm16  = extend_s_16to64(uimm16);
8378    Addr64 cia     = guest_CIA_curr_instr;
8379    IRType ty      = mode64 ? Ity_I64 : Ity_I32;
8380    Bool   uncond  = False;
8381 
8382    switch (opc1) {
8383    case 0x03: // twi  (Trap Word Immediate, PPC32 p548)
8384       uncond = do_trap( TO,
8385                         mode64 ? unop(Iop_64to32, getIReg(rA_addr))
8386                                : getIReg(rA_addr),
8387                         mkU32( (UInt)simm16 ),
8388                         cia );
8389       if (TO == 4) {
8390          DIP("tweqi r%u,%d\n", rA_addr, (Int)simm16);
8391       } else {
8392          DIP("tw%di r%u,%d\n", TO, rA_addr, (Int)simm16);
8393       }
8394       break;
8395    case 0x02: // tdi
8396       if (!mode64)
8397          return False;
8398       uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia );
8399       if (TO == 4) {
8400          DIP("tdeqi r%u,%d\n", rA_addr, (Int)simm16);
8401       } else {
8402          DIP("td%di r%u,%d\n", TO, rA_addr, (Int)simm16);
8403       }
8404       break;
8405    default:
8406       return False;
8407    }
8408 
8409    if (uncond) {
8410       /* If the trap shows signs of being unconditional, don't
8411          continue decoding past it. */
8412       putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
8413       dres->jk_StopHere = Ijk_Boring;
8414       dres->whatNext    = Dis_StopHere;
8415    }
8416 
8417    return True;
8418 }
8419 
dis_trap(UInt theInstr,DisResult * dres)8420 static Bool dis_trap ( UInt theInstr,
8421                         /*OUT*/DisResult* dres )
8422 {
8423    /* X-Form */
8424    UInt   opc2    = ifieldOPClo10(theInstr);
8425    UChar  TO      = ifieldRegDS(theInstr);
8426    UChar  rA_addr = ifieldRegA(theInstr);
8427    UChar  rB_addr = ifieldRegB(theInstr);
8428    Addr64 cia     = guest_CIA_curr_instr;
8429    IRType ty      = mode64 ? Ity_I64 : Ity_I32;
8430    Bool   uncond  = False;
8431 
8432    if (ifieldBIT0(theInstr) != 0)
8433       return False;
8434 
8435    switch (opc2) {
8436    case 0x004: // tw  (Trap Word, PPC64 p540)
8437       uncond = do_trap( TO,
8438                         mode64 ? unop(Iop_64to32, getIReg(rA_addr))
8439                                : getIReg(rA_addr),
8440                         mode64 ? unop(Iop_64to32, getIReg(rB_addr))
8441                                : getIReg(rB_addr),
8442                         cia );
8443       if (TO == 4) {
8444          DIP("tweq r%u,r%u\n", rA_addr, rB_addr);
8445       } else {
8446          DIP("tw%d r%u,r%u\n", TO, rA_addr, rB_addr);
8447       }
8448       break;
8449    case 0x044: // td (Trap Doubleword, PPC64 p534)
8450       if (!mode64)
8451          return False;
8452       uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia );
8453       if (TO == 4) {
8454          DIP("tdeq r%u,r%u\n", rA_addr, rB_addr);
8455       } else {
8456          DIP("td%d r%u,r%u\n", TO, rA_addr, rB_addr);
8457       }
8458       break;
8459    default:
8460       return False;
8461    }
8462 
8463    if (uncond) {
8464       /* If the trap shows signs of being unconditional, don't
8465          continue decoding past it. */
8466       putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
8467       dres->jk_StopHere = Ijk_Boring;
8468       dres->whatNext    = Dis_StopHere;
8469    }
8470 
8471    return True;
8472 }
8473 
8474 
8475 /*
8476   System Linkage Instructions
8477 */
dis_syslink(UInt theInstr,const VexAbiInfo * abiinfo,DisResult * dres)8478 static Bool dis_syslink ( UInt theInstr,
8479                           const VexAbiInfo* abiinfo, DisResult* dres )
8480 {
8481    IRType ty = mode64 ? Ity_I64 : Ity_I32;
8482 
8483    if (theInstr != 0x44000002) {
8484       vex_printf("dis_syslink(ppc)(theInstr)\n");
8485       return False;
8486    }
8487 
8488    // sc  (System Call, PPC32 p504)
8489    DIP("sc\n");
8490 
8491    /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on Darwin
8492       Valgrind can back the guest up to this instruction if it needs
8493       to restart the syscall. */
8494    putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) );
8495 
8496    /* It's important that all ArchRegs carry their up-to-date value
8497       at this point.  So we declare an end-of-block here, which
8498       forces any TempRegs caching ArchRegs to be flushed. */
8499    putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
8500 
8501    dres->whatNext    = Dis_StopHere;
8502    dres->jk_StopHere = Ijk_Sys_syscall;
8503    return True;
8504 }
8505 
8506 
8507 /*
8508   Memory Synchronization Instructions
8509 
8510   Note on Reservations:
8511   We rely on the assumption that V will in fact only allow one thread at
8512   once to run.  In effect, a thread can make a reservation, but we don't
8513   check any stores it does.  Instead, the reservation is cancelled when
8514   the scheduler switches to another thread (run_thread_for_a_while()).
8515 */
dis_memsync(UInt theInstr)8516 static Bool dis_memsync ( UInt theInstr )
8517 {
8518    /* X-Form, XL-Form */
8519    UChar opc1    = ifieldOPC(theInstr);
8520    UInt  b11to25 = IFIELD(theInstr, 11, 15);
8521    UChar flag_L  = ifieldRegDS(theInstr);
8522    UInt  b11to20 = IFIELD(theInstr, 11, 10);
8523    UInt  M0      = IFIELD(theInstr, 11, 5);
8524    UChar rD_addr = ifieldRegDS(theInstr);
8525    UChar rS_addr = rD_addr;
8526    UChar rA_addr = ifieldRegA(theInstr);
8527    UChar rB_addr = ifieldRegB(theInstr);
8528    UInt  opc2    = ifieldOPClo10(theInstr);
8529    UChar b0      = ifieldBIT0(theInstr);
8530 
8531    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
8532    IRTemp EA     = newTemp(ty);
8533 
8534    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
8535 
8536    switch (opc1) {
8537    /* XL-Form */
8538    case 0x13:   // isync (Instruction Synchronize, PPC32 p432)
8539       if (opc2 != 0x096) {
8540          vex_printf("dis_memsync(ppc)(0x13,opc2)\n");
8541          return False;
8542       }
8543       if (b11to25 != 0 || b0 != 0) {
8544          vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n");
8545          return False;
8546       }
8547       DIP("isync\n");
8548       stmt( IRStmt_MBE(Imbe_Fence) );
8549       break;
8550 
8551    /* X-Form */
8552    case 0x1F:
8553       switch (opc2) {
8554       case 0x356: // eieio or mbar (Enforce In-Order Exec of I/O, PPC32 p394)
8555          if (M0 == 0) {
8556             if (b11to20 != 0 || b0 != 0) {
8557                vex_printf("dis_memsync(ppc)(eieio,b11to20|b0)\n");
8558                return False;
8559             }
8560             DIP("eieio\n");
8561          } else {
8562             if (b11to20 != 0 || b0 != 0) {
8563                vex_printf("dis_memsync(ppc)(mbar,b11to20|b0)\n");
8564                return False;
8565             }
8566             DIP("mbar %d\n", M0);
8567          }
8568          /* Insert a memory fence, just to be on the safe side. */
8569          stmt( IRStmt_MBE(Imbe_Fence) );
8570          break;
8571 
8572       case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458)
8573          IRTemp res;
8574          /* According to the PowerPC ISA version 2.05, b0 (called EH
8575             in the documentation) is merely a hint bit to the
8576             hardware, I think as to whether or not contention is
8577             likely.  So we can just ignore it. */
8578          DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
8579 
8580          // trap if misaligned
8581          gen_SIGBUS_if_misaligned( EA, 4 );
8582 
8583          // and actually do the load
8584          res = newTemp(Ity_I32);
8585          stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) );
8586 
8587          putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) );
8588          break;
8589       }
8590 
8591       case 0x034: { // lbarx (Load Word and Reserve Indexed)
8592          IRTemp res;
8593          /* According to the PowerPC ISA version 2.05, b0 (called EH
8594             in the documentation) is merely a hint bit to the
8595             hardware, I think as to whether or not contention is
8596             likely.  So we can just ignore it. */
8597          DIP("lbarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
8598 
8599          // and actually do the load
8600          res = newTemp(Ity_I8);
8601          stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) );
8602 
8603          putIReg( rD_addr, mkWidenFrom8(ty, mkexpr(res), False) );
8604          break;
8605      }
8606 
8607       case 0x074: { // lharx (Load Word and Reserve Indexed)
8608          IRTemp res;
8609          /* According to the PowerPC ISA version 2.05, b0 (called EH
8610             in the documentation) is merely a hint bit to the
8611             hardware, I think as to whether or not contention is
8612             likely.  So we can just ignore it. */
8613          DIP("lharx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
8614 
8615          // trap if misaligned
8616          gen_SIGBUS_if_misaligned( EA, 2 );
8617 
8618          // and actually do the load
8619          res = newTemp(Ity_I16);
8620          stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) );
8621 
8622          putIReg( rD_addr, mkWidenFrom16(ty, mkexpr(res), False) );
8623          break;
8624       }
8625 
8626       case 0x096: {
8627          // stwcx. (Store Word Conditional Indexed, PPC32 p532)
8628          // Note this has to handle stwcx. in both 32- and 64-bit modes,
8629          // so isn't quite as straightforward as it might otherwise be.
8630          IRTemp rS = newTemp(Ity_I32);
8631          IRTemp resSC;
8632          if (b0 != 1) {
8633             vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
8634             return False;
8635          }
8636          DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
8637 
8638          // trap if misaligned
8639          gen_SIGBUS_if_misaligned( EA, 4 );
8640 
8641          // Get the data to be stored, and narrow to 32 bits if necessary
8642          assign( rS, mkNarrowTo32(ty, getIReg(rS_addr)) );
8643 
8644          // Do the store, and get success/failure bit into resSC
8645          resSC = newTemp(Ity_I1);
8646          stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
8647 
8648          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
8649          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
8650          putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
8651          putCR0(0, getXER_SO());
8652 
8653          /* Note:
8654             If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
8655             whether rS is stored is dependent on that value. */
8656          /* So I guess we can just ignore this case? */
8657          break;
8658       }
8659 
8660       case 0x2B6: {
8661          // stbcx. (Store Byte Conditional Indexed)
8662          // Note this has to handle stbcx. in both 32- and 64-bit modes,
8663          // so isn't quite as straightforward as it might otherwise be.
8664          IRTemp rS = newTemp(Ity_I8);
8665          IRTemp resSC;
8666          if (b0 != 1) {
8667             vex_printf("dis_memsync(ppc)(stbcx.,b0)\n");
8668             return False;
8669          }
8670          DIP("stbcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
8671 
8672          // Get the data to be stored, and narrow to 32 bits if necessary
8673          assign( rS, mkNarrowTo8(ty, getIReg(rS_addr)) );
8674 
8675          // Do the store, and get success/failure bit into resSC
8676          resSC = newTemp(Ity_I1);
8677          stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
8678 
8679          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
8680          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
8681          putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
8682          putCR0(0, getXER_SO());
8683 
8684          /* Note:
8685             If resaddr != lbarx_resaddr, CR0[EQ] is undefined, and
8686             whether rS is stored is dependent on that value. */
8687          /* So I guess we can just ignore this case? */
8688          break;
8689       }
8690 
8691       case 0x2D6: {
8692          // sthcx. (Store Word Conditional Indexed, PPC32 p532)
8693          // Note this has to handle sthcx. in both 32- and 64-bit modes,
8694          // so isn't quite as straightforward as it might otherwise be.
8695          IRTemp rS = newTemp(Ity_I16);
8696          IRTemp resSC;
8697          if (b0 != 1) {
8698             vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
8699             return False;
8700          }
8701          DIP("sthcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
8702 
8703          // trap if misaligned
8704          gen_SIGBUS_if_misaligned( EA, 2 );
8705 
8706          // Get the data to be stored, and narrow to 16 bits if necessary
8707          assign( rS, mkNarrowTo16(ty, getIReg(rS_addr)) );
8708 
8709          // Do the store, and get success/failure bit into resSC
8710          resSC = newTemp(Ity_I1);
8711          stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
8712 
8713          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
8714          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
8715          putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
8716          putCR0(0, getXER_SO());
8717 
8718          /* Note:
8719             If resaddr != lharx_resaddr, CR0[EQ] is undefined, and
8720             whether rS is stored is dependent on that value. */
8721          /* So I guess we can just ignore this case? */
8722          break;
8723       }
8724 
8725       case 0x256: // sync (Synchronize, PPC32 p543),
8726                   // also lwsync (L==1), ptesync (L==2)
8727          /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html
8728 
8729             The PowerPC architecture used in IBM chips has expanded
8730             the sync instruction into two variants: lightweight sync
8731             and heavyweight sync.  The original sync instruction is
8732             the new heavyweight sync and lightweight sync is a strict
8733             subset of the heavyweight sync functionality. This allows
8734             the programmer to specify a less expensive operation on
8735             high-end systems when the full sync functionality is not
8736             necessary.
8737 
8738             The basic "sync" mnemonic now utilizes an operand. "sync"
8739             without an operand now becomes a extended mnemonic for
8740             heavyweight sync.  Processors without the lwsync
8741             instruction will not decode the L field and will perform a
8742             heavyweight sync.  Everything is backward compatible.
8743 
8744             sync    =       sync 0
8745             lwsync  =       sync 1
8746             ptesync =       sync 2    *** TODO - not implemented ***
8747          */
8748          if (b11to20 != 0 || b0 != 0) {
8749             vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n");
8750             return False;
8751          }
8752          if (flag_L != 0/*sync*/ && flag_L != 1/*lwsync*/) {
8753             vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n");
8754             return False;
8755          }
8756          DIP("%ssync\n", flag_L == 1 ? "lw" : "");
8757          /* Insert a memory fence.  It's sometimes important that these
8758             are carried through to the generated code. */
8759          stmt( IRStmt_MBE(Imbe_Fence) );
8760          break;
8761 
8762       /* 64bit Memsync */
8763       case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473)
8764          IRTemp res;
8765          /* According to the PowerPC ISA version 2.05, b0 (called EH
8766             in the documentation) is merely a hint bit to the
8767             hardware, I think as to whether or not contention is
8768             likely.  So we can just ignore it. */
8769          if (!mode64)
8770             return False;
8771          DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
8772 
8773          // trap if misaligned
8774          gen_SIGBUS_if_misaligned( EA, 8 );
8775 
8776          // and actually do the load
8777          res = newTemp(Ity_I64);
8778          stmt( stmt_load( res, mkexpr(EA), NULL/*this is a load*/) );
8779 
8780          putIReg( rD_addr, mkexpr(res) );
8781          break;
8782       }
8783 
8784       case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581)
8785          // A marginally simplified version of the stwcx. case
8786          IRTemp rS = newTemp(Ity_I64);
8787          IRTemp resSC;
8788          if (b0 != 1) {
8789             vex_printf("dis_memsync(ppc)(stdcx.,b0)\n");
8790             return False;
8791          }
8792          if (!mode64)
8793             return False;
8794          DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
8795 
8796          // trap if misaligned
8797          gen_SIGBUS_if_misaligned( EA, 8 );
8798 
8799          // Get the data to be stored
8800          assign( rS, getIReg(rS_addr) );
8801 
8802          // Do the store, and get success/failure bit into resSC
8803          resSC = newTemp(Ity_I1);
8804          stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
8805 
8806          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
8807          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
8808          putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
8809          putCR0(0, getXER_SO());
8810 
8811          /* Note:
8812             If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
8813             whether rS is stored is dependent on that value. */
8814          /* So I guess we can just ignore this case? */
8815          break;
8816       }
8817 
8818       /* 128bit Memsync */
8819       case 0x114: { // lqarx (Load QuadWord and Reserve Indexed)
8820          IRTemp res_hi = newTemp(ty);
8821          IRTemp res_lo = newTemp(ty);
8822 
8823          /* According to the PowerPC ISA version 2.07, b0 (called EH
8824             in the documentation) is merely a hint bit to the
8825             hardware, I think as to whether or not contention is
8826             likely.  So we can just ignore it. */
8827          DIP("lqarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
8828 
8829          // trap if misaligned
8830          gen_SIGBUS_if_misaligned( EA, 16 );
8831 
8832          // and actually do the load
8833          if (mode64) {
8834             if (host_endness == VexEndnessBE) {
8835                stmt( stmt_load( res_hi,
8836                                 mkexpr(EA), NULL/*this is a load*/) );
8837                stmt( stmt_load( res_lo,
8838                                 binop(Iop_Add64, mkexpr(EA), mkU64(8) ),
8839                                 NULL/*this is a load*/) );
8840 	    } else {
8841                stmt( stmt_load( res_lo,
8842                                 mkexpr(EA), NULL/*this is a load*/) );
8843                stmt( stmt_load( res_hi,
8844                                 binop(Iop_Add64, mkexpr(EA), mkU64(8) ),
8845                                 NULL/*this is a load*/) );
8846             }
8847          } else {
8848             stmt( stmt_load( res_hi,
8849                              binop( Iop_Add32, mkexpr(EA), mkU32(4) ),
8850                              NULL/*this is a load*/) );
8851             stmt( stmt_load( res_lo,
8852                              binop( Iop_Add32, mkexpr(EA), mkU32(12) ),
8853                              NULL/*this is a load*/) );
8854          }
8855          putIReg( rD_addr,   mkexpr(res_hi) );
8856          putIReg( rD_addr+1, mkexpr(res_lo) );
8857          break;
8858       }
8859 
8860       case 0x0B6: { // stqcx. (Store QuadWord Condition Indexd, PPC64)
8861          // A marginally simplified version of the stwcx. case
8862          IRTemp rS_hi = newTemp(ty);
8863          IRTemp rS_lo = newTemp(ty);
8864          IRTemp resSC;
8865          if (b0 != 1) {
8866             vex_printf("dis_memsync(ppc)(stqcx.,b0)\n");
8867             return False;
8868          }
8869 
8870          DIP("stqcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
8871 
8872          // trap if misaligned
8873          gen_SIGBUS_if_misaligned( EA, 16 );
8874          // Get the data to be stored
8875          assign( rS_hi, getIReg(rS_addr) );
8876          assign( rS_lo, getIReg(rS_addr+1) );
8877 
8878          // Do the store, and get success/failure bit into resSC
8879          resSC = newTemp(Ity_I1);
8880 
8881          if (mode64) {
8882             if (host_endness == VexEndnessBE) {
8883                stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_hi) ) );
8884                store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ),
8885                       mkexpr(rS_lo) );
8886 	    } else {
8887                stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_lo) ) );
8888                store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ),
8889                       mkexpr(rS_hi) );
8890 	    }
8891          } else {
8892             stmt( stmt_load( resSC, binop( Iop_Add32,
8893                                            mkexpr(EA),
8894                                            mkU32(4) ),
8895                                            mkexpr(rS_hi) ) );
8896             store( binop(Iop_Add32, mkexpr(EA), mkU32(12) ), mkexpr(rS_lo) );
8897          }
8898 
8899          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
8900          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
8901          putCR321(0, binop( Iop_Shl8,
8902                             unop(Iop_1Uto8, mkexpr(resSC) ),
8903                             mkU8(1)));
8904          putCR0(0, getXER_SO());
8905          break;
8906       }
8907 
8908       default:
8909          vex_printf("dis_memsync(ppc)(opc2)\n");
8910          return False;
8911       }
8912       break;
8913 
8914    default:
8915       vex_printf("dis_memsync(ppc)(opc1)\n");
8916       return False;
8917    }
8918    return True;
8919 }
8920 
8921 
8922 
8923 /*
8924   Integer Shift Instructions
8925 */
dis_int_shift(UInt theInstr)8926 static Bool dis_int_shift ( UInt theInstr )
8927 {
8928    /* X-Form, XS-Form */
8929    UChar opc1    = ifieldOPC(theInstr);
8930    UChar rS_addr = ifieldRegDS(theInstr);
8931    UChar rA_addr = ifieldRegA(theInstr);
8932    UChar rB_addr = ifieldRegB(theInstr);
8933    UChar sh_imm  = rB_addr;
8934    UInt  opc2    = ifieldOPClo10(theInstr);
8935    UChar b1      = ifieldBIT1(theInstr);
8936    UChar flag_rC = ifieldBIT0(theInstr);
8937 
8938    IRType  ty         = mode64 ? Ity_I64 : Ity_I32;
8939    IRTemp  rA         = newTemp(ty);
8940    IRTemp  rS         = newTemp(ty);
8941    IRTemp  rB         = newTemp(ty);
8942    IRTemp  outofrange = newTemp(Ity_I1);
8943    IRTemp  rS_lo32    = newTemp(Ity_I32);
8944    IRTemp  rB_lo32    = newTemp(Ity_I32);
8945    IRExpr* e_tmp;
8946 
8947    assign( rS, getIReg(rS_addr) );
8948    assign( rB, getIReg(rB_addr) );
8949    assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) );
8950    assign( rB_lo32, mkNarrowTo32(ty, mkexpr(rB)) );
8951 
8952    if (opc1 == 0x1F) {
8953       switch (opc2) {
8954       case 0x018: { // slw (Shift Left Word, PPC32 p505)
8955          DIP("slw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
8956              rA_addr, rS_addr, rB_addr);
8957          /* rA = rS << rB */
8958          /* ppc32 semantics are:
8959             slw(x,y) = (x << (y & 31))         -- primary result
8960                        & ~((y << 26) >>s 31)   -- make result 0
8961                                                   for y in 32 .. 63
8962          */
8963          e_tmp =
8964             binop( Iop_And32,
8965                binop( Iop_Shl32,
8966                       mkexpr(rS_lo32),
8967                       unop( Iop_32to8,
8968                             binop(Iop_And32,
8969                                   mkexpr(rB_lo32), mkU32(31)))),
8970                unop( Iop_Not32,
8971                      binop( Iop_Sar32,
8972                             binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)),
8973                             mkU8(31))) );
8974          assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
8975          break;
8976       }
8977 
8978       case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506)
8979          IRTemp sh_amt = newTemp(Ity_I32);
8980          DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
8981              rA_addr, rS_addr, rB_addr);
8982          /* JRS: my reading of the (poorly worded) PPC32 doc p506 is:
8983             amt = rB & 63
8984             rA = Sar32( rS, amt > 31 ? 31 : amt )
8985             XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi)
8986          */
8987          assign( sh_amt, binop(Iop_And32, mkU32(0x3F),
8988                                           mkexpr(rB_lo32)) );
8989          assign( outofrange,
8990                  binop(Iop_CmpLT32U, mkU32(31), mkexpr(sh_amt)) );
8991          e_tmp = binop( Iop_Sar32,
8992                         mkexpr(rS_lo32),
8993                         unop( Iop_32to8,
8994                               IRExpr_ITE( mkexpr(outofrange),
8995                                           mkU32(31),
8996                                           mkexpr(sh_amt)) ) );
8997          assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) );
8998 
8999          set_XER_CA_CA32( ty, PPCG_FLAG_OP_SRAW,
9000                           mkexpr(rA),
9001                           mkWidenFrom32(ty, mkexpr(rS_lo32), True),
9002                           mkWidenFrom32(ty, mkexpr(sh_amt), True ),
9003                           mkWidenFrom32(ty, getXER_CA_32(), True) );
9004          break;
9005       }
9006 
9007       case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507)
9008          DIP("srawi%s r%u,r%u,%d\n", flag_rC ? ".":"",
9009              rA_addr, rS_addr, sh_imm);
9010          vassert(sh_imm < 32);
9011          if (mode64) {
9012             assign( rA, binop(Iop_Sar64,
9013                               binop(Iop_Shl64, getIReg(rS_addr),
9014                                                mkU8(32)),
9015                               mkU8(32 + sh_imm)) );
9016          } else {
9017             assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32),
9018                                          mkU8(sh_imm)) );
9019          }
9020 
9021          set_XER_CA_CA32( ty, PPCG_FLAG_OP_SRAWI,
9022                           mkexpr(rA),
9023                           mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True),
9024                           mkSzImm(ty, sh_imm),
9025                           mkWidenFrom32(ty, getXER_CA_32(), /* Syned */False) );
9026          break;
9027 
9028       case 0x218: // srw (Shift Right Word, PPC32 p508)
9029          DIP("srw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
9030              rA_addr, rS_addr, rB_addr);
9031          /* rA = rS >>u rB */
9032          /* ppc32 semantics are:
9033             srw(x,y) = (x >>u (y & 31))        -- primary result
9034                        & ~((y << 26) >>s 31)   -- make result 0
9035                                                   for y in 32 .. 63
9036          */
9037          e_tmp =
9038             binop(
9039                Iop_And32,
9040                binop( Iop_Shr32,
9041                       mkexpr(rS_lo32),
9042                       unop( Iop_32to8,
9043                             binop(Iop_And32, mkexpr(rB_lo32),
9044                                              mkU32(31)))),
9045                unop( Iop_Not32,
9046                      binop( Iop_Sar32,
9047                             binop(Iop_Shl32, mkexpr(rB_lo32),
9048                                              mkU8(26)),
9049                             mkU8(31))));
9050          assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
9051          break;
9052 
9053 
9054       /* 64bit Shifts */
9055       case 0x01B: // sld (Shift Left DWord, PPC64 p568)
9056          DIP("sld%s r%u,r%u,r%u\n",
9057              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
9058          /* rA = rS << rB */
9059          /* ppc64 semantics are:
9060             slw(x,y) = (x << (y & 63))         -- primary result
9061                        & ~((y << 57) >>s 63)   -- make result 0
9062                                                   for y in 64 ..
9063          */
9064          assign( rA,
9065             binop(
9066                Iop_And64,
9067                binop( Iop_Shl64,
9068                       mkexpr(rS),
9069                       unop( Iop_64to8,
9070                             binop(Iop_And64, mkexpr(rB), mkU64(63)))),
9071                unop( Iop_Not64,
9072                      binop( Iop_Sar64,
9073                             binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
9074                             mkU8(63)))) );
9075          break;
9076 
9077       case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570)
9078          IRTemp sh_amt = newTemp(Ity_I64);
9079          DIP("srad%s r%u,r%u,r%u\n",
9080              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
9081          /* amt = rB & 127
9082             rA = Sar64( rS, amt > 63 ? 63 : amt )
9083             XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi)
9084          */
9085          assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) );
9086          assign( outofrange,
9087                  binop(Iop_CmpLT64U, mkU64(63), mkexpr(sh_amt)) );
9088          assign( rA,
9089                  binop( Iop_Sar64,
9090                         mkexpr(rS),
9091                         unop( Iop_64to8,
9092                               IRExpr_ITE( mkexpr(outofrange),
9093                                           mkU64(63),
9094                                           mkexpr(sh_amt)) ))
9095                );
9096          set_XER_CA_CA32( ty, PPCG_FLAG_OP_SRAD,
9097                           mkexpr(rA), mkexpr(rS), mkexpr(sh_amt),
9098                           mkWidenFrom32(ty, getXER_CA_32(), /* Syned */False) );
9099          break;
9100       }
9101 
9102       case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571)
9103          sh_imm |= b1<<5;
9104          vassert(sh_imm < 64);
9105          DIP("sradi%s r%u,r%u,%u\n",
9106              flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
9107          assign( rA, binop(Iop_Sar64, getIReg(rS_addr), mkU8(sh_imm)) );
9108 
9109          set_XER_CA_CA32( ty, PPCG_FLAG_OP_SRADI,
9110                           mkexpr(rA),
9111                           getIReg(rS_addr),
9112                           mkU64(sh_imm),
9113                           mkWidenFrom32(ty, getXER_CA_32(), /* Syned */False) );
9114          break;
9115 
9116       case 0x21B: // srd (Shift Right DWord, PPC64 p574)
9117          DIP("srd%s r%u,r%u,r%u\n",
9118              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
9119          /* rA = rS >>u rB */
9120          /* ppc semantics are:
9121             srw(x,y) = (x >>u (y & 63))        -- primary result
9122                        & ~((y << 57) >>s 63)   -- make result 0
9123                                                   for y in 64 .. 127
9124          */
9125          assign( rA,
9126             binop(
9127                Iop_And64,
9128                binop( Iop_Shr64,
9129                       mkexpr(rS),
9130                       unop( Iop_64to8,
9131                             binop(Iop_And64, mkexpr(rB), mkU64(63)))),
9132                unop( Iop_Not64,
9133                      binop( Iop_Sar64,
9134                             binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
9135                             mkU8(63)))) );
9136          break;
9137 
9138       default:
9139          vex_printf("dis_int_shift(ppc)(opc2)\n");
9140          return False;
9141       }
9142    } else {
9143       vex_printf("dis_int_shift(ppc)(opc1)\n");
9144       return False;
9145    }
9146 
9147    putIReg( rA_addr, mkexpr(rA) );
9148 
9149    if (flag_rC) {
9150       set_CR0( mkexpr(rA) );
9151    }
9152    return True;
9153 }
9154 
9155 
9156 
9157 /*
9158   Integer Load/Store Reverse Instructions
9159 */
9160 /* Generates code to swap the byte order in an Ity_I32. */
gen_byterev32(IRTemp t)9161 static IRExpr* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t )
9162 {
9163    vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
9164    return unop(Iop_Reverse8sIn32_x1, mkexpr(t));
9165 }
9166 
9167 /* Generates code to swap the byte order in the lower half of an Ity_I32,
9168    and zeroes the upper half. */
gen_byterev16(IRTemp t)9169 static IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t )
9170 {
9171    vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
9172    return
9173       binop(Iop_Or32,
9174          binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
9175                           mkU32(0x0000FF00)),
9176          binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
9177                           mkU32(0x000000FF))
9178       );
9179 }
9180 
dis_int_ldst_rev(UInt theInstr)9181 static Bool dis_int_ldst_rev ( UInt theInstr )
9182 {
9183    /* X-Form */
9184    UChar opc1    = ifieldOPC(theInstr);
9185    UChar rD_addr = ifieldRegDS(theInstr);
9186    UChar rS_addr = rD_addr;
9187    UChar rA_addr = ifieldRegA(theInstr);
9188    UChar rB_addr = ifieldRegB(theInstr);
9189    UInt  opc2    = ifieldOPClo10(theInstr);
9190    UChar b0      = ifieldBIT0(theInstr);
9191 
9192    IRType ty = mode64 ? Ity_I64 : Ity_I32;
9193    IRTemp EA = newTemp(ty);
9194    IRTemp w1 = newTemp(Ity_I32);
9195    IRTemp w2 = newTemp(Ity_I32);
9196 
9197    if (opc1 != 0x1F || b0 != 0) {
9198       vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n");
9199       return False;
9200    }
9201 
9202    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
9203 
9204    switch (opc2) {
9205 
9206       case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449)
9207          DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
9208          assign( w1, unop(Iop_16Uto32, load(Ity_I16, mkexpr(EA))) );
9209          assign( w2, gen_byterev16(w1) );
9210          putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
9211                                          /* Signed */False) );
9212          break;
9213 
9214       case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459)
9215          DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
9216          assign( w1, load(Ity_I32, mkexpr(EA)) );
9217          assign( w2, gen_byterev32(w1) );
9218          putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
9219                                          /* Signed */False) );
9220          break;
9221 
9222       case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed)
9223       {
9224          /* Caller makes sure we are only called in mode64. */
9225 
9226          /* If we supported swapping LE/BE loads in the backend then we could
9227             just load the value with the bytes reversed by doing a BE load
9228             on an LE machine and a LE load on a BE machine.
9229 
9230                IRTemp dw1 = newTemp(Ity_I64);
9231                if (host_endness == VexEndnessBE)
9232                   assign( dw1, IRExpr_Load(Iend_LE, Ity_I64, mkexpr(EA)));
9233                else
9234                   assign( dw1, IRExpr_Load(Iend_BE, Ity_I64, mkexpr(EA)));
9235                putIReg( rD_addr, mkexpr(dw1) );
9236 
9237             But since we currently don't we load the value as is and then
9238             switch it around with Iop_Reverse8sIn64_x1. */
9239 
9240          IRTemp dw1 = newTemp(Ity_I64);
9241          IRTemp dw2 = newTemp(Ity_I64);
9242          DIP("ldbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
9243          assign( dw1, load(Ity_I64, mkexpr(EA)) );
9244          assign( dw2, unop(Iop_Reverse8sIn64_x1, mkexpr(dw1)) );
9245          putIReg( rD_addr, mkexpr(dw2) );
9246          break;
9247       }
9248 
9249       case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523)
9250          DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
9251          assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
9252          store( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) );
9253          break;
9254 
9255       case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531)
9256          DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
9257          assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
9258          store( mkexpr(EA), gen_byterev32(w1) );
9259          break;
9260 
9261       case 0x294: // stdbrx (Store Doubleword Byte-Reverse Indexed)
9262       {
9263          IRTemp lo = newTemp(Ity_I32);
9264          IRTemp hi = newTemp(Ity_I32);
9265          IRTemp rS = newTemp(Ity_I64);
9266          assign( rS, getIReg( rS_addr ) );
9267          DIP("stdbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
9268          assign(lo, unop(Iop_64HIto32, mkexpr(rS)));
9269          assign(hi, unop(Iop_64to32, mkexpr(rS)));
9270          store( mkexpr( EA ),
9271                 binop( Iop_32HLto64, gen_byterev32( hi ),
9272                        gen_byterev32( lo ) ) );
9273          break;
9274       }
9275 
9276       default:
9277          vex_printf("dis_int_ldst_rev(ppc)(opc2)\n");
9278          return False;
9279    }
9280    return True;
9281 }
9282 
9283 
9284 
9285 /*
9286   Processor Control Instructions
9287 */
dis_proc_ctl(const VexAbiInfo * vbi,UInt theInstr)9288 static Bool dis_proc_ctl ( const VexAbiInfo* vbi, UInt theInstr )
9289 {
9290    UChar opc1     = ifieldOPC(theInstr);
9291 
9292    /* X-Form */
9293    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
9294    UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
9295    UChar rD_addr  = ifieldRegDS(theInstr);
9296    UInt  b11to20  = IFIELD( theInstr, 11, 10 );
9297 
9298    /* XFX-Form */
9299    UChar rS_addr  = rD_addr;
9300    UInt  SPR      = b11to20;
9301    UInt  TBR      = b11to20;
9302    UChar b20      = toUChar( IFIELD( theInstr, 20, 1 ) );
9303    UInt  CRM      = IFIELD( theInstr, 12, 8 );
9304    UChar b11      = toUChar( IFIELD( theInstr, 11, 1 ) );
9305 
9306    UInt  opc2     = ifieldOPClo10(theInstr);
9307    UChar b0       = ifieldBIT0(theInstr);
9308 
9309    IRType ty = mode64 ? Ity_I64 : Ity_I32;
9310    IRTemp rS = newTemp(ty);
9311    assign( rS, getIReg(rS_addr) );
9312 
9313    /* Reorder SPR field as per PPC32 p470 */
9314    SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F);
9315    /* Reorder TBR field as per PPC32 p475 */
9316    TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31);
9317 
9318    /* b0 = 0, inst is treated as floating point inst for reservation purposes
9319     * b0 = 1, inst is treated as vector inst for reservation purposes
9320     */
9321    if (opc1 != 0x1F) {
9322       vex_printf("dis_proc_ctl(ppc)(opc1|b%d)\n", b0);
9323       return False;
9324    }
9325 
9326    switch (opc2) {
9327    /* X-Form */
9328    case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466)
9329       if (b21to22 != 0 || b11to20 != 0) {
9330          vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n");
9331          return False;
9332       }
9333       DIP("mcrxr crf%d\n", crfD);
9334       /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */
9335       putGST_field( PPC_GST_CR,
9336                     getGST_field( PPC_GST_XER, 7 ),
9337                     crfD );
9338 
9339       // Clear XER[0-3]
9340       putXER_SO( mkU8(0) );
9341       putXER_OV( mkU8(0) );
9342       putXER_CA( mkU8(0) );
9343       break;
9344    }
9345 
9346    case 0x013:
9347       // b11to20==0:      mfcr (Move from Cond Register, PPC32 p467)
9348       // b20==1 & b11==0: mfocrf (Move from One CR Field)
9349       // However it seems that the 'mfcr' behaviour is an acceptable
9350       // implementation of mfocr (from the 2.02 arch spec)
9351       if (b11to20 == 0) {
9352          DIP("mfcr r%u\n", rD_addr);
9353          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
9354                                          /* Signed */False) );
9355          break;
9356       }
9357       if (b20 == 1 && b11 == 0) {
9358          DIP("mfocrf r%u,%u\n", rD_addr, CRM);
9359          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
9360                                          /* Signed */False) );
9361          break;
9362       }
9363       /* not decodable */
9364       return False;
9365 
9366    /* XFX-Form */
9367    case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470)
9368 
9369       switch (SPR) {  // Choose a register...
9370       case 0x1:
9371          DIP("mfxer r%u\n", rD_addr);
9372          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ),
9373                                          /* Signed */False) );
9374          break;
9375       case 0x3:  // 131
9376          DIP("mfspr r%u (DSCR)\n", rD_addr);
9377          putIReg( rD_addr, getGST( PPC_GST_DSCR) );
9378          break;
9379       case 0x8:
9380          DIP("mflr r%u\n", rD_addr);
9381          putIReg( rD_addr, getGST( PPC_GST_LR ) );
9382          break;
9383       case 0x9:
9384          DIP("mfctr r%u\n", rD_addr);
9385          putIReg( rD_addr, getGST( PPC_GST_CTR ) );
9386          break;
9387       case 0x80:  // 128
9388          DIP("mfspr r%u (TFHAR)\n", rD_addr);
9389          putIReg( rD_addr, getGST( PPC_GST_TFHAR) );
9390          break;
9391       case 0x81:  // 129
9392          DIP("mfspr r%u (TFIAR)\n", rD_addr);
9393          putIReg( rD_addr, getGST( PPC_GST_TFIAR) );
9394          break;
9395       case 0x82:  // 130
9396          DIP("mfspr r%u (TEXASR)\n", rD_addr);
9397          putIReg( rD_addr, getGST( PPC_GST_TEXASR) );
9398          break;
9399       case 0x83:  // 131
9400          DIP("mfspr r%u (TEXASRU)\n", rD_addr);
9401          putIReg( rD_addr, getGST( PPC_GST_TEXASRU) );
9402          break;
9403       case 0x9F:  // 159
9404          DIP("mfspr r%u (PSPB)\n", rD_addr);
9405          putIReg( rD_addr, getGST( PPC_GST_PSPB) );
9406          break;
9407       case 0x380:  // 896
9408          DIP("mfspr r%u (PPR)\n", rD_addr);
9409          putIReg( rD_addr, getGST( PPC_GST_PPR) );
9410          break;
9411       case 0x382:  // 898
9412          DIP("mfspr r%u (PPR)32\n", rD_addr);
9413          putIReg( rD_addr, getGST( PPC_GST_PPR32) );
9414          break;
9415       case 0x100:
9416          DIP("mfvrsave r%u\n", rD_addr);
9417          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ),
9418                                          /* Signed */False) );
9419          break;
9420 
9421       case 0x103:
9422          DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr);
9423          putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) );
9424          break;
9425 
9426       case 268 /* 0x10C  TB  - 64 bit time base register */:
9427       {
9428          IRTemp   val  = newTemp(Ity_I64);
9429          IRExpr** args = mkIRExprVec_0();
9430          IRDirty* d    = unsafeIRDirty_1_N(
9431                                            val,
9432                                            0/*regparms*/,
9433                                            "ppcg_dirtyhelper_MFTB",
9434                                            fnptr_to_fnentry(vbi,
9435                                                             &ppcg_dirtyhelper_MFTB),
9436                                            args );
9437          /* execute the dirty call, dumping the result in val. */
9438          stmt( IRStmt_Dirty(d) );
9439          putIReg( rD_addr, (mode64) ? mkexpr(val) :
9440                                       unop(Iop_64to32, mkexpr(val)) );
9441 
9442          break;
9443       }
9444       case 269 /* 0x10D  TBU - upper 32-bits of time base register */:
9445       {
9446          DIP("mfspr r%u,%u", rD_addr, SPR);
9447          IRTemp   val  = newTemp(Ity_I64);
9448          IRExpr** args = mkIRExprVec_0();
9449          IRDirty* d    = unsafeIRDirty_1_N(
9450                                            val,
9451                                            0/*regparms*/,
9452                                            "ppcg_dirtyhelper_MFTB",
9453                                            fnptr_to_fnentry(vbi,
9454                                                             &ppcg_dirtyhelper_MFTB),
9455                                            args );
9456          /* execute the dirty call, dumping the result in val. */
9457          stmt( IRStmt_Dirty(d) );
9458          putIReg( rD_addr,
9459                   mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)),
9460                                 /* Signed */False) );
9461          break;
9462       }
9463       case 284 /* 0x1  TBL - lower 32-bits of time base register */:
9464       {
9465          DIP("mfspr r%u,%u", rD_addr, SPR);
9466          IRTemp   val  = newTemp(Ity_I64);
9467          IRExpr** args = mkIRExprVec_0();
9468          IRDirty* d    = unsafeIRDirty_1_N(
9469                                            val,
9470                                            0/*regparms*/,
9471                                            "ppcg_dirtyhelper_MFTB",
9472                                            fnptr_to_fnentry(vbi,
9473                                                             &ppcg_dirtyhelper_MFTB),
9474                                            args );
9475          /* execute the dirty call, dumping the result in val. */
9476          stmt( IRStmt_Dirty(d) );
9477          putIReg( rD_addr,
9478                   mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(val)),
9479                                 /* Signed */False) );
9480          break;
9481       }
9482 
9483       /* Again, runs natively on PPC7400 (7447, really).  Not
9484          bothering with a feature test. */
9485       case 287: /* 0x11F */ {
9486          IRTemp   val  = newTemp(Ity_I32);
9487          IRExpr** args = mkIRExprVec_0();
9488          IRDirty* d    = unsafeIRDirty_1_N(
9489                             val,
9490                             0/*regparms*/,
9491                             "ppc32g_dirtyhelper_MFSPR_287",
9492                             fnptr_to_fnentry
9493                                (vbi, &ppc32g_dirtyhelper_MFSPR_287),
9494                             args
9495                          );
9496          /* execute the dirty call, dumping the result in val. */
9497          stmt( IRStmt_Dirty(d) );
9498          putIReg( rD_addr,
9499                   mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
9500          DIP("mfspr r%u,%u", rD_addr, SPR);
9501          break;
9502       }
9503 
9504       default:
9505          vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR);
9506          return False;
9507       }
9508       break;
9509 
9510    case 0x173: { // mftb (Move from Time Base, PPC32 p475)
9511       IRTemp   val  = newTemp(Ity_I64);
9512       IRExpr** args = mkIRExprVec_0();
9513       IRDirty* d    = unsafeIRDirty_1_N(
9514                               val,
9515                               0/*regparms*/,
9516                               "ppcg_dirtyhelper_MFTB",
9517                               fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB),
9518                               args );
9519       /* execute the dirty call, dumping the result in val. */
9520       stmt( IRStmt_Dirty(d) );
9521 
9522       switch (TBR) {
9523       case 269:
9524          DIP("mftbu r%u", rD_addr);
9525          putIReg( rD_addr,
9526                   mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)),
9527                                 /* Signed */False) );
9528          break;
9529       case 268:
9530          DIP("mftb r%u", rD_addr);
9531          putIReg( rD_addr, (mode64) ? mkexpr(val) :
9532                                       unop(Iop_64to32, mkexpr(val)) );
9533          break;
9534       case 284:
9535          DIP("mftbl r%u", rD_addr);
9536          putIReg( rD_addr,
9537                   mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(val)),
9538                                 /* Signed */False) );
9539          break;
9540       default:
9541          return False; /* illegal instruction */
9542       }
9543       break;
9544    }
9545 
9546    case 0x090: {
9547       // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477)
9548       // b20==1: mtocrf (Move to One Cond Reg Field)
9549       Int   cr;
9550       UChar shft;
9551       if (b11 != 0)
9552          return False;
9553       if (b20 == 1) {
9554          /* ppc64 v2.02 spec says mtocrf gives undefined outcome if >
9555             1 field is written.  It seems more robust to decline to
9556             decode the insn if so. */
9557          switch (CRM) {
9558             case 0x01: case 0x02: case 0x04: case 0x08:
9559             case 0x10: case 0x20: case 0x40: case 0x80:
9560                break;
9561             default:
9562                return False;
9563          }
9564       }
9565       DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf",
9566                            CRM, rS_addr);
9567       /* Write to each field specified by CRM */
9568       for (cr = 0; cr < 8; cr++) {
9569          if ((CRM & (1 << (7-cr))) == 0)
9570             continue;
9571          shft = 4*(7-cr);
9572          putGST_field( PPC_GST_CR,
9573                        binop(Iop_Shr32,
9574                              mkNarrowTo32(ty, mkexpr(rS)),
9575                              mkU8(shft)), cr );
9576       }
9577       break;
9578    }
9579 
9580    case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483)
9581 
9582       switch (SPR) {  // Choose a register...
9583       case 0x1:
9584          DIP("mtxer r%u\n", rS_addr);
9585          putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) );
9586          break;
9587       case 0x3:
9588          DIP("mtspr r%u (DSCR)\n", rS_addr);
9589          putGST( PPC_GST_DSCR, mkexpr(rS) );
9590          break;
9591       case 0x8:
9592          DIP("mtlr r%u\n", rS_addr);
9593          putGST( PPC_GST_LR, mkexpr(rS) );
9594          break;
9595       case 0x9:
9596          DIP("mtctr r%u\n", rS_addr);
9597          putGST( PPC_GST_CTR, mkexpr(rS) );
9598          break;
9599       case 0x100:
9600          DIP("mtvrsave r%u\n", rS_addr);
9601          putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) );
9602          break;
9603       case 0x80:  // 128
9604          DIP("mtspr r%u (TFHAR)\n", rS_addr);
9605          putGST( PPC_GST_TFHAR, mkexpr(rS) );
9606          break;
9607       case 0x81:  // 129
9608          DIP("mtspr r%u (TFIAR)\n", rS_addr);
9609          putGST( PPC_GST_TFIAR, mkexpr(rS) );
9610          break;
9611       case 0x82:  // 130
9612          DIP("mtspr r%u (TEXASR)\n", rS_addr);
9613          putGST( PPC_GST_TEXASR, mkexpr(rS) );
9614          break;
9615       case 0x9F:  // 159
9616          DIP("mtspr r%u (PSPB)\n", rS_addr);
9617          putGST( PPC_GST_PSPB, mkexpr(rS) );
9618          break;
9619       case 0x380:  // 896
9620          DIP("mtspr r%u (PPR)\n", rS_addr);
9621          putGST( PPC_GST_PPR, mkexpr(rS) );
9622          break;
9623       case 0x382:  // 898
9624          DIP("mtspr r%u (PPR32)\n", rS_addr);
9625          putGST( PPC_GST_PPR32, mkexpr(rS) );
9626          break;
9627       default:
9628          vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR);
9629          return False;
9630       }
9631       break;
9632 
9633    case 0x33:                // mfvsrd
9634    {
9635       UChar XS = ifieldRegXS( theInstr );
9636       UChar rA_addr = ifieldRegA(theInstr);
9637       IRExpr * high64;
9638       IRTemp vS = newTemp( Ity_V128 );
9639       DIP("mfvsrd r%u,vsr%d\n", rA_addr, XS);
9640 
9641       /*  XS = SX || S
9642        *  For SX=0, mfvsrd is treated as a Floating-Point
9643        *            instruction in terms of resource availability.
9644        *  For SX=1, mfvsrd is treated as a Vector instruction in
9645        *            terms of resource availability.
9646        * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
9647        */
9648       assign( vS, getVSReg( XS ) );
9649       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
9650       putIReg( rA_addr, (mode64) ? high64 :
9651       unop( Iop_64to32, high64 ) );
9652       break;
9653    }
9654 
9655    case 0x73:                // mfvsrwz
9656    {
9657       UChar XS = ifieldRegXS( theInstr );
9658       UChar rA_addr = ifieldRegA(theInstr);
9659       IRExpr * high64;
9660       IRTemp vS = newTemp( Ity_V128 );
9661       DIP("mfvsrwz r%u,vsr%d\n", rA_addr, XS);
9662       /*  XS = SX || S
9663        *  For SX=0, mfvsrwz is treated as a Floating-Point
9664        *            instruction in terms of resource availability.
9665        *  For SX=1, mfvsrwz is treated as a Vector instruction in
9666        *            terms of resource availability.
9667        * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
9668        */
9669 
9670       assign( vS, getVSReg( XS ) );
9671       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
9672       /* move value to the destination setting the upper 32-bits to zero */
9673       putIReg( rA_addr, (mode64) ?
9674                                   binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) :
9675                                   unop(  Iop_64to32,
9676                                          binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) ) );
9677       break;
9678    }
9679 
9680    case 0xB3:                // mtvsrd
9681    {
9682       UChar XT = ifieldRegXT( theInstr );
9683       UChar rA_addr = ifieldRegA(theInstr);
9684       IRTemp rA = newTemp(ty);
9685       DIP("mtvsrd vsr%d,r%u\n", XT, rA_addr);
9686       /*  XS = SX || S
9687        *  For SX=0, mfvsrd is treated as a Floating-Point
9688        *            instruction in terms of resource availability.
9689        *  For SX=1, mfvsrd is treated as a Vector instruction in
9690        *            terms of resource availability.
9691        * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
9692        */
9693       assign( rA, getIReg(rA_addr) );
9694 
9695       if (mode64)
9696          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( rA ), mkU64( 0 ) ) );
9697       else
9698          putVSReg( XT, binop( Iop_64HLtoV128,
9699                               binop( Iop_32HLto64,
9700                                      mkU32( 0 ),
9701                                      mkexpr( rA ) ),
9702                                      mkU64( 0 ) ) );
9703       break;
9704    }
9705 
9706    case 0xD3:                // mtvsrwa
9707    {
9708       UChar XT = ifieldRegXT( theInstr );
9709       UChar rA_addr = ifieldRegA(theInstr);
9710       IRTemp rA = newTemp( Ity_I32 );
9711       DIP("mtvsrwa vsr%d,r%u\n", XT, rA_addr);
9712       /*  XS = SX || S
9713        *  For SX=0, mtvsrwa is treated as a Floating-Point
9714        *            instruction in terms of resource availability.
9715        *  For SX=1, mtvsrwa is treated as a Vector instruction in
9716        *            terms of resource availability.
9717        * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
9718        */
9719       if (mode64)
9720          assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) );
9721       else
9722          assign( rA, getIReg(rA_addr) );
9723 
9724       putVSReg( XT, binop( Iop_64HLtoV128,
9725                            unop( Iop_32Sto64, mkexpr( rA ) ),
9726                            mkU64( 0 ) ) );
9727       break;
9728    }
9729 
9730    case 0xF3:                // mtvsrwz
9731       {
9732          UChar XT = ifieldRegXT( theInstr );
9733          UChar rA_addr = ifieldRegA(theInstr);
9734          IRTemp rA = newTemp( Ity_I32 );
9735          DIP("mtvsrwz vsr%d,r%u\n", rA_addr, XT);
9736          /*  XS = SX || S
9737           *  For SX=0, mtvsrwz is treated as a Floating-Point
9738           *            instruction in terms of resource availability.
9739           *  For SX=1, mtvsrwz is treated as a Vector instruction in
9740           *            terms of resource availability.
9741           * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
9742           */
9743          if (mode64)
9744              assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) );
9745          else
9746              assign( rA, getIReg(rA_addr) );
9747 
9748          putVSReg( XT, binop( Iop_64HLtoV128,
9749                               binop( Iop_32HLto64, mkU32( 0 ), mkexpr ( rA ) ),
9750                               mkU64( 0 ) ) );
9751          break;
9752       }
9753 
9754    default:
9755       vex_printf("dis_proc_ctl(ppc)(opc2)\n");
9756       return False;
9757    }
9758    return True;
9759 }
9760 
9761 
9762 /*
9763   Cache Management Instructions
9764 */
dis_cache_manage(UInt theInstr,DisResult * dres,const VexArchInfo * guest_archinfo)9765 static Bool dis_cache_manage ( UInt         theInstr,
9766                                DisResult*   dres,
9767                                const VexArchInfo* guest_archinfo )
9768 {
9769    /* X-Form */
9770    UChar opc1    = ifieldOPC(theInstr);
9771    UChar b21to25 = ifieldRegDS(theInstr);
9772    UChar rA_addr = ifieldRegA(theInstr);
9773    UChar rB_addr = ifieldRegB(theInstr);
9774    UInt  opc2    = ifieldOPClo10(theInstr);
9775    UChar b0      = ifieldBIT0(theInstr);
9776    UInt  lineszB = guest_archinfo->ppc_icache_line_szB;
9777    Bool  is_dcbzl = False;
9778 
9779    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
9780 
9781    // Check for valid hint values for dcbt and dcbtst as currently described in
9782    // ISA 2.07.  If valid, then we simply set b21to25 to zero since we have no
9783    // means of modeling the hint anyway.
9784    if (opc1 == 0x1F && ((opc2 == 0x116) || (opc2 == 0xF6))) {
9785       if (b21to25 == 0x10 || b21to25 < 0x10)
9786          b21to25 = 0;
9787    }
9788    if (opc1 == 0x1F && opc2 == 0x116 && b21to25 == 0x11)
9789       b21to25 = 0;
9790 
9791    if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz
9792       if (b21to25 == 1) {
9793          is_dcbzl = True;
9794          b21to25 = 0;
9795          if (!(guest_archinfo->ppc_dcbzl_szB)) {
9796             vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n");
9797             return False;
9798          }
9799       }
9800    }
9801 
9802    if (opc1 != 0x1F || b0 != 0) {
9803       if (0) vex_printf("dis_cache_manage %d %d\n",
9804                         opc1, b0);
9805       vex_printf("dis_cache_manage(ppc)(opc1|b0)\n");
9806       return False;
9807    }
9808 
9809    /* stay sane .. */
9810    vassert(lineszB == 16 || lineszB == 32 || lineszB == 64 || lineszB == 128);
9811 
9812    switch (opc2) {
9813 //zz    case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380)
9814 //zz       vassert(0); /* AWAITING TEST CASE */
9815 //zz       DIP("dcba r%u,r%u\n", rA_addr, rB_addr);
9816 //zz       if (0) vex_printf("vex ppc->IR: kludged dcba\n");
9817 //zz       break;
9818 
9819    case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382)
9820       DIP("dcbf r%u,r%u\n", rA_addr, rB_addr);
9821       /* nop as far as vex is concerned */
9822       break;
9823 
9824    case 0x036: // dcbst (Data Cache Block Store, PPC32 p384)
9825       DIP("dcbst r%u,r%u\n", rA_addr, rB_addr);
9826       /* nop as far as vex is concerned */
9827       break;
9828 
9829    case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385)
9830       DIP("dcbt r%u,r%u\n", rA_addr, rB_addr);
9831       /* nop as far as vex is concerned */
9832       break;
9833 
9834    case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386)
9835       DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr);
9836       /* nop as far as vex is concerned */
9837       break;
9838 
9839    case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387)
9840                  // dcbzl (Data Cache Block Clear to Zero Long, bug#135264)
9841       /* Clear all bytes in cache block at (rA|0) + rB. */
9842       IRTemp  EA   = newTemp(ty);
9843       IRTemp  addr = newTemp(ty);
9844       IRExpr* irx_addr;
9845       UInt    i;
9846       UInt clearszB;
9847       if (is_dcbzl) {
9848           clearszB = guest_archinfo->ppc_dcbzl_szB;
9849           DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr);
9850       }
9851       else {
9852           clearszB = guest_archinfo->ppc_dcbz_szB;
9853           DIP("dcbz r%u,r%u\n", rA_addr, rB_addr);
9854       }
9855 
9856       assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
9857 
9858       if (mode64) {
9859          /* Round EA down to the start of the containing block. */
9860          assign( addr, binop( Iop_And64,
9861                               mkexpr(EA),
9862                               mkU64( ~((ULong)clearszB-1) )) );
9863 
9864          for (i = 0; i < clearszB / 8; i++) {
9865             irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) );
9866             store( irx_addr, mkU64(0) );
9867          }
9868       } else {
9869          /* Round EA down to the start of the containing block. */
9870          assign( addr, binop( Iop_And32,
9871                               mkexpr(EA),
9872                               mkU32( ~(clearszB-1) )) );
9873 
9874          for (i = 0; i < clearszB / 4; i++) {
9875             irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) );
9876             store( irx_addr, mkU32(0) );
9877          }
9878       }
9879       break;
9880    }
9881 
9882    case 0x3D6: {
9883       // icbi (Instruction Cache Block Invalidate, PPC32 p431)
9884       /* Invalidate all translations containing code from the cache
9885          block at (rA|0) + rB. */
9886       IRTemp EA   = newTemp(ty);
9887       IRTemp addr = newTemp(ty);
9888       DIP("icbi r%u,r%u\n", rA_addr, rB_addr);
9889       assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
9890 
9891       /* Round EA down to the start of the containing block. */
9892       assign( addr, binop( mkSzOp(ty, Iop_And8),
9893                            mkexpr(EA),
9894                            mkSzImm(ty, ~(((ULong)lineszB)-1) )) );
9895       putGST( PPC_GST_CMSTART, mkexpr(addr) );
9896       putGST( PPC_GST_CMLEN, mkSzImm(ty, lineszB) );
9897 
9898       /* be paranoid ... */
9899       stmt( IRStmt_MBE(Imbe_Fence) );
9900 
9901       putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()));
9902       dres->jk_StopHere = Ijk_InvalICache;
9903       dres->whatNext    = Dis_StopHere;
9904       break;
9905    }
9906 
9907    default:
9908       vex_printf("dis_cache_manage(ppc)(opc2)\n");
9909       return False;
9910    }
9911    return True;
9912 }
9913 
9914 
9915 /*------------------------------------------------------------*/
9916 /*--- Floating Point Helpers                               ---*/
9917 /*------------------------------------------------------------*/
9918 
9919 /* --------- Synthesise a 2-bit FPU rounding mode. --------- */
9920 /* Produces a value in 0 .. 3, which is encoded as per the type
9921    IRRoundingMode.  PPCRoundingMode encoding is different to
9922    IRRoundingMode, so need to map it.
9923 */
9924 
set_round_to_Oddmode(void)9925 static IRExpr* /* :: Ity_I32 */ set_round_to_Oddmode ( void )
9926 {
9927 /* PPC/ valgrind have two-bits to designate the rounding mode.
9928    ISA 3.0 adds instructions than can use a round to odd mode
9929    but did not change the number of bits for the rm.  Basically,
9930    they added two instructions that only differ by the rounding
9931    mode the operation uses.  In essesce, they encoded the rm
9932    in the name.  In order to avoid having to create Iops, that
9933    encode the rm in th name, we will "expand" the definition of
9934    the rounding mode bits.  We will just pass the rm and then
9935    map the to odd mode to the appropriate PPCFpOp name that
9936    will tell us which instruction to map to.
9937 
9938    rounding mode | PPC | IR
9939    ------------------------
9940    to nearest    | 000  | 00
9941    to zero       | 001  | 11
9942    to +infinity  | 010  | 10
9943    to -infinity  | 011  | 01
9944    to odd        | 1xx  | xx
9945 */
9946    return mkU32(8);
9947 }
9948 
get_IR_roundingmode(void)9949 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void )
9950 {
9951 /*
9952    rounding mode | PPC | IR
9953    ------------------------
9954    to nearest    | 00  | 00
9955    to zero       | 01  | 11
9956    to +infinity  | 10  | 10
9957    to -infinity  | 11  | 01
9958 */
9959    IRTemp rm_PPC32 = newTemp(Ity_I32);
9960    assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) );
9961 
9962    // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
9963    return binop( Iop_Xor32,
9964                  mkexpr(rm_PPC32),
9965                  binop( Iop_And32,
9966                         binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)),
9967                         mkU32(2) ));
9968 }
9969 
9970 /* The DFP IR rounding modes were chosen such that the existing PPC to IR
9971  * mapping would still work with the extended three bit DFP rounding
9972  * mode designator.
9973 
9974  *  rounding mode                     | PPC  |  IR
9975  *  -----------------------------------------------
9976  *  to nearest, ties to even          | 000  | 000
9977  *  to zero                           | 001  | 011
9978  *  to +infinity                      | 010  | 010
9979  *  to -infinity                      | 011  | 001
9980  *  to nearest, ties away from 0      | 100  | 100
9981  *  to nearest, ties toward 0         | 101  | 111
9982  *  to away from 0                    | 110  | 110
9983  *  to prepare for shorter precision  | 111  | 101
9984  */
get_IR_roundingmode_DFP(void)9985 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode_DFP( void )
9986 {
9987    IRTemp rm_PPC32 = newTemp( Ity_I32 );
9988    assign( rm_PPC32, getGST_masked_upper( PPC_GST_FPSCR, MASK_FPSCR_DRN ) );
9989 
9990    // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
9991    return binop( Iop_Xor32,
9992                  mkexpr( rm_PPC32 ),
9993                  binop( Iop_And32,
9994                         binop( Iop_Shl32, mkexpr( rm_PPC32 ), mkU8( 1 ) ),
9995                         mkU32( 2 ) ) );
9996 }
9997 
9998 #define NANmaskSingle   0x7F800000
9999 #define NANmaskDouble   0x7FF00000
10000 
Check_NaN(IRExpr * value,IRExpr * Hi32Mask)10001 static IRExpr * Check_NaN( IRExpr * value, IRExpr * Hi32Mask )
10002 {
10003    IRTemp exp_zero  = newTemp(Ity_I8);
10004    IRTemp frac_mask = newTemp(Ity_I32);
10005    IRTemp frac_not_zero = newTemp(Ity_I8);
10006 
10007    /* Check if the result is QNAN or SNAN and not +infinity or -infinity.
10008     * The input value is always 64-bits, for single precision values, the
10009     * lower 32 bits must be zero.
10010     *
10011     * Single Pricision
10012     *  [62:54] exponent field is equal to 0xFF for NAN and Infinity.
10013     *  [53:32] fraction field is zero for Infinity and non-zero for NAN
10014     *  [31:0]  unused for single precision representation
10015     *
10016     * Double Pricision
10017     *  [62:51] exponent field is equal to 0xFF for NAN and Infinity.
10018     *  [50:0]  fraction field is zero for Infinity and non-zero for NAN
10019     *
10020     * Returned result is a U32 value of 0xFFFFFFFF for NaN and 0 otherwise.
10021     */
10022    assign( frac_mask, unop( Iop_Not32,
10023                             binop( Iop_Or32,
10024                                    mkU32( 0x80000000ULL ), Hi32Mask) ) );
10025 
10026    assign( exp_zero,
10027            unop( Iop_1Sto8,
10028                  binop( Iop_CmpEQ32,
10029                         binop( Iop_And32,
10030                                unop( Iop_64HIto32,
10031                                      unop( Iop_ReinterpF64asI64,
10032                                            value ) ),
10033                                Hi32Mask ),
10034                         Hi32Mask ) ) );
10035    assign( frac_not_zero,
10036            binop( Iop_Or8,
10037                   unop( Iop_1Sto8,
10038                         binop( Iop_CmpNE32,
10039                                binop( Iop_And32,
10040                                       unop( Iop_64HIto32,
10041                                             unop( Iop_ReinterpF64asI64,
10042                                                   value ) ),
10043                                       mkexpr( frac_mask ) ),
10044                                mkU32( 0x0 ) ) ),
10045                   unop( Iop_1Sto8,
10046                         binop( Iop_CmpNE32,
10047                                binop( Iop_And32,
10048                                       unop( Iop_64to32,
10049                                             unop( Iop_ReinterpF64asI64,
10050                                                   value ) ),
10051                                       mkU32( 0xFFFFFFFF ) ),
10052                                mkU32( 0x0 ) ) ) ) );
10053    return unop( Iop_8Sto32,
10054                 binop( Iop_And8,
10055                        mkexpr( exp_zero ),
10056                        mkexpr( frac_not_zero ) ) );
10057 }
10058 
Complement_non_NaN(IRExpr * value,IRExpr * nan_mask)10059 static IRExpr * Complement_non_NaN( IRExpr * value, IRExpr * nan_mask )
10060 {
10061    /* This function will only complement the 64-bit floating point value if it
10062     * is not Nan.  NaN is not a signed value.  Need to do computations using
10063     * 32-bit operands to ensure it will run in 32-bit mode.
10064     */
10065    return  binop( Iop_32HLto64,
10066                   binop( Iop_Or32,
10067                          binop( Iop_And32,
10068                                 nan_mask,
10069                                 unop( Iop_64HIto32,
10070                                       unop( Iop_ReinterpF64asI64,
10071                                             value ) ) ),
10072                          binop( Iop_And32,
10073                                 unop( Iop_Not32,
10074                                       nan_mask ),
10075                                 unop( Iop_64HIto32,
10076                                       unop( Iop_ReinterpF64asI64,
10077                                             unop( Iop_NegF64,
10078                                                   value ) ) ) ) ),
10079                   unop( Iop_64to32,
10080                         unop( Iop_ReinterpF64asI64, value ) ) );
10081 }
10082 
10083 /*------------------------------------------------------------*/
10084 /*--- Floating Point Instruction Translation               ---*/
10085 /*------------------------------------------------------------*/
10086 
10087 /*
10088   Floating Point Load Instructions
10089 */
dis_fp_load(UInt theInstr)10090 static Bool dis_fp_load ( UInt theInstr )
10091 {
10092    /* X-Form, D-Form */
10093    UChar opc1      = ifieldOPC(theInstr);
10094    UChar frD_addr  = ifieldRegDS(theInstr);
10095    UChar rA_addr   = ifieldRegA(theInstr);
10096    UChar rB_addr   = ifieldRegB(theInstr);
10097    UInt  opc2      = ifieldOPClo10(theInstr);
10098    UChar b0        = ifieldBIT0(theInstr);
10099    UInt  uimm16    = ifieldUIMM16(theInstr);
10100 
10101    Int    simm16 = extend_s_16to32(uimm16);
10102    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
10103    IRTemp EA     = newTemp(ty);
10104    IRTemp rA     = newTemp(ty);
10105    IRTemp rB     = newTemp(ty);
10106    IRTemp iHi    = newTemp(Ity_I32);
10107    IRTemp iLo    = newTemp(Ity_I32);
10108 
10109    assign( rA, getIReg(rA_addr) );
10110    assign( rB, getIReg(rB_addr) );
10111 
10112    /* These are completely straightforward from a rounding and status
10113       bits perspective: no rounding involved and no funny status or CR
10114       bits affected. */
10115 
10116    switch (opc1) {
10117    case 0x30: // lfs (Load Float Single, PPC32 p441)
10118       DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
10119       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
10120       putFReg( frD_addr,
10121                unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
10122       break;
10123 
10124    case 0x31: // lfsu (Load Float Single, Update, PPC32 p442)
10125       if (rA_addr == 0)
10126          return False;
10127       DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
10128       assign( EA, ea_rA_simm(rA_addr, simm16) );
10129       putFReg( frD_addr,
10130                unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
10131       putIReg( rA_addr, mkexpr(EA) );
10132       break;
10133 
10134    case 0x32: // lfd (Load Float Double, PPC32 p437)
10135       DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
10136       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
10137       putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
10138       break;
10139 
10140    case 0x33: // lfdu (Load Float Double, Update, PPC32 p438)
10141       if (rA_addr == 0)
10142          return False;
10143       DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
10144       assign( EA, ea_rA_simm(rA_addr, simm16) );
10145       putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
10146       putIReg( rA_addr, mkexpr(EA) );
10147       break;
10148 
10149    case 0x1F:
10150       if (b0 != 0) {
10151          vex_printf("dis_fp_load(ppc)(instr,b0)\n");
10152          return False;
10153       }
10154 
10155       switch(opc2) {
10156       case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444)
10157          DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
10158          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
10159          putFReg( frD_addr, unop( Iop_F32toF64,
10160                                   load(Ity_F32, mkexpr(EA))) );
10161          break;
10162 
10163       case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443)
10164          if (rA_addr == 0)
10165             return False;
10166          DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
10167          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
10168          putFReg( frD_addr,
10169                   unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
10170          putIReg( rA_addr, mkexpr(EA) );
10171          break;
10172 
10173       case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440)
10174          DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
10175          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
10176          putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
10177          break;
10178 
10179       case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439)
10180          if (rA_addr == 0)
10181             return False;
10182          DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
10183          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
10184          putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
10185          putIReg( rA_addr, mkexpr(EA) );
10186          break;
10187 
10188       case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120)
10189          DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
10190          assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
10191          assign( iLo, load(Ity_I32, mkexpr(EA)) );
10192          assign( iHi, binop(Iop_Sub32,
10193                             mkU32(0),
10194                             binop(Iop_Shr32, mkexpr(iLo), mkU8(31)))  );
10195          putFReg( frD_addr, unop(Iop_ReinterpI64asF64,
10196                                  binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) );
10197          break;
10198 
10199       case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed
10200       {
10201          IRTemp dw = newTemp( Ity_I64 );
10202          DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
10203          assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
10204          assign( iLo, load(Ity_I32, mkexpr(EA)) );
10205          assign( dw, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( iLo ) ) );
10206          putFReg( frD_addr, unop( Iop_ReinterpI64asF64, mkexpr( dw ) ) );
10207          break;
10208       }
10209 
10210       default:
10211          vex_printf("dis_fp_load(ppc)(opc2)\n");
10212          return False;
10213       }
10214       break;
10215 
10216    default:
10217       vex_printf("dis_fp_load(ppc)(opc1)\n");
10218       return False;
10219    }
10220    return True;
10221 }
10222 
10223 
10224 
10225 /*
10226   Floating Point Store Instructions
10227 */
dis_fp_store(UInt theInstr)10228 static Bool dis_fp_store ( UInt theInstr )
10229 {
10230    /* X-Form, D-Form */
10231    UChar opc1      = ifieldOPC(theInstr);
10232    UChar frS_addr  = ifieldRegDS(theInstr);
10233    UChar rA_addr   = ifieldRegA(theInstr);
10234    UChar rB_addr   = ifieldRegB(theInstr);
10235    UInt  opc2      = ifieldOPClo10(theInstr);
10236    UChar b0        = ifieldBIT0(theInstr);
10237    Int   uimm16    = ifieldUIMM16(theInstr);
10238 
10239    Int    simm16 = extend_s_16to32(uimm16);
10240    IRTemp frS    = newTemp(Ity_F64);
10241    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
10242    IRTemp EA     = newTemp(ty);
10243    IRTemp rA     = newTemp(ty);
10244    IRTemp rB     = newTemp(ty);
10245 
10246    assign( frS, getFReg(frS_addr) );
10247    assign( rA,  getIReg(rA_addr) );
10248    assign( rB,  getIReg(rB_addr) );
10249 
10250    /* These are straightforward from a status bits perspective: no
10251       funny status or CR bits affected.  For single precision stores,
10252       the values are truncated and denormalised (not rounded) to turn
10253       them into single precision values. */
10254 
10255    switch (opc1) {
10256 
10257    case 0x34: // stfs (Store Float Single, PPC32 p518)
10258       DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
10259       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
10260       /* Use Iop_TruncF64asF32 to truncate and possible denormalise
10261          the value to be stored in the correct way, without any
10262          rounding. */
10263       store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
10264       break;
10265 
10266    case 0x35: // stfsu (Store Float Single, Update, PPC32 p519)
10267       if (rA_addr == 0)
10268          return False;
10269       DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
10270       assign( EA, ea_rA_simm(rA_addr, simm16) );
10271       /* See comment for stfs */
10272       store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
10273       putIReg( rA_addr, mkexpr(EA) );
10274       break;
10275 
10276    case 0x36: // stfd (Store Float Double, PPC32 p513)
10277       DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
10278       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
10279       store( mkexpr(EA), mkexpr(frS) );
10280       break;
10281 
10282    case 0x37: // stfdu (Store Float Double, Update, PPC32 p514)
10283       if (rA_addr == 0)
10284          return False;
10285       DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
10286       assign( EA, ea_rA_simm(rA_addr, simm16) );
10287       store( mkexpr(EA), mkexpr(frS) );
10288       putIReg( rA_addr, mkexpr(EA) );
10289       break;
10290 
10291    case 0x1F:
10292       if (b0 != 0) {
10293          vex_printf("dis_fp_store(ppc)(instr,b0)\n");
10294          return False;
10295       }
10296       switch(opc2) {
10297       case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521)
10298          DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
10299          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
10300          /* See note for stfs */
10301          store( mkexpr(EA),
10302                 unop(Iop_TruncF64asF32, mkexpr(frS)) );
10303          break;
10304 
10305       case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520)
10306          if (rA_addr == 0)
10307             return False;
10308          DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
10309          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
10310          /* See note for stfs */
10311          store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
10312          putIReg( rA_addr, mkexpr(EA) );
10313          break;
10314 
10315       case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516)
10316          DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
10317          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
10318          store( mkexpr(EA), mkexpr(frS) );
10319          break;
10320 
10321       case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515)
10322          if (rA_addr == 0)
10323             return False;
10324          DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
10325          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
10326          store( mkexpr(EA), mkexpr(frS) );
10327          putIReg( rA_addr, mkexpr(EA) );
10328          break;
10329 
10330       case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517)
10331          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
10332          DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
10333          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
10334          store( mkexpr(EA),
10335                 unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) );
10336          break;
10337 
10338       default:
10339          vex_printf("dis_fp_store(ppc)(opc2)\n");
10340          return False;
10341       }
10342       break;
10343 
10344    default:
10345       vex_printf("dis_fp_store(ppc)(opc1)\n");
10346       return False;
10347    }
10348    return True;
10349 }
10350 
10351 
10352 
10353 /*
10354   Floating Point Arith Instructions
10355 */
dis_fp_arith(UInt theInstr)10356 static Bool dis_fp_arith ( UInt theInstr )
10357 {
10358    /* A-Form */
10359    UChar opc1     = ifieldOPC(theInstr);
10360    UChar frD_addr = ifieldRegDS(theInstr);
10361    UChar frA_addr = ifieldRegA(theInstr);
10362    UChar frB_addr = ifieldRegB(theInstr);
10363    UChar frC_addr = ifieldRegC(theInstr);
10364    UChar opc2     = ifieldOPClo5(theInstr);
10365    UChar flag_rC  = ifieldBIT0(theInstr);
10366 
10367    IRTemp  frD = newTemp(Ity_F64);
10368    IRTemp  frA = newTemp(Ity_F64);
10369    IRTemp  frB = newTemp(Ity_F64);
10370    IRTemp  frC = newTemp(Ity_F64);
10371    IRExpr* rm  = get_IR_roundingmode();
10372 
10373    /* By default, we will examine the results of the operation and set
10374       fpscr[FPRF] accordingly. */
10375    Bool set_FPRF = True;
10376 
10377    /* By default, if flag_RC is set, we will clear cr1 after the
10378       operation.  In reality we should set cr1 to indicate the
10379       exception status of the operation, but since we're not
10380       simulating exceptions, the exception status will appear to be
10381       zero.  Hence cr1 should be cleared if this is a . form insn. */
10382    Bool clear_CR1 = True;
10383 
10384    assign( frA, getFReg(frA_addr));
10385    assign( frB, getFReg(frB_addr));
10386    assign( frC, getFReg(frC_addr));
10387 
10388    switch (opc1) {
10389    case 0x3B:
10390       switch (opc2) {
10391       case 0x12: // fdivs (Floating Divide Single, PPC32 p407)
10392          if (frC_addr != 0)
10393             return False;
10394          DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10395              frD_addr, frA_addr, frB_addr);
10396          assign( frD, triop( Iop_DivF64r32,
10397                              rm, mkexpr(frA), mkexpr(frB) ));
10398          break;
10399 
10400       case 0x14: // fsubs (Floating Subtract Single, PPC32 p430)
10401          if (frC_addr != 0)
10402             return False;
10403          DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10404              frD_addr, frA_addr, frB_addr);
10405          assign( frD, triop( Iop_SubF64r32,
10406                              rm, mkexpr(frA), mkexpr(frB) ));
10407          break;
10408 
10409       case 0x15: // fadds (Floating Add Single, PPC32 p401)
10410          if (frC_addr != 0)
10411             return False;
10412          DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10413              frD_addr, frA_addr, frB_addr);
10414          assign( frD, triop( Iop_AddF64r32,
10415                              rm, mkexpr(frA), mkexpr(frB) ));
10416          break;
10417 
10418       case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428)
10419          // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
10420          if (frA_addr != 0 || frC_addr != 0)
10421             return False;
10422          DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? ".":"",
10423              frD_addr, frB_addr);
10424          // however illogically, on ppc970 this insn behaves identically
10425          // to fsqrt (double-precision).  So use SqrtF64, not SqrtF64r32.
10426          assign( frD, binop( Iop_SqrtF64, rm, mkexpr(frB) ));
10427          break;
10428 
10429       case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421)
10430          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
10431          if (frA_addr != 0 || frC_addr != 0)
10432             return False;
10433          DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"",
10434              frD_addr, frB_addr);
10435          { IRExpr* ieee_one
10436               = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
10437            assign( frD, triop( Iop_DivF64r32,
10438                                rm,
10439                                ieee_one, mkexpr(frB) ));
10440          }
10441          break;
10442 
10443       case 0x19: // fmuls (Floating Multiply Single, PPC32 p414)
10444          if (frB_addr != 0)
10445             return False;
10446          DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10447              frD_addr, frA_addr, frC_addr);
10448          assign( frD, triop( Iop_MulF64r32,
10449                              rm, mkexpr(frA), mkexpr(frC) ));
10450          break;
10451 
10452       case 0x1A: // frsqrtes (Floating Recip SqRt Est Single)
10453          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
10454          // Undocumented instruction?
10455          if (frA_addr != 0 || frC_addr != 0)
10456             return False;
10457          DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"",
10458              frD_addr, frB_addr);
10459          assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) );
10460          break;
10461 
10462       default:
10463          vex_printf("dis_fp_arith(ppc)(3B: opc2)\n");
10464          return False;
10465       }
10466       break;
10467 
10468    case 0x3F:
10469       switch (opc2) {
10470       case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406)
10471          if (frC_addr != 0)
10472             return False;
10473          DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10474              frD_addr, frA_addr, frB_addr);
10475          assign( frD, triop(Iop_DivF64, rm, mkexpr(frA), mkexpr(frB)) );
10476          break;
10477 
10478       case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429)
10479          if (frC_addr != 0)
10480             return False;
10481          DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10482              frD_addr, frA_addr, frB_addr);
10483          assign( frD, triop(Iop_SubF64, rm, mkexpr(frA), mkexpr(frB)) );
10484          break;
10485 
10486       case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400)
10487          if (frC_addr != 0)
10488             return False;
10489          DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10490              frD_addr, frA_addr, frB_addr);
10491          assign( frD, triop(Iop_AddF64, rm, mkexpr(frA), mkexpr(frB)) );
10492          break;
10493 
10494       case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427)
10495          // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
10496          if (frA_addr != 0 || frC_addr != 0)
10497             return False;
10498          DIP("fsqrt%s fr%u,fr%u\n", flag_rC ? ".":"",
10499              frD_addr, frB_addr);
10500          assign( frD, binop(Iop_SqrtF64, rm, mkexpr(frB)) );
10501          break;
10502 
10503       case 0x17: { // fsel (Floating Select, PPC32 p426)
10504          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
10505          IRTemp cc    = newTemp(Ity_I32);
10506          IRTemp cc_b0 = newTemp(Ity_I32);
10507 
10508          DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10509              frD_addr, frA_addr, frC_addr, frB_addr);
10510 
10511          // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40
10512          // => GT|EQ == (cc & 0x1 == 0)
10513          assign( cc, binop(Iop_CmpF64, mkexpr(frA),
10514                                        IRExpr_Const(IRConst_F64(0))) );
10515          assign( cc_b0, binop(Iop_And32, mkexpr(cc), mkU32(1)) );
10516 
10517          // frD = (frA >= 0.0) ? frC : frB
10518          //     = (cc_b0 == 0) ? frC : frB
10519          assign( frD,
10520                  IRExpr_ITE(
10521                     binop(Iop_CmpEQ32, mkexpr(cc_b0), mkU32(0)),
10522                     mkexpr(frC),
10523                     mkexpr(frB) ));
10524 
10525          /* One of the rare ones which don't mess with FPRF */
10526          set_FPRF = False;
10527          break;
10528       }
10529 
10530       case 0x18: // fre (Floating Reciprocal Estimate)
10531          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
10532          // Note: unclear whether this insn really exists or not
10533          // ppc970 doesn't have it, but POWER5 does
10534          if (frA_addr != 0 || frC_addr != 0)
10535             return False;
10536          DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"",
10537              frD_addr, frB_addr);
10538          { IRExpr* ieee_one
10539               = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
10540            assign( frD, triop( Iop_DivF64,
10541                                rm,
10542                                ieee_one, mkexpr(frB) ));
10543          }
10544          break;
10545 
10546       case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413)
10547          if (frB_addr != 0)
10548             vex_printf("dis_fp_arith(ppc)(instr,fmul)\n");
10549          DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10550              frD_addr, frA_addr, frC_addr);
10551          assign( frD, triop(Iop_MulF64, rm, mkexpr(frA), mkexpr(frC)) );
10552          break;
10553 
10554       case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424)
10555          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
10556          if (frA_addr != 0 || frC_addr != 0)
10557             return False;
10558          DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"",
10559              frD_addr, frB_addr);
10560          assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) );
10561          break;
10562 
10563       default:
10564          vex_printf("dis_fp_arith(ppc)(3F: opc2)\n");
10565          return False;
10566       }
10567       break;
10568 
10569    default:
10570       vex_printf("dis_fp_arith(ppc)(opc1)\n");
10571       return False;
10572    }
10573 
10574    putFReg( frD_addr, mkexpr(frD) );
10575 
10576    if (set_FPRF) {
10577       // XXX XXX XXX FIXME
10578       // set FPRF from frD
10579    }
10580 
10581    if (flag_rC && clear_CR1) {
10582       putCR321( 1, mkU8(0) );
10583       putCR0( 1, mkU8(0) );
10584    }
10585 
10586    return True;
10587 }
10588 
10589 
10590 
10591 /*
10592   Floating Point Mult-Add Instructions
10593 */
dis_fp_multadd(UInt theInstr)10594 static Bool dis_fp_multadd ( UInt theInstr )
10595 {
10596    /* A-Form */
10597    UChar opc1     = ifieldOPC(theInstr);
10598    UChar frD_addr = ifieldRegDS(theInstr);
10599    UChar frA_addr = ifieldRegA(theInstr);
10600    UChar frB_addr = ifieldRegB(theInstr);
10601    UChar frC_addr = ifieldRegC(theInstr);
10602    UChar opc2     = ifieldOPClo5(theInstr);
10603    UChar flag_rC  = ifieldBIT0(theInstr);
10604 
10605    IRTemp  frD = newTemp(Ity_F64);
10606    IRTemp  frA = newTemp(Ity_F64);
10607    IRTemp  frB = newTemp(Ity_F64);
10608    IRTemp  frC = newTemp(Ity_F64);
10609    IRTemp  rmt = newTemp(Ity_I32);
10610    IRTemp  tmp = newTemp(Ity_F64);
10611    IRTemp  sign_tmp = newTemp(Ity_I64);
10612    IRTemp  nan_mask = newTemp(Ity_I32);
10613    IRExpr* rm;
10614 
10615    /* By default, we will examine the results of the operation and set
10616       fpscr[FPRF] accordingly. */
10617    Bool set_FPRF = True;
10618 
10619    /* By default, if flag_RC is set, we will clear cr1 after the
10620       operation.  In reality we should set cr1 to indicate the
10621       exception status of the operation, but since we're not
10622       simulating exceptions, the exception status will appear to be
10623       zero.  Hence cr1 should be cleared if this is a . form insn. */
10624    Bool clear_CR1 = True;
10625 
10626    /* Bind the rounding mode expression to a temp; there's no
10627       point in creating gratuitous CSEs, as we know we'll need
10628       to use it twice. */
10629    assign( rmt, get_IR_roundingmode() );
10630    rm = mkexpr(rmt);
10631 
10632    assign( frA, getFReg(frA_addr));
10633    assign( frB, getFReg(frB_addr));
10634    assign( frC, getFReg(frC_addr));
10635 
10636    /* The rounding in this is all a bit dodgy.  The idea is to only do
10637       one rounding.  That clearly isn't achieveable without dedicated
10638       four-input IR primops, although in the single precision case we
10639       can sort-of simulate it by doing the inner multiply in double
10640       precision.
10641 
10642       In the negated cases, the negation happens after rounding. */
10643 
10644    switch (opc1) {
10645    case 0x3B:
10646       switch (opc2) {
10647       case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412)
10648          DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10649              frD_addr, frA_addr, frC_addr, frB_addr);
10650          assign( frD, qop( Iop_MSubF64r32, rm,
10651                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
10652          break;
10653 
10654       case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409)
10655          DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10656              frD_addr, frA_addr, frC_addr, frB_addr);
10657          assign( frD, qop( Iop_MAddF64r32, rm,
10658                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
10659          break;
10660 
10661       case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420)
10662       case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418)
10663 
10664          if (opc2 == 0x1E) {
10665             DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10666                      frD_addr, frA_addr, frC_addr, frB_addr);
10667             assign( tmp, qop( Iop_MSubF64r32, rm,
10668                               mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
10669          } else {
10670             DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10671                      frD_addr, frA_addr, frC_addr, frB_addr);
10672             assign( tmp, qop( Iop_MAddF64r32, rm,
10673                               mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
10674          }
10675 
10676          assign( nan_mask, Check_NaN( mkexpr( tmp ),
10677                                       mkU32( NANmaskSingle ) ) );
10678          assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ),
10679                                                mkexpr( nan_mask ) ) );
10680          assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) );
10681          break;
10682 
10683       default:
10684          vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n");
10685          return False;
10686       }
10687       break;
10688 
10689    case 0x3F:
10690       switch (opc2) {
10691       case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411)
10692          DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10693              frD_addr, frA_addr, frC_addr, frB_addr);
10694          assign( frD, qop( Iop_MSubF64, rm,
10695                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
10696          break;
10697 
10698       case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408)
10699          DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10700              frD_addr, frA_addr, frC_addr, frB_addr);
10701          assign( frD, qop( Iop_MAddF64, rm,
10702                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
10703          break;
10704 
10705       case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419)
10706       case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417)
10707 
10708          if (opc2 == 0x1E) {
10709             DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10710                      frD_addr, frA_addr, frC_addr, frB_addr);
10711             assign( tmp, qop( Iop_MSubF64, rm,
10712                               mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
10713          } else {
10714             DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
10715                      frD_addr, frA_addr, frC_addr, frB_addr);
10716             assign( tmp, qop( Iop_MAddF64, rm,
10717                               mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
10718          }
10719 
10720          assign( nan_mask, Check_NaN( mkexpr( tmp ),
10721                                       mkU32( NANmaskDouble ) ) );
10722          assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ),
10723                                                mkexpr( nan_mask ) ) );
10724          assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) );
10725          break;
10726 
10727       default:
10728          vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n");
10729          return False;
10730       }
10731       break;
10732 
10733    default:
10734       vex_printf("dis_fp_multadd(ppc)(opc1)\n");
10735       return False;
10736    }
10737 
10738    putFReg( frD_addr, mkexpr(frD) );
10739 
10740    if (set_FPRF) {
10741       // XXX XXX XXX FIXME
10742       // set FPRF from frD
10743    }
10744 
10745    if (flag_rC && clear_CR1) {
10746       putCR321( 1, mkU8(0) );
10747       putCR0( 1, mkU8(0) );
10748    }
10749 
10750    return True;
10751 }
10752 
10753 /*
10754  * fe_flag is set to 1 if any of the following conditions occurs:
10755  *  - The floating-point operand in register FRB is a Zero, a
10756  *    NaN, an Infinity, or a negative value.
10757  *  - e_b is less than or equal to: -970 for double precision; -103 for single precision
10758  *  Otherwise fe_flag is set to 0.
10759  *
10760  * fg_flag is set to 1 if either of the following conditions occurs.
10761  *   - The floating-point operand in register FRB is a Zero, an
10762  *     Infinity, or a denormalized value.
10763  *  Otherwise fg_flag is set to 0.
10764  *
10765  */
10766 
do_fp_tsqrt(IRTemp frB_Int,Bool sp,IRTemp * fe_flag_tmp,IRTemp * fg_flag_tmp)10767 static void do_fp_tsqrt(IRTemp frB_Int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
10768 {
10769    // The following temps are for holding intermediate results
10770    IRTemp e_b = newTemp(Ity_I32);
10771    IRExpr * fe_flag,  * fg_flag;
10772    IRTemp frB_exp_shR = newTemp(Ity_I32);
10773    UInt bias = sp? 127 : 1023;
10774    IRExpr * frbNaN, * frbDenorm, * frBNeg;
10775    IRExpr * eb_LTE;
10776    IRTemp  frbZero_tmp = newTemp(Ity_I1);
10777    IRTemp  frbInf_tmp = newTemp(Ity_I1);
10778    *fe_flag_tmp = newTemp(Ity_I32);
10779    *fg_flag_tmp = newTemp(Ity_I32);
10780 
10781    if ( sp )
10782       assign( frB_exp_shR, fp_exp_part( Ity_I32, frB_Int ) );
10783    else
10784       assign( frB_exp_shR, fp_exp_part( Ity_I64, frB_Int ) );
10785 
10786    assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
10787 
10788    //////////////////  fe_flag tests BEGIN //////////////////////
10789    /* We first do all tests that may result in setting fe_flag to '1'.
10790     * (NOTE: These tests are similar to those used for ftdiv.  See do_fp_tdiv()
10791     * for details.)
10792     */
10793    if ( sp ) {
10794       frbNaN = is_NaN( Ity_I32, frB_Int );
10795       assign( frbInf_tmp, is_Inf( Ity_I32, frB_Int ) );
10796       assign( frbZero_tmp, is_Zero( Ity_I32, frB_Int ) );
10797 
10798    } else {
10799       frbNaN = is_NaN( Ity_I64, frB_Int );
10800       assign( frbInf_tmp, is_Inf( Ity_I64, frB_Int ) );
10801       assign( frbZero_tmp, is_Zero( Ity_I64, frB_Int ) );
10802    }
10803 
10804    {
10805       // Test_value = -970 for double precision
10806       UInt test_value = sp ? 0xffffff99 : 0xfffffc36;
10807       eb_LTE = binop( Iop_CmpLE32S, mkexpr( e_b ), mkU32( test_value ) );
10808    }
10809    frBNeg = binop( Iop_CmpEQ32,
10810                    binop( Iop_Shr32,
10811                           sp ? mkexpr( frB_Int ) : unop( Iop_64HIto32, mkexpr( frB_Int ) ),
10812                           mkU8( 31 ) ),
10813                    mkU32( 1 ) );
10814    //////////////////  fe_flag tests END //////////////////////
10815 
10816    //////////////////  fg_flag tests BEGIN //////////////////////
10817    /*
10818     * The following tests were already performed above in the fe_flag
10819     * tests.  So these conditions will result in both fe_ and fg_ flags
10820     * being set.
10821     *   - Test if FRB is Zero
10822     *   - Test if FRB is an Infinity
10823     */
10824 
10825    /*
10826     * Test if FRB holds a denormalized value.  A denormalized value is one where
10827     * the exp is 0 and the fraction is non-zero.
10828     */
10829    if (sp) {
10830       IRTemp frac_part = newTemp(Ity_I32);
10831       assign( frac_part, binop( Iop_And32, mkexpr(frB_Int), mkU32(0x007fffff)) );
10832       frbDenorm
10833                = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
10834                          binop( Iop_CmpNE32, mkexpr( frac_part ), mkU32( 0 ) ) );
10835    } else {
10836       IRExpr * hi32, * low32, * fraction_is_nonzero;
10837       IRTemp frac_part = newTemp(Ity_I64);
10838 
10839       assign( frac_part, FP_FRAC_PART(frB_Int) );
10840       hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
10841       low32 = unop( Iop_64to32, mkexpr( frac_part ) );
10842       fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
10843                                                 mkU32( 0 ) );
10844       frbDenorm
10845                = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
10846                          fraction_is_nonzero );
10847    }
10848    //////////////////  fg_flag tests END //////////////////////
10849 
10850    /////////////////////////
10851    fe_flag = mkOR1( mkexpr( frbZero_tmp ),
10852                     mkOR1( frbNaN,
10853                            mkOR1( mkexpr( frbInf_tmp ),
10854                                   mkOR1( frBNeg, eb_LTE ) ) ) );
10855 
10856    fe_flag = unop(Iop_1Uto32, fe_flag);
10857 
10858    fg_flag = mkOR1( mkexpr( frbZero_tmp ),
10859                     mkOR1( mkexpr( frbInf_tmp ), frbDenorm ) );
10860    fg_flag = unop(Iop_1Uto32, fg_flag);
10861    assign (*fg_flag_tmp, fg_flag);
10862    assign (*fe_flag_tmp, fe_flag);
10863 }
10864 /*
10865  * fe_flag is set to 1 if any of the following conditions occurs:
10866  *  - The double-precision floating-point operand in register FRA is a NaN or an
10867  *    Infinity.
10868  *  - The double-precision floating-point operand in register FRB is a Zero, a
10869  *    NaN, or an Infinity.
10870  *  - e_b is less than or equal to -1022.
10871  *  - e_b is greater than or equal to 1021.
10872  *  - The double-precision floating-point operand in register FRA is not a zero
10873  *    and the difference, e_a - e_b, is greater than or equal to 1023.
10874  *  - The double-precision floating-point operand in register FRA is not a zero
10875  *    and the difference, e_a - e_b, is less than or equal to -1021.
10876  *  - The double-precision floating-point operand in register FRA is not a zero
10877  *    and e_a is less than or equal to -970
10878  *  Otherwise fe_flag is set to 0.
10879  *
10880  * fg_flag is set to 1 if either of the following conditions occurs.
10881  *   - The double-precision floating-point operand in register FRA is an Infinity.
10882  *   - The double-precision floating-point operand in register FRB is a Zero, an
10883  *     Infinity, or a denormalized value.
10884  *  Otherwise fg_flag is set to 0.
10885  *
10886  */
_do_fp_tdiv(IRTemp frA_int,IRTemp frB_int,Bool sp,IRTemp * fe_flag_tmp,IRTemp * fg_flag_tmp)10887 static void _do_fp_tdiv(IRTemp frA_int, IRTemp frB_int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
10888 {
10889    // The following temps are for holding intermediate results
10890    IRTemp e_a = newTemp(Ity_I32);
10891    IRTemp e_b = newTemp(Ity_I32);
10892    IRTemp frA_exp_shR = newTemp(Ity_I32);
10893    IRTemp frB_exp_shR = newTemp(Ity_I32);
10894 
10895    UInt bias = sp? 127 : 1023;
10896    *fe_flag_tmp = newTemp(Ity_I32);
10897    *fg_flag_tmp = newTemp(Ity_I32);
10898 
10899    /* The following variables hold boolean results from tests
10900     * that are OR'ed together for setting the fe_ and fg_ flags.
10901     * For some cases, the booleans are used more than once, so
10902     * I make those IRTemp's instead of IRExpr's.
10903     */
10904    IRExpr * fraNaN, * frbNaN, * frbDenorm;
10905    IRExpr * eb_LTE, * eb_GTE, * ea_eb_GTE, * ea_eb_LTE, * ea_LTE;
10906    IRTemp  fraInf_tmp = newTemp(Ity_I1);
10907    IRTemp  frbZero_tmp = newTemp(Ity_I1);
10908    IRTemp  frbInf_tmp = newTemp(Ity_I1);
10909    IRTemp  fraNotZero_tmp = newTemp(Ity_I1);
10910 
10911 /* The following are the flags that are set by OR'ing the results of
10912  * all the tests done for tdiv.  These flags are the input to the specified CR.
10913  */
10914    IRExpr * fe_flag, * fg_flag;
10915 
10916    // Create temps that will be used throughout the following tests.
10917    if ( sp ) {
10918       assign( frA_exp_shR, fp_exp_part( Ity_I32, frA_int ) );
10919       assign( frB_exp_shR, fp_exp_part( Ity_I32, frB_int ) );
10920    } else{
10921       assign( frA_exp_shR, fp_exp_part( Ity_I64, frA_int ) );
10922       assign( frB_exp_shR, fp_exp_part( Ity_I64, frB_int ) );
10923    }
10924 
10925    /* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */
10926    assign(e_a, binop( Iop_Sub32, mkexpr(frA_exp_shR), mkU32( bias ) ));
10927    assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
10928 
10929 
10930    //////////////////  fe_flag tests BEGIN //////////////////////
10931    /* We first do all tests that may result in setting fe_flag to '1'. */
10932 
10933    /*
10934     * Test if the double-precision floating-point operand in register FRA is
10935     * a NaN:
10936     */
10937    fraNaN = sp ? is_NaN( Ity_I32, frA_int ) : is_NaN( Ity_I64, frA_int );
10938    /*
10939     * Test if the double-precision floating-point operands in register FRA
10940     * and FRB is an Infinity.  Test if FRB is zero.
10941     */
10942    if ( sp ) {
10943       assign(fraInf_tmp, is_Inf( Ity_I32, frA_int ) );
10944       assign( frbInf_tmp, is_Inf( Ity_I32, frB_int ) );
10945       assign( frbZero_tmp, is_Zero( Ity_I32, frB_int ) );
10946 
10947    } else {
10948       assign(fraInf_tmp, is_Inf( Ity_I64, frA_int ) );
10949       assign( frbInf_tmp, is_Inf( Ity_I64, frB_int ) );
10950       assign( frbZero_tmp, is_Zero( Ity_I64, frB_int ) );
10951    }
10952    /*
10953     * Test if the double-precision floating-point operand in register FRB is
10954     * a NaN:
10955     */
10956    frbNaN = sp ? is_NaN( Ity_I32, frB_int ) : is_NaN( Ity_I64, frB_int );
10957 
10958    /*
10959     * Test if e_b <= -1022 for double precision;
10960     * or e_b <= -126 for single precision
10961     */
10962    {
10963       UInt test_value = sp ? 0xffffff82 : 0xfffffc02;
10964       eb_LTE = binop(Iop_CmpLE32S, mkexpr(e_b), mkU32(test_value));
10965    }
10966 
10967    /*
10968     * Test if e_b >= 1021 (i.e., 1021 < e_b) for double precision;
10969     * or e_b >= -125 (125 < e_b) for single precision
10970     */
10971    {
10972       Int test_value = sp ? 125 : 1021;
10973       eb_GTE = binop(Iop_CmpLT32S, mkU32(test_value), mkexpr(e_b));
10974    }
10975 
10976    /*
10977     * Test if FRA != Zero and (e_a - e_b) >= bias
10978     */
10979    if ( sp )
10980       assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( Ity_I32, frA_int ) ) );
10981    else
10982       assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( Ity_I64, frA_int ) ) );
10983 
10984    ea_eb_GTE = mkAND1( mkexpr( fraNotZero_tmp ),
10985                        binop( Iop_CmpLT32S, mkU32( bias ),
10986                               binop( Iop_Sub32, mkexpr( e_a ),
10987                                      mkexpr( e_b ) ) ) );
10988 
10989    /*
10990     * Test if FRA != Zero and (e_a - e_b) <= [-1021 (double precision) or -125 (single precision)]
10991     */
10992    {
10993       UInt test_value = sp ? 0xffffff83 : 0xfffffc03;
10994 
10995       ea_eb_LTE = mkAND1( mkexpr( fraNotZero_tmp ),
10996                           binop( Iop_CmpLE32S,
10997                                  binop( Iop_Sub32,
10998                                         mkexpr( e_a ),
10999                                         mkexpr( e_b ) ),
11000                                         mkU32( test_value ) ) );
11001    }
11002 
11003    /*
11004     * Test if FRA != Zero and e_a <= [-970 (double precision) or -103 (single precision)]
11005     */
11006    {
11007       UInt test_value = 0xfffffc36;  //Int test_value = -970;
11008 
11009       ea_LTE = mkAND1( mkexpr( fraNotZero_tmp ), binop( Iop_CmpLE32S,
11010                                                         mkexpr( e_a ),
11011                                                         mkU32( test_value ) ) );
11012    }
11013    //////////////////  fe_flag tests END //////////////////////
11014 
11015    //////////////////  fg_flag tests BEGIN //////////////////////
11016    /*
11017     * The following tests were already performed above in the fe_flag
11018     * tests.  So these conditions will result in both fe_ and fg_ flags
11019     * being set.
11020     *   - Test if FRA is an Infinity
11021     *   - Test if FRB ix Zero
11022     *   - Test if FRB is an Infinity
11023     */
11024 
11025    /*
11026     * Test if FRB holds a denormalized value.  A denormalized value is one where
11027     * the exp is 0 and the fraction is non-zero.
11028     */
11029    {
11030       IRExpr * fraction_is_nonzero;
11031 
11032       if (sp) {
11033          fraction_is_nonzero = binop( Iop_CmpNE32, FP_FRAC_PART32(frB_int),
11034                                       mkU32( 0 ) );
11035       } else {
11036          IRExpr * hi32, * low32;
11037          IRTemp frac_part = newTemp(Ity_I64);
11038          assign( frac_part, FP_FRAC_PART(frB_int) );
11039 
11040          hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
11041          low32 = unop( Iop_64to32, mkexpr( frac_part ) );
11042          fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
11043                                       mkU32( 0 ) );
11044       }
11045       frbDenorm = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ),
11046                                  mkU32( 0x0 ) ), fraction_is_nonzero );
11047 
11048    }
11049    //////////////////  fg_flag tests END //////////////////////
11050 
11051    fe_flag
11052    = mkOR1(
11053             fraNaN,
11054             mkOR1(
11055                    mkexpr( fraInf_tmp ),
11056                    mkOR1(
11057                           mkexpr( frbZero_tmp ),
11058                           mkOR1(
11059                                  frbNaN,
11060                                  mkOR1(
11061                                         mkexpr( frbInf_tmp ),
11062                                         mkOR1( eb_LTE,
11063                                                mkOR1( eb_GTE,
11064                                                       mkOR1( ea_eb_GTE,
11065                                                              mkOR1( ea_eb_LTE,
11066                                                                     ea_LTE ) ) ) ) ) ) ) ) );
11067 
11068    fe_flag = unop(Iop_1Uto32, fe_flag);
11069 
11070    fg_flag = mkOR1( mkexpr( fraInf_tmp ), mkOR1( mkexpr( frbZero_tmp ),
11071                                                  mkOR1( mkexpr( frbInf_tmp ),
11072                                                         frbDenorm ) ) );
11073    fg_flag = unop(Iop_1Uto32, fg_flag);
11074    assign(*fe_flag_tmp, fe_flag);
11075    assign(*fg_flag_tmp, fg_flag);
11076 }
11077 
11078 /* See description for _do_fp_tdiv() above. */
do_fp_tdiv(IRTemp frA_int,IRTemp frB_int)11079 static IRExpr * do_fp_tdiv(IRTemp frA_int, IRTemp frB_int)
11080 {
11081    IRTemp  fe_flag, fg_flag;
11082    /////////////////////////
11083    /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
11084     * where fl_flag == 1 on ppc64.
11085     */
11086    IRExpr * fl_flag = unop(Iop_Not32, mkU32(0xFFFFFE));
11087    fe_flag = fg_flag = IRTemp_INVALID;
11088    _do_fp_tdiv(frA_int, frB_int, False/*not single precision*/, &fe_flag, &fg_flag);
11089    return binop( Iop_Or32,
11090                  binop( Iop_Or32,
11091                         binop( Iop_Shl32, fl_flag, mkU8( 3 ) ),
11092                         binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
11093                  binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) );
11094 }
11095 
dis_fp_tests(UInt theInstr)11096 static Bool dis_fp_tests ( UInt theInstr )
11097 {
11098    UChar opc1     = ifieldOPC(theInstr);
11099    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
11100    UChar frB_addr = ifieldRegB(theInstr);
11101    UChar b0       = ifieldBIT0(theInstr);
11102    UInt  opc2     = ifieldOPClo10(theInstr);
11103    IRTemp frB_I64     = newTemp(Ity_I64);
11104 
11105    if (opc1 != 0x3F || b0 != 0 ){
11106       vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
11107       return False;
11108    }
11109    assign( frB_I64, unop( Iop_ReinterpF64asI64, getFReg( frB_addr ) ) );
11110 
11111    switch (opc2) {
11112       case 0x080: // ftdiv
11113       {
11114          UChar frA_addr = ifieldRegA(theInstr);
11115          IRTemp frA_I64     = newTemp(Ity_I64);
11116          UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
11117          if (b21to22 != 0 ) {
11118             vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
11119             return False;
11120          }
11121 
11122          assign( frA_I64, unop( Iop_ReinterpF64asI64, getFReg( frA_addr ) ) );
11123          putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
11124 
11125          DIP("ftdiv crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
11126          break;
11127       }
11128       case 0x0A0: // ftsqrt
11129       {
11130          IRTemp flags = newTemp(Ity_I32);
11131          IRTemp  fe_flag, fg_flag;
11132          fe_flag = fg_flag = IRTemp_INVALID;
11133          UChar b18to22  = toUChar( IFIELD( theInstr, 18, 5 ) );
11134          if ( b18to22 != 0) {
11135             vex_printf("dis_fp_tests(ppc)(ftsqrt)\n");
11136             return False;
11137          }
11138          DIP("ftsqrt crf%d,fr%u\n", crfD, frB_addr);
11139          do_fp_tsqrt(frB_I64, False /* not single precision*/, &fe_flag, &fg_flag);
11140          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
11141           * where fl_flag == 1 on ppc64.
11142           */
11143          assign( flags,
11144                  binop( Iop_Or32,
11145                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
11146                                binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
11147                         binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
11148          putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
11149          break;
11150       }
11151 
11152       default:
11153          vex_printf("dis_fp_tests(ppc)(opc2)\n");
11154          return False;
11155 
11156    }
11157    return True;
11158 }
11159 
11160 /*
11161   Floating Point Compare Instructions
11162 */
dis_fp_cmp(UInt theInstr)11163 static Bool dis_fp_cmp ( UInt theInstr )
11164 {
11165    /* X-Form */
11166    UChar opc1     = ifieldOPC(theInstr);
11167    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
11168    UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
11169    UChar frA_addr = ifieldRegA(theInstr);
11170    UChar frB_addr = ifieldRegB(theInstr);
11171    UInt  opc2     = ifieldOPClo10(theInstr);
11172    UChar b0       = ifieldBIT0(theInstr);
11173 
11174    IRTemp ccIR    = newTemp(Ity_I32);
11175    IRTemp ccPPC32 = newTemp(Ity_I32);
11176 
11177    IRTemp frA     = newTemp(Ity_F64);
11178    IRTemp frB     = newTemp(Ity_F64);
11179 
11180    if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) {
11181       vex_printf("dis_fp_cmp(ppc)(instr)\n");
11182       return False;
11183    }
11184 
11185    assign( frA, getFReg(frA_addr));
11186    assign( frB, getFReg(frB_addr));
11187 
11188    assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) );
11189 
11190    /* Map compare result from IR to PPC32 */
11191    /*
11192      FP cmp result | PPC | IR
11193      --------------------------
11194      UN            | 0x1 | 0x45
11195      EQ            | 0x2 | 0x40
11196      GT            | 0x4 | 0x00
11197      LT            | 0x8 | 0x01
11198    */
11199 
11200    // ccPPC32 = Shl(1, (~(ccIR>>5) & 2)
11201    //                    | ((ccIR ^ (ccIR>>6)) & 1)
11202    assign(
11203       ccPPC32,
11204       binop(
11205          Iop_Shl32,
11206          mkU32(1),
11207          unop(
11208             Iop_32to8,
11209             binop(
11210                Iop_Or32,
11211                binop(
11212                   Iop_And32,
11213                   unop(
11214                      Iop_Not32,
11215                      binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))
11216                   ),
11217                   mkU32(2)
11218                ),
11219                binop(
11220                   Iop_And32,
11221                   binop(
11222                      Iop_Xor32,
11223                      mkexpr(ccIR),
11224                      binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))
11225                   ),
11226                   mkU32(1)
11227                )
11228             )
11229          )
11230       )
11231    );
11232 
11233    putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
11234    putFPCC( mkexpr( ccPPC32 ) );
11235 
11236    // XXX XXX XXX FIXME
11237    // Also write the result into FPRF (it's not entirely clear how)
11238 
11239    /* Note: Differences between fcmpu and fcmpo are only in exception
11240       flag settings, which aren't supported anyway. */
11241    switch (opc2) {
11242    case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403)
11243       DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
11244       break;
11245    case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402)
11246       DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
11247       break;
11248    default:
11249       vex_printf("dis_fp_cmp(ppc)(opc2)\n");
11250       return False;
11251    }
11252    return True;
11253 }
11254 
11255 
11256 
11257 /*
11258   Floating Point Rounding/Conversion Instructions
11259 */
dis_fp_round(UInt theInstr)11260 static Bool dis_fp_round ( UInt theInstr )
11261 {
11262    /* X-Form */
11263    UChar opc1     = ifieldOPC(theInstr);
11264    UChar b16to20  = ifieldRegA(theInstr);
11265    UChar frD_addr = ifieldRegDS(theInstr);
11266    UChar frB_addr = ifieldRegB(theInstr);
11267    UInt  opc2     = ifieldOPClo10(theInstr);
11268    UChar flag_rC  = ifieldBIT0(theInstr);
11269 
11270    IRTemp  frD     = newTemp(Ity_F64);
11271    IRTemp  frB     = newTemp(Ity_F64);
11272    IRTemp  r_tmp32 = newTemp(Ity_I32);
11273    IRTemp  r_tmp64 = newTemp(Ity_I64);
11274    IRExpr* rm      = get_IR_roundingmode();
11275 
11276    /* By default, we will examine the results of the operation and set
11277       fpscr[FPRF] accordingly. */
11278    Bool set_FPRF = True;
11279 
11280    /* By default, if flag_RC is set, we will clear cr1 after the
11281       operation.  In reality we should set cr1 to indicate the
11282       exception status of the operation, but since we're not
11283       simulating exceptions, the exception status will appear to be
11284       zero.  Hence cr1 should be cleared if this is a . form insn. */
11285    Bool clear_CR1 = True;
11286    if ((!(opc1 == 0x3F || opc1 == 0x3B)) || b16to20 != 0) {
11287       vex_printf("dis_fp_round(ppc)(instr)\n");
11288       return False;
11289    }
11290 
11291    assign( frB, getFReg(frB_addr));
11292    if (opc1 == 0x3B) {
11293       /* The fcfid[u]s instructions (from ISA 2.06) are a bit odd because
11294        * they're very similar to the other instructions handled here, but have
11295        * a different primary opcode.
11296        */
11297       switch (opc2) {
11298          case 0x34E: // fcfids (Float convert from signed DWord to single precision)
11299             DIP("fcfids%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11300             assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
11301             assign( frD, binop( Iop_RoundF64toF32, rm, binop( Iop_I64StoF64, rm,
11302                                                               mkexpr( r_tmp64 ) ) ) );
11303             goto putFR;
11304 
11305          case 0x3Ce: // fcfidus (Float convert from unsigned DWord to single precision)
11306             DIP("fcfidus%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11307             assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
11308             assign( frD, unop( Iop_F32toF64, binop( Iop_I64UtoF32, rm, mkexpr( r_tmp64 ) ) ) );
11309             goto putFR;
11310       }
11311    }
11312 
11313 
11314    switch (opc2) {
11315    case 0x00C: // frsp (Float Round to Single, PPC32 p423)
11316       DIP("frsp%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11317       assign( frD, binop( Iop_RoundF64toF32, rm, mkexpr(frB) ));
11318       break;
11319 
11320    case 0x00E: // fctiw (Float Conv to Int, PPC32 p404)
11321       DIP("fctiw%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11322       assign( r_tmp32,
11323               binop(Iop_F64toI32S, rm, mkexpr(frB)) );
11324       assign( frD, unop( Iop_ReinterpI64asF64,
11325                          unop( Iop_32Uto64, mkexpr(r_tmp32))));
11326       /* FPRF is undefined after fctiw.  Leave unchanged. */
11327       set_FPRF = False;
11328       break;
11329 
11330    case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405)
11331       DIP("fctiwz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11332       assign( r_tmp32,
11333               binop(Iop_F64toI32S, mkU32(Irrm_ZERO), mkexpr(frB) ));
11334       assign( frD, unop( Iop_ReinterpI64asF64,
11335                          unop( Iop_32Uto64, mkexpr(r_tmp32))));
11336       /* FPRF is undefined after fctiwz.  Leave unchanged. */
11337       set_FPRF = False;
11338       break;
11339 
11340    case 0x08F: case 0x08E: // fctiwu[z]
11341       DIP("fctiwu%s%s fr%u,fr%u\n", opc2 == 0x08F ? "z" : "",
11342                flag_rC ? ".":"", frD_addr, frB_addr);
11343       assign( r_tmp32,
11344               binop( Iop_F64toI32U,
11345                      opc2 == 0x08F ? mkU32( Irrm_ZERO ) : rm,
11346                      mkexpr( frB ) ) );
11347       assign( frD, unop( Iop_ReinterpI64asF64,
11348                          unop( Iop_32Uto64, mkexpr(r_tmp32))));
11349       /* FPRF is undefined after fctiwz.  Leave unchanged. */
11350       set_FPRF = False;
11351       break;
11352 
11353 
11354    case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437)
11355       DIP("fctid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11356       assign( r_tmp64,
11357               binop(Iop_F64toI64S, rm, mkexpr(frB)) );
11358       assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
11359       /* FPRF is undefined after fctid.  Leave unchanged. */
11360       set_FPRF = False;
11361       break;
11362 
11363    case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437)
11364       DIP("fctidz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11365       assign( r_tmp64,
11366               binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
11367       assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
11368       /* FPRF is undefined after fctidz.  Leave unchanged. */
11369       set_FPRF = False;
11370       break;
11371 
11372    case 0x3AE: case 0x3AF: // fctidu[z] (Float Conv to Int DWord Unsigned [Round to Zero])
11373    {
11374       DIP("fctidu%s%s fr%u,fr%u\n", opc2 == 0x3AE ? "" : "z",
11375                flag_rC ? ".":"", frD_addr, frB_addr);
11376       assign( r_tmp64,
11377               binop(Iop_F64toI64U, opc2 == 0x3AE ? rm : mkU32(Irrm_ZERO), mkexpr(frB)) );
11378       assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
11379       /* FPRF is undefined after fctidz.  Leave unchanged. */
11380       set_FPRF = False;
11381       break;
11382    }
11383    case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434)
11384       DIP("fcfid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11385       assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
11386       assign( frD,
11387               binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) );
11388       break;
11389 
11390    case 0x3CE: // fcfidu (Float convert from unsigned DWord)
11391       DIP("fcfidu%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11392       assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
11393       assign( frD, binop( Iop_I64UtoF64, rm, mkexpr( r_tmp64 ) ) );
11394       break;
11395 
11396    case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim
11397       switch(opc2) {
11398       case 0x188: // frin (Floating Round to Integer Nearest)
11399          DIP("frin%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11400          assign( r_tmp64,
11401                  binop(Iop_F64toI64S, mkU32(Irrm_NEAREST), mkexpr(frB)) );
11402          break;
11403       case 0x1A8: // friz (Floating Round to Integer Toward Zero)
11404          DIP("friz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11405          assign( r_tmp64,
11406                  binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
11407          break;
11408       case 0x1C8: // frip (Floating Round to Integer Plus)
11409          DIP("frip%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11410          assign( r_tmp64,
11411                  binop(Iop_F64toI64S, mkU32(Irrm_PosINF), mkexpr(frB)) );
11412          break;
11413       case 0x1E8: // frim (Floating Round to Integer Minus)
11414          DIP("frim%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11415          assign( r_tmp64,
11416                  binop(Iop_F64toI64S, mkU32(Irrm_NegINF), mkexpr(frB)) );
11417          break;
11418       }
11419 
11420       /* don't use the rounded integer if frB is outside -9e18..9e18 */
11421       /* F64 has only log10(2**52) significant digits anyway */
11422       /* need to preserve sign of zero */
11423       /*   frD = (fabs(frB) > 9e18) ? frB :
11424                (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64  */
11425       assign(frD, IRExpr_ITE(
11426                      binop(Iop_CmpNE8,
11427                            unop(Iop_32to8,
11428                                 binop(Iop_CmpF64,
11429                                       IRExpr_Const(IRConst_F64(9e18)),
11430                                       unop(Iop_AbsF64, mkexpr(frB)))),
11431                            mkU8(0)),
11432                      mkexpr(frB),
11433                      IRExpr_ITE(
11434                         binop(Iop_CmpNE32,
11435                               binop(Iop_Shr32,
11436                                     unop(Iop_64HIto32,
11437                                          unop(Iop_ReinterpF64asI64,
11438                                               mkexpr(frB))),
11439                                     mkU8(31)),
11440                               mkU32(0)),
11441                         unop(Iop_NegF64,
11442                              unop( Iop_AbsF64,
11443                                    binop(Iop_I64StoF64, mkU32(0),
11444                                          mkexpr(r_tmp64)) )),
11445                         binop(Iop_I64StoF64, mkU32(0), mkexpr(r_tmp64) )
11446                      )
11447       ));
11448       break;
11449 
11450    default:
11451       vex_printf("dis_fp_round(ppc)(opc2)\n");
11452       return False;
11453    }
11454 putFR:
11455    putFReg( frD_addr, mkexpr(frD) );
11456 
11457    if (set_FPRF) {
11458       // XXX XXX XXX FIXME
11459       // set FPRF from frD
11460    }
11461 
11462    if (flag_rC && clear_CR1) {
11463       putCR321( 1, mkU8(0) );
11464       putCR0( 1, mkU8(0) );
11465    }
11466 
11467    return True;
11468 }
11469 
11470 /*
11471   Floating Point Pair Instructions
11472 */
dis_fp_pair(UInt theInstr)11473 static Bool dis_fp_pair ( UInt theInstr )
11474 {
11475    /* X-Form/DS-Form */
11476    UChar  opc1         = ifieldOPC(theInstr);
11477    UChar  frT_hi_addr  = ifieldRegDS(theInstr);
11478    UChar  frT_lo_addr  = frT_hi_addr + 1;
11479    UChar  rA_addr      = ifieldRegA(theInstr);
11480    UChar  rB_addr      = ifieldRegB(theInstr);
11481    UInt  uimm16        = ifieldUIMM16(theInstr);
11482    Int    simm16       = extend_s_16to32(uimm16);
11483    UInt   opc2         = ifieldOPClo10(theInstr);
11484    IRType ty           = mode64 ? Ity_I64 : Ity_I32;
11485    IRTemp EA_hi        = newTemp(ty);
11486    IRTemp EA_lo        = newTemp(ty);
11487    IRTemp frT_hi       = newTemp(Ity_F64);
11488    IRTemp frT_lo       = newTemp(Ity_F64);
11489    UChar b0            = ifieldBIT0(theInstr);
11490    Bool is_load        = 0;
11491 
11492    switch (opc1) {
11493    case 0x1F: // register offset
11494       /* These instructions work on a pair of registers.  The specified
11495        * register must be even.
11496        */
11497       if ((frT_hi_addr %2) != 0) {
11498          vex_printf("dis_fp_pair(ppc) ldpx or stdpx: odd frT register\n");
11499          return False;
11500       }
11501 
11502       switch(opc2) {
11503       case 0x317:     // lfdpx (FP Load Double Pair X-form, ISA 2.05  p125)
11504          DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
11505          is_load = 1;
11506          break;
11507       case 0x397:     // stfdpx (FP STORE Double Pair X-form, ISA 2.05  p125)
11508          DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
11509          break;
11510       default:
11511          vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n");
11512          return False;
11513       }
11514 
11515       if (b0 != 0) {
11516          vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n");
11517          return False;
11518       }
11519       assign( EA_hi, ea_rAor0_idxd( rA_addr, rB_addr ) );
11520       break;
11521    case 0x39:
11522    {
11523       UInt  DS  = IFIELD( theInstr, 2, 14);
11524       UChar vRT = ifieldRegDS(theInstr);
11525       IRTemp EA = newTemp( ty );
11526 
11527       opc2 = ifieldOPC0o2(theInstr);
11528 
11529       switch(opc2) {
11530       case 0x0:     // lfdp (FP Load Double Pair DS-form, ISA 2.05  p125)
11531          /* This instruction works on a pair of registers.  The specified
11532           * register must be even.
11533           */
11534          if ((frT_hi_addr %2) != 0) {
11535             vex_printf("dis_fp_pair(ppc) lfdp : odd frT register\n");
11536             return False;
11537          }
11538 
11539          DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
11540          assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
11541          is_load = 1;
11542          break;
11543 
11544       case 0x2:     // lxsd (Load VSX Scalar Doubleword)
11545          DIP("lxsd v%u,%d(r%u)\n", vRT, DS, rA_addr);
11546 
11547          assign( EA, ea_rAor0_simm( rA_addr, DS<<2  ) );
11548 
11549          putVSReg( vRT+32, binop( Iop_64HLtoV128,
11550                                   load( Ity_I64, mkexpr( EA ) ),
11551                                   mkU64( 0 ) ) );
11552          return True;
11553 
11554       case 0x3:     // lxssp (Load VSX Scalar Single from memory,
11555                     // store as double in register)
11556          DIP("lxssp v%u,%d(r%u)\n", vRT, DS, rA_addr);
11557 
11558          assign( EA, ea_rAor0_simm( rA_addr, DS<<2  ) );
11559 
11560          putVSReg( vRT+32,
11561                    binop( Iop_64HLtoV128,
11562                           unop( Iop_ReinterpF64asI64,
11563                                 unop( Iop_F32toF64,
11564                                       unop( Iop_ReinterpI32asF32,
11565                                             load( Ity_I32, mkexpr( EA ) ) ) ) ),
11566 				mkU64( 0 ) ) );
11567          return True;
11568 
11569       default:
11570          vex_printf("dis_fp_pair(ppc) : DS-form wrong opc2\n");
11571          return False;
11572       }
11573       break;
11574    }
11575    case 0x3d:
11576    {
11577       UInt  DS  = IFIELD( theInstr, 2, 14);
11578       UChar vRS = ifieldRegDS(theInstr);
11579       IRTemp EA = newTemp( ty );
11580 
11581       opc2 = ifieldOPC0o2(theInstr);
11582 
11583       switch(opc2) {
11584       case 0x0:
11585          // stfdp (FP Store Double Pair DS-form, ISA 2.05  p125)
11586          /* This instruction works on a pair of registers.  The specified
11587           * register must be even.
11588           */
11589          if ((frT_hi_addr %2) != 0) {
11590             vex_printf("dis_fp_pair(ppc) stfdp : odd frT register\n");
11591             return False;
11592          }
11593 
11594          DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
11595          assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
11596          break;
11597 
11598       case 0x1:
11599       {
11600          UInt ea_off = 8;
11601          IRTemp word[2];
11602          IRExpr* irx_addr;
11603          UInt  T  = IFIELD( theInstr, 21, 5);  // T or S depending on inst
11604          UInt  TX = IFIELD( theInstr,  3, 1);  // TX or SX field
11605 
11606          word[0] = newTemp(Ity_I64);
11607          word[1] = newTemp(Ity_I64);
11608          DS  = IFIELD( theInstr, 4, 12);   // DQ in the instruction definition
11609          assign( EA, ea_rAor0_simm( rA_addr, DS<<4  ) );
11610 
11611          if ( IFIELD( theInstr, 0, 3) == 1) {
11612             // lxv (Load VSX Vector)
11613             DIP("lxv v%u,%d(r%u)\n", vRS, DS, rA_addr);
11614 
11615             assign( word[0], load( Ity_I64, mkexpr( EA ) ) );
11616 
11617             irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
11618                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
11619 
11620             assign( word[1], load( Ity_I64, irx_addr ) );
11621 
11622             if (host_endness == VexEndnessBE)
11623                putVSReg( TX*32+T, binop( Iop_64HLtoV128,
11624                                          mkexpr( word[0] ),
11625                                          mkexpr( word[1] ) ) );
11626             else
11627                putVSReg( TX*32+T, binop( Iop_64HLtoV128,
11628                                          mkexpr( word[1] ),
11629                                          mkexpr( word[0] ) ) );
11630             return True;
11631 
11632          } else if ( IFIELD( theInstr, 0, 3) == 5) {
11633             // stxv (Store VSX Vector)
11634             DIP("stxv v%u,%d(r%u)\n", vRS, DS, rA_addr);
11635 
11636             if (host_endness == VexEndnessBE) {
11637                store( mkexpr(EA), unop( Iop_V128HIto64,
11638                                         getVSReg( TX*32+T ) ) );
11639                irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
11640                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
11641                store( irx_addr, unop( Iop_V128to64,
11642                                        getVSReg( TX*32+T ) ) );
11643             } else {
11644                store( mkexpr(EA), unop( Iop_V128to64,
11645                                         getVSReg( TX*32+T ) ) );
11646                irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
11647                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
11648                store( irx_addr, unop( Iop_V128HIto64,
11649                                       getVSReg( TX*32+T ) ) );
11650             }
11651             return True;
11652 
11653          } else {
11654             vex_printf("dis_fp_pair vector load/store (ppc) : DS-form wrong opc2\n");
11655             return False;
11656          }
11657          break;
11658       }
11659       case 0x2:
11660          // stxsd (Store VSX Scalar Doubleword)
11661          DIP("stxsd v%u,%d(r%u)\n", vRS, DS, rA_addr);
11662 
11663          assign( EA, ea_rAor0_simm( rA_addr, DS<<2  ) );
11664 
11665          store( mkexpr(EA), unop( Iop_V128HIto64,
11666                                   getVSReg( vRS+32 ) ) );
11667          /* HW is clearing vector element 1.  Don't see that in the ISA but
11668           * matching the HW.
11669           */
11670          putVSReg( vRS+32, binop( Iop_64HLtoV128,
11671                                   unop( Iop_V128HIto64,
11672                                         getVSReg( vRS+32 ) ),
11673                                   mkU64( 0 ) ) );
11674          return True;
11675 
11676       case 0x3:
11677       {
11678          // stxssp (Store VSX Scalar Single - store double precision
11679          // value from register into memory in single precision format)
11680          IRTemp high64 = newTemp(Ity_F64);
11681          IRTemp val32  = newTemp(Ity_I32);
11682 
11683          DIP("stxssp v%u,%d(r%u)\n", vRS, DS, rA_addr);
11684 
11685          assign( EA, ea_rAor0_simm( rA_addr, DS<<2  ) );
11686          assign(high64, unop( Iop_ReinterpI64asF64,
11687                               unop( Iop_V128HIto64, getVSReg( vRS+32 ) ) ) );
11688 
11689          assign(val32, unop( Iop_ReinterpF32asI32,
11690                              unop( Iop_TruncF64asF32,
11691                                    mkexpr(high64) ) ) );
11692          store( mkexpr(EA), mkexpr( val32 ) );
11693 
11694          return True;
11695       }
11696       default:
11697          vex_printf("dis_fp_pair(ppc) : DS-form wrong opc2\n");
11698          return False;
11699       }
11700       break;
11701    }
11702    default:   // immediate offset
11703       vex_printf("dis_fp_pair(ppc)(instr)\n");
11704       return False;
11705    }
11706 
11707    if (mode64)
11708       assign( EA_lo, binop(Iop_Add64, mkexpr(EA_hi), mkU64(8)) );
11709    else
11710       assign( EA_lo, binop(Iop_Add32, mkexpr(EA_hi), mkU32(8)) );
11711 
11712    assign( frT_hi, getFReg(frT_hi_addr) );
11713    assign( frT_lo, getFReg(frT_lo_addr) );
11714 
11715    if (is_load) {
11716       putFReg( frT_hi_addr, load(Ity_F64, mkexpr(EA_hi)) );
11717       putFReg( frT_lo_addr, load(Ity_F64, mkexpr(EA_lo)) );
11718    } else {
11719       store( mkexpr(EA_hi), mkexpr(frT_hi) );
11720       store( mkexpr(EA_lo), mkexpr(frT_lo) );
11721    }
11722 
11723    return True;
11724 }
11725 
11726 
11727 /*
11728   Floating Point Merge Instructions
11729 */
dis_fp_merge(UInt theInstr)11730 static Bool dis_fp_merge ( UInt theInstr )
11731 {
11732    /* X-Form */
11733    UInt  opc2     = ifieldOPClo10(theInstr);
11734    UChar frD_addr = ifieldRegDS(theInstr);
11735    UChar frA_addr = ifieldRegA(theInstr);
11736    UChar frB_addr = ifieldRegB(theInstr);
11737 
11738    IRTemp frD = newTemp(Ity_F64);
11739    IRTemp frA = newTemp(Ity_F64);
11740    IRTemp frB = newTemp(Ity_F64);
11741 
11742    assign( frA, getFReg(frA_addr));
11743    assign( frB, getFReg(frB_addr));
11744 
11745    switch (opc2) {
11746    case 0x3c6: // fmrgew floating merge even word
11747       DIP("fmrgew fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr);
11748 
11749       assign( frD, unop( Iop_ReinterpI64asF64,
11750                          binop( Iop_32HLto64,
11751                                 unop( Iop_64HIto32,
11752                                       unop( Iop_ReinterpF64asI64,
11753                                             mkexpr(frA) ) ),
11754                                 unop( Iop_64HIto32,
11755                                       unop( Iop_ReinterpF64asI64,
11756                                             mkexpr(frB) ) ) ) ) );
11757    break;
11758 
11759    case 0x346: // fmrgow floating merge odd word
11760       DIP("fmrgow fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr);
11761 
11762       assign( frD, unop( Iop_ReinterpI64asF64,
11763                          binop( Iop_32HLto64,
11764                                 unop( Iop_64to32,
11765                                       unop( Iop_ReinterpF64asI64,
11766                                             mkexpr(frA) ) ),
11767                                 unop( Iop_64to32,
11768                                       unop( Iop_ReinterpF64asI64,
11769                                             mkexpr(frB) ) ) ) ) );
11770    break;
11771 
11772    default:
11773       vex_printf("dis_fp_merge(ppc)(opc2)\n");
11774       return False;
11775    }
11776 
11777    putFReg( frD_addr, mkexpr(frD) );
11778    return True;
11779 }
11780 
11781 /*
11782   Floating Point Move Instructions
11783 */
dis_fp_move(UInt theInstr)11784 static Bool dis_fp_move ( UInt theInstr )
11785 {
11786    /* X-Form */
11787    UChar opc1     = ifieldOPC(theInstr);
11788    UChar frD_addr = ifieldRegDS(theInstr);
11789    UChar frA_addr = ifieldRegA(theInstr);
11790    UChar frB_addr = ifieldRegB(theInstr);
11791    UInt  opc2     = ifieldOPClo10(theInstr);
11792    UChar flag_rC  = ifieldBIT0(theInstr);
11793 
11794    IRTemp frD = newTemp(Ity_F64);
11795    IRTemp frB = newTemp(Ity_F64);
11796    IRTemp itmpB = newTemp(Ity_F64);
11797    IRTemp frA;
11798    IRTemp signA;
11799    IRTemp hiD;
11800 
11801    if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) {
11802       vex_printf("dis_fp_move(ppc)(instr)\n");
11803       return False;
11804    }
11805 
11806    assign( frB, getFReg(frB_addr));
11807 
11808    switch (opc2) {
11809    case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126)
11810       DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frA_addr,
11811           frB_addr);
11812       signA = newTemp(Ity_I32);
11813       hiD = newTemp(Ity_I32);
11814       itmpB = newTemp(Ity_I64);
11815       frA = newTemp(Ity_F64);
11816       assign( frA, getFReg(frA_addr) );
11817 
11818       /* get A's sign bit */
11819       assign(signA, binop(Iop_And32,
11820                           unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64,
11821                                                   mkexpr(frA))),
11822                           mkU32(0x80000000)) );
11823 
11824       assign( itmpB, unop(Iop_ReinterpF64asI64, mkexpr(frB)) );
11825 
11826       /* mask off B's sign bit and or in A's sign bit */
11827       assign(hiD, binop(Iop_Or32,
11828                         binop(Iop_And32,
11829                               unop(Iop_64HIto32,
11830                                    mkexpr(itmpB)),  /* frB's high 32 bits */
11831                               mkU32(0x7fffffff)),
11832                         mkexpr(signA)) );
11833 
11834       /* combine hiD/loB into frD */
11835       assign( frD, unop(Iop_ReinterpI64asF64,
11836                         binop(Iop_32HLto64,
11837                               mkexpr(hiD),
11838                               unop(Iop_64to32,
11839                                    mkexpr(itmpB)))) );   /* frB's low 32 bits */
11840       break;
11841 
11842    case 0x028: // fneg (Floating Negate, PPC32 p416)
11843       DIP("fneg%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11844       assign( frD, unop( Iop_NegF64, mkexpr(frB) ));
11845       break;
11846 
11847    case 0x048: // fmr (Floating Move Register, PPC32 p410)
11848       DIP("fmr%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11849       assign( frD, mkexpr(frB) );
11850       break;
11851 
11852    case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415)
11853       DIP("fnabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11854       assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) )));
11855       break;
11856 
11857    case 0x108: // fabs (Floating Absolute Value, PPC32 p399)
11858       DIP("fabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
11859       assign( frD, unop( Iop_AbsF64, mkexpr(frB) ));
11860       break;
11861 
11862    default:
11863       vex_printf("dis_fp_move(ppc)(opc2)\n");
11864       return False;
11865    }
11866 
11867    putFReg( frD_addr, mkexpr(frD) );
11868 
11869    /* None of these change FPRF.  cr1 is set in the usual way though,
11870       if flag_rC is set. */
11871 
11872    if (flag_rC) {
11873       putCR321( 1, mkU8(0) );
11874       putCR0( 1, mkU8(0) );
11875    }
11876 
11877    return True;
11878 }
11879 
11880 
11881 
11882 /*
11883   Floating Point Status/Control Register Instructions
11884 */
dis_fp_scr(UInt theInstr,Bool GX_level)11885 static Bool dis_fp_scr ( UInt theInstr, Bool GX_level )
11886 {
11887    /* Many forms - see each switch case */
11888    UChar opc1    = ifieldOPC(theInstr);
11889    UInt  opc2    = ifieldOPClo10(theInstr);
11890    UChar flag_rC = ifieldBIT0(theInstr);
11891 
11892    if (opc1 != 0x3F) {
11893       vex_printf("dis_fp_scr(ppc)(instr)\n");
11894       return False;
11895    }
11896 
11897    switch (opc2) {
11898    case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479)
11899       // Bit crbD of the FPSCR is set.
11900       UChar crbD    = ifieldRegDS(theInstr);
11901       UInt  b11to20 = IFIELD(theInstr, 11, 10);
11902 
11903       if (b11to20 != 0) {
11904          vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n");
11905          return False;
11906       }
11907       DIP("mtfsb1%s crb%d \n", flag_rC ? ".":"", crbD);
11908       putGST_masked( PPC_GST_FPSCR, mkU64( 1 <<( 31 - crbD ) ),
11909 		     1ULL << ( 31 - crbD ) );
11910       break;
11911    }
11912 
11913    case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465)
11914       UChar   crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
11915       UChar   b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) );
11916       UChar   crfS    = toUChar( IFIELD( theInstr, 18, 3 ) );
11917       UChar   b11to17 = toUChar( IFIELD( theInstr, 11, 7 ) );
11918       IRTemp  tmp     = newTemp(Ity_I32);
11919       IRExpr* fpscr_all;
11920       if (b21to22 != 0 || b11to17 != 0 || flag_rC != 0) {
11921          vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n");
11922          return False;
11923       }
11924       DIP("mcrfs crf%d,crf%d\n", crfD, crfS);
11925       vassert(crfD < 8);
11926       vassert(crfS < 8);
11927       fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
11928       assign( tmp, binop(Iop_And32,
11929                          binop(Iop_Shr32,fpscr_all,mkU8(4 * (7-crfS))),
11930                         mkU32(0xF)) );
11931       putGST_field( PPC_GST_CR, mkexpr(tmp), crfD );
11932       break;
11933    }
11934 
11935    case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478)
11936       // Bit crbD of the FPSCR is cleared.
11937       UChar crbD    = ifieldRegDS(theInstr);
11938       UInt  b11to20 = IFIELD(theInstr, 11, 10);
11939 
11940       if (b11to20 != 0) {
11941          vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n");
11942          return False;
11943       }
11944       DIP("mtfsb0%s crb%d\n", flag_rC ? ".":"", crbD);
11945       putGST_masked( PPC_GST_FPSCR, mkU64( 0 ), 1ULL << ( 31 - crbD ) );
11946       break;
11947    }
11948 
11949    case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481)
11950       UInt crfD     = IFIELD( theInstr, 23, 3 );
11951       UChar b17to22 = toUChar( IFIELD( theInstr, 17, 6 ) );
11952       UChar IMM     = toUChar( IFIELD( theInstr, 12, 4 ) );
11953       UChar b11     = toUChar( IFIELD( theInstr, 11, 1 ) );
11954       UChar Wbit    = toUChar( IFIELD( theInstr, 16, 1 ) );
11955 
11956       if (b17to22 != 0 || b11 != 0 || (Wbit && !GX_level)) {
11957          vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n");
11958          return False;
11959       }
11960       DIP("mtfsfi%s crf%u,%d%s\n", flag_rC ? ".":"", crfD, IMM, Wbit ? ",1":"");
11961       crfD = crfD + (8 * (1 - Wbit) );
11962       putGST_field( PPC_GST_FPSCR, mkU32( IMM ), crfD );
11963       break;
11964    }
11965 
11966    case 0x247: { // mffs (Move from FPSCR, PPC32 p468)
11967       UChar   frD_addr  = ifieldRegDS(theInstr);
11968       UChar   frB_addr  = ifieldRegB(theInstr);
11969       IRTemp  frB = newTemp(Ity_F64);
11970       UInt    b11to12   = IFIELD(theInstr, 19, 2);
11971       UInt    b13to15   = IFIELD(theInstr, 16, 3);
11972       UInt    RN        = IFIELD(theInstr, 11, 2);
11973       UInt    DRN       = IFIELD(theInstr, 11, 3);
11974 
11975       /* The FPSCR_DRN, FPSCR_RN and FPSCR_FPCC are all stored in
11976        * their own 8-bit entries with distinct offsets.  The FPSCR
11977        * register is handled as two 32-bit values.  We need to
11978        * assemble the pieces into the single 64-bit value to return.
11979        */
11980       IRExpr* fpscr_lower
11981          = binop( Iop_Or32,
11982                   getGST_masked( PPC_GST_FPSCR, (MASK_FPSCR_RN | MASK_FPSCR_C_FPCC) ),
11983                   binop( Iop_Or32,
11984                          binop( Iop_Shl32,
11985                                 getC(),
11986                                 mkU8(63-47) ) ,
11987                          binop( Iop_Shl32,
11988                                 getFPCC(),
11989                                 mkU8(63-51) ) ) );
11990       IRExpr* fpscr_upper = getGST_masked_upper( PPC_GST_FPSCR, MASK_FPSCR_DRN );
11991 
11992       if ((b11to12 == 0) && (b13to15 == 0)) {
11993             DIP("mffs%s fr%u\n", flag_rC ? ".":"", frD_addr);
11994             putFReg( frD_addr,
11995                      unop( Iop_ReinterpI64asF64,
11996                            binop( Iop_32HLto64, fpscr_upper, fpscr_lower ) ) );
11997 
11998       } else if ((b11to12 == 0) && (b13to15 == 1)) {
11999             DIP("mffsce fr%u\n", frD_addr);
12000             /* Technically as of 4/5/2017 we are not tracking VE, OE, UE, ZE,
12001                or XE but in case that changes in the future, do the masking. */
12002             putFReg( frD_addr,
12003                      unop( Iop_ReinterpI64asF64,
12004                            binop( Iop_32HLto64, fpscr_upper,
12005                                   binop( Iop_And32, fpscr_lower,
12006                                          mkU32( 0xFFFFFF07 ) ) ) ) );
12007 
12008       } else if ((b11to12 == 2) && (b13to15 == 4)) {
12009             IRTemp  frB_int = newTemp(Ity_I64);
12010 
12011             DIP("mffscdrn fr%u,fr%u\n", frD_addr, frB_addr);
12012 
12013             assign( frB, getFReg(frB_addr));
12014             assign( frB_int, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
12015 
12016             /* Clear all of the FPSCR bits except for the DRN field, VE,
12017                OE, UE, ZE and XE bits and write the result to the frD
12018                register. Note, currently the exception bits are not tracked but
12019                will mask anyway in case that changes in the future. */
12020             putFReg( frD_addr,
12021                      unop( Iop_ReinterpI64asF64,
12022                            binop( Iop_32HLto64,
12023                                   binop( Iop_And32, mkU32(0x7), fpscr_upper ),
12024                                   binop( Iop_And32, mkU32(0xFF), fpscr_lower ) ) ) );
12025 
12026             /* Put new_DRN bits into the FPSCR register */
12027             putGST_masked( PPC_GST_FPSCR, mkexpr( frB_int ), MASK_FPSCR_DRN );
12028 
12029       } else if ((b11to12 == 2) && (b13to15 == 5)) {
12030             DIP("mffscdrni fr%u,%d\n", frD_addr, DRN);
12031 
12032             /* Clear all of the FPSCR bits except for the DRN field, VE,
12033                OE, UE, ZE and XE bits and write the result to the frD
12034                register. Note, currently the exception bits are not tracked but
12035                will mask anyway in case that changes in the future. */
12036             putFReg( frD_addr,
12037                      unop( Iop_ReinterpI64asF64,
12038                            binop( Iop_32HLto64,
12039                                   binop( Iop_And32, mkU32(0x7), fpscr_upper ),
12040                                   binop( Iop_And32, mkU32(0xFF), fpscr_lower ) ) ) );
12041 
12042             /* Put new_DRN bits into the FPSCR register */
12043             putGST_masked( PPC_GST_FPSCR, binop( Iop_32HLto64, mkU32( DRN ),
12044                                                  mkU32( 0 ) ), MASK_FPSCR_DRN );
12045 
12046       } else if ((b11to12 == 2) && (b13to15 == 6)) {
12047             IRTemp  frB_int = newTemp(Ity_I64);
12048 
12049             DIP("mffscrn fr%u,fr%u\n", frD_addr,frB_addr);
12050 
12051             assign( frB, getFReg(frB_addr));
12052             assign( frB_int, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
12053 
12054             /* Clear all of the FPSCR bits except for the DRN field, VE,
12055                OE, UE, ZE and XE bits and write the result to the frD
12056                register. Note, currently the exception bits are not tracked but
12057                will mask anyway in case that changes in the future. */
12058             putFReg( frD_addr,
12059                      unop( Iop_ReinterpI64asF64,
12060                            binop( Iop_32HLto64,
12061                                   binop( Iop_And32, mkU32(0x7), fpscr_upper ),
12062                                   binop( Iop_And32, mkU32(0xFF), fpscr_lower ) ) ) );
12063 
12064             /* Put new_CRN bits into the FPSCR register */
12065             putGST_masked( PPC_GST_FPSCR, mkexpr( frB_int ), MASK_FPSCR_RN );
12066 
12067       } else if ((b11to12 == 2) && (b13to15 == 7)) {
12068             DIP("mffscrni fr%u,%u\n", frD_addr, RN);
12069 
12070             /* Clear all of the FPSCR bits except for the DRN field, VE,
12071                OE, UE, ZE and XE bits and write the result to the frD
12072                register. Note, currently the exception bits are not tracked but
12073                will mask anyway in case that changes in the future. */
12074             putFReg( frD_addr,
12075                      unop( Iop_ReinterpI64asF64,
12076                            binop( Iop_32HLto64,
12077                                   binop( Iop_And32, mkU32(0x7), fpscr_upper ),
12078                                   binop( Iop_And32, mkU32(0xFF), fpscr_lower ) ) ) );
12079 
12080             /* Put new_RN bits into the FPSCR register */
12081             putGST_masked( PPC_GST_FPSCR, binop( Iop_32HLto64, mkU32( 0 ),
12082                                                  mkU32( RN ) ), MASK_FPSCR_RN );
12083 
12084       } else if ((b11to12 == 3) && (b13to15 == 0)) {
12085             DIP("mffsl fr%u\n", frD_addr);
12086             /* Technically as of 4/5/2017 we are not tracking VE, OE, UE, ZE,
12087                XE, FR, FI, C, FL, FG, FE, FU.  Also only track DRN in the upper
12088                bits but in case that changes in the future we will do the
12089                masking. */
12090             putFReg( frD_addr,
12091                      unop( Iop_ReinterpI64asF64,
12092                            binop( Iop_32HLto64,
12093                                   binop( Iop_And32, fpscr_upper,
12094                                          mkU32( 0x7 ) ),
12095                                   binop( Iop_And32, fpscr_lower,
12096                                          mkU32( 0x7F0FF ) ) ) ) );
12097       } else {
12098          vex_printf("dis_fp_scr(ppc)(mff**) Unrecognized instruction.\n");
12099          return False;
12100       }
12101       break;
12102    }
12103 
12104    case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480)
12105       UChar b25      = toUChar( IFIELD(theInstr, 25, 1) );
12106       UChar FM       = toUChar( IFIELD(theInstr, 17, 8) );
12107       UChar frB_addr = ifieldRegB(theInstr);
12108       IRTemp frB   = newTemp(Ity_F64);
12109       IRTemp rB_64 = newTemp( Ity_I64 );
12110       Int i;
12111       ULong mask;
12112       UChar Wbit;
12113 #define BFP_MASK_SEED 0x3000000000000000ULL
12114 #define DFP_MASK_SEED 0x7000000000000000ULL
12115 
12116       if (GX_level) {
12117          /* This implies that Decimal Floating Point is supported, and the
12118           * FPSCR must be managed as a 64-bit register.
12119           */
12120          Wbit = toUChar( IFIELD(theInstr, 16, 1) );
12121       } else {
12122          Wbit = 0;
12123       }
12124 
12125       if (b25 == 1) {
12126          /* new 64 bit move variant for power 6.  If L field (bit 25) is
12127           * a one do a full 64 bit move.  Note, the FPSCR is not really
12128           * properly modeled.  This instruciton only changes the value of
12129           * the rounding mode bit fields RN, FPCC and DRN.  The HW exception bits
12130           * do not get set in the simulator.  1/12/09
12131           */
12132          DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC ? ".":"", FM, frB_addr);
12133          mask = 0x1F0001F003;
12134 
12135       } else {
12136          DIP("mtfsf%s %d,fr%u\n", flag_rC ? ".":"", FM, frB_addr);
12137          // Build 32bit mask from FM:
12138          mask = 0;
12139          for (i=0; i<8; i++) {
12140             if ((FM & (1<<(7-i))) == 1) {
12141                /* FPSCR field k is set to the contents of the corresponding
12142                 * field of register FRB, where k = i+8x(1-W).  In the Power
12143                 * ISA, register field numbering is from left to right, so field
12144                 * 15 is the least significant field in a 64-bit register.  To
12145                 * generate the mask, we set all the appropriate rounding mode
12146                 * bits in the highest order nibble (field 0) and shift right
12147                 * 'k x nibble length'.
12148                 */
12149                if (Wbit)
12150                   mask |= DFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) );
12151                else
12152                   mask |= BFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) );
12153             }
12154             if ((FM & (1<<(7-i))) == 0x2) { //set the FPCC bits
12155                mask |= 0xF000;
12156             }
12157             if ((FM & (1<<(7-i))) == 0x4) { //set the Floating-Point Class Descriptor (C) bit
12158                mask |= 0x10000;
12159             }
12160          }
12161       }
12162       assign( frB, getFReg(frB_addr));
12163       assign( rB_64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
12164       putGST_masked( PPC_GST_FPSCR, mkexpr( rB_64 ), mask );
12165       break;
12166    }
12167 
12168    default:
12169       vex_printf("dis_fp_scr(ppc)(opc2)\n");
12170       return False;
12171    }
12172    return True;
12173 }
12174 
12175 /*------------------------------------------------------------*/
12176 /*--- Decimal Floating Point (DFP)  Helper functions       ---*/
12177 /*------------------------------------------------------------*/
12178 #define DFP_LONG  1
12179 #define DFP_EXTND 2
12180 #define DFP_LONG_BIAS   398
12181 #define DFP_LONG_ENCODED_FIELD_MASK  0x1F00
12182 #define DFP_EXTND_BIAS  6176
12183 #define DFP_EXTND_ENCODED_FIELD_MASK 0x1F000
12184 #define DFP_LONG_EXP_MSK   0XFF
12185 #define DFP_EXTND_EXP_MSK  0XFFF
12186 
12187 #define DFP_G_FIELD_LONG_MASK     0x7FFC0000  // upper 32-bits only
12188 #define DFP_LONG_GFIELD_RT_SHIFT  (63 - 13 - 32) // adj for upper 32-bits
12189 #define DFP_G_FIELD_EXTND_MASK    0x7FFFC000  // upper 32-bits only
12190 #define DFP_EXTND_GFIELD_RT_SHIFT (63 - 17 - 32) //adj for upper 32 bits
12191 #define DFP_T_FIELD_LONG_MASK     0x3FFFF  // mask for upper 32-bits
12192 #define DFP_T_FIELD_EXTND_MASK    0x03FFFF // mask for upper 32-bits
12193 #define DFP_LONG_EXP_MAX          369      // biased max
12194 #define DFP_LONG_EXP_MIN          0        // biased min
12195 #define DFP_EXTND_EXP_MAX         6111     // biased max
12196 #define DFP_EXTND_EXP_MIN         0        // biased min
12197 #define DFP_LONG_MAX_SIG_DIGITS   16
12198 #define DFP_EXTND_MAX_SIG_DIGITS  34
12199 #define MAX_DIGITS_IN_STRING      8
12200 
12201 
12202 #define  AND(x, y) binop( Iop_And32, x, y )
12203 #define AND4(w, x, y, z) AND( AND( w, x ), AND( y, z ) )
12204 #define   OR(x, y) binop( Iop_Or32,  x, y )
12205 #define  OR3(x, y, z)    OR( x, OR( y, z ) )
12206 #define  OR4(w, x, y, z) OR( OR( w, x ), OR( y, z ) )
12207 #define  NOT(x) unop( Iop_1Uto32, unop( Iop_Not1, unop( Iop_32to1,  mkexpr( x ) ) ) )
12208 
12209 #define  SHL(value, by) binop( Iop_Shl32, value, mkU8( by ) )
12210 #define  SHR(value, by) binop( Iop_Shr32, value, mkU8( by ) )
12211 
12212 #define BITS5(_b4,_b3,_b2,_b1,_b0) \
12213    (((_b4) << 4) | ((_b3) << 3) | ((_b2) << 2) | \
12214     ((_b1) << 1) | ((_b0) << 0))
12215 
Gfield_encoding(IRExpr * lmexp,IRExpr * lmd32)12216 static IRExpr * Gfield_encoding( IRExpr * lmexp, IRExpr * lmd32 )
12217 {
12218    IRTemp lmd_07_mask   = newTemp( Ity_I32 );
12219    IRTemp lmd_8_mask    = newTemp( Ity_I32 );
12220    IRTemp lmd_9_mask    = newTemp( Ity_I32 );
12221    IRTemp lmexp_00_mask = newTemp( Ity_I32 );
12222    IRTemp lmexp_01_mask = newTemp( Ity_I32 );
12223    IRTemp lmexp_10_mask = newTemp( Ity_I32 );
12224    IRTemp lmd_07_val    = newTemp( Ity_I32 );
12225    IRTemp lmd_8_val     = newTemp( Ity_I32 );
12226    IRTemp lmd_9_val     = newTemp( Ity_I32 );
12227 
12228    /* The encodig is as follows:
12229     * lmd - left most digit
12230     * lme - left most 2-bits of the exponent
12231     *
12232     *    lmd
12233     *   0 - 7    (lmexp << 3) | lmd
12234     *     8      0b11000 (24 decimal) if lme=0b00;
12235     *            0b11010 (26 decimal) if lme=0b01;
12236     *            0b11100 (28 decimal) if lme=0b10;
12237     *     9      0b11001 (25 decimal) if lme=0b00;
12238     *            0b11011 (27 decimal) if lme=0b01;
12239     *            0b11101 (29 decimal) if lme=0b10;
12240     */
12241 
12242    /* Generate the masks for each condition */
12243    assign( lmd_07_mask,
12244            unop( Iop_1Sto32, binop( Iop_CmpLE32U, lmd32, mkU32( 7 ) ) ) );
12245    assign( lmd_8_mask,
12246            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 8 ) ) ) );
12247    assign( lmd_9_mask,
12248            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 9 ) ) ) );
12249    assign( lmexp_00_mask,
12250            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 0 ) ) ) );
12251    assign( lmexp_01_mask,
12252            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 1 ) ) ) );
12253    assign( lmexp_10_mask,
12254            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 2 ) ) ) );
12255 
12256    /* Generate the values for each LMD condition, assuming the condition
12257     * is TRUE.
12258     */
12259    assign( lmd_07_val,
12260            binop( Iop_Or32, binop( Iop_Shl32, lmexp, mkU8( 3 ) ), lmd32 ) );
12261    assign( lmd_8_val,
12262            binop( Iop_Or32,
12263                   binop( Iop_Or32,
12264                          binop( Iop_And32,
12265                                 mkexpr( lmexp_00_mask ),
12266                                 mkU32( 24 ) ),
12267                          binop( Iop_And32,
12268                                 mkexpr( lmexp_01_mask ),
12269                                 mkU32( 26 ) ) ),
12270                   binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 28 ) ) ) );
12271    assign( lmd_9_val,
12272            binop( Iop_Or32,
12273                   binop( Iop_Or32,
12274                          binop( Iop_And32,
12275                                 mkexpr( lmexp_00_mask ),
12276                                 mkU32( 25 ) ),
12277                          binop( Iop_And32,
12278                                 mkexpr( lmexp_01_mask ),
12279                                 mkU32( 27 ) ) ),
12280                   binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 29 ) ) ) );
12281 
12282    /* generate the result from the possible LMD values */
12283    return binop( Iop_Or32,
12284                  binop( Iop_Or32,
12285                         binop( Iop_And32,
12286                                mkexpr( lmd_07_mask ),
12287                                mkexpr( lmd_07_val ) ),
12288                         binop( Iop_And32,
12289                                mkexpr( lmd_8_mask ),
12290                                mkexpr( lmd_8_val ) ) ),
12291                  binop( Iop_And32, mkexpr( lmd_9_mask ), mkexpr( lmd_9_val ) ) );
12292 }
12293 
Get_lmd(IRTemp * lmd,IRExpr * gfield_0_4)12294 static void Get_lmd( IRTemp * lmd, IRExpr * gfield_0_4 )
12295 {
12296    /* Extract the exponent and the left most digit of the mantissa
12297     * from the G field bits [0:4].
12298     */
12299    IRTemp lmd_07_mask   = newTemp( Ity_I32 );
12300    IRTemp lmd_8_00_mask = newTemp( Ity_I32 );
12301    IRTemp lmd_8_01_mask = newTemp( Ity_I32 );
12302    IRTemp lmd_8_10_mask = newTemp( Ity_I32 );
12303    IRTemp lmd_9_00_mask = newTemp( Ity_I32 );
12304    IRTemp lmd_9_01_mask = newTemp( Ity_I32 );
12305    IRTemp lmd_9_10_mask = newTemp( Ity_I32 );
12306 
12307    IRTemp lmd_07_val = newTemp( Ity_I32 );
12308    IRTemp lmd_8_val  = newTemp( Ity_I32 );
12309    IRTemp lmd_9_val  = newTemp( Ity_I32 );
12310 
12311    /* The left most digit (LMD) encoding is as follows:
12312     *    lmd
12313     *   0 - 7    (lmexp << 3) | lmd
12314     *     8      0b11000 (24 decimal) if lme=0b00;
12315     *            0b11010 (26 decimal) if lme=0b01;
12316     *            0b11100 (28 decimal) if lme=0b10
12317     *     9      0b11001 (25 decimal) if lme=0b00;
12318     *            0b11011 (27 decimal) if lme=0b01;
12319     *            0b11101 (29 decimal) if lme=0b10;
12320     */
12321 
12322    /* Generate the masks for each condition of LMD and exponent bits */
12323    assign( lmd_07_mask,
12324            unop( Iop_1Sto32, binop( Iop_CmpLE32U,
12325                                     gfield_0_4,
12326                                     mkU32( BITS5(1,0,1,1,1) ) ) ) );
12327    assign( lmd_8_00_mask,
12328            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
12329                                     gfield_0_4,
12330                                     mkU32( BITS5(1,1,0,0,0) ) ) ) );
12331    assign( lmd_8_01_mask,
12332            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
12333                                     gfield_0_4,
12334                                     mkU32( BITS5(1,1,0,1,0) ) ) ) );
12335    assign( lmd_8_10_mask,
12336            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
12337                                     gfield_0_4,
12338                                     mkU32( BITS5(1,1,1,0,0) ) ) ) );
12339    assign( lmd_9_00_mask,
12340            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
12341                                     gfield_0_4,
12342                                     mkU32( BITS5(1,1,0,0,1) ) ) ) );
12343    assign( lmd_9_01_mask,
12344            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
12345                                     gfield_0_4,
12346                                     mkU32( BITS5(1,1,0,1,1) ) ) ) );
12347    assign( lmd_9_10_mask,
12348            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
12349                                     gfield_0_4,
12350                                     mkU32( BITS5(1,1,1,0,1) ) ) ) );
12351 
12352    /* Generate the values for each LMD condition, assuming the condition
12353     * is TRUE.
12354     */
12355    assign( lmd_07_val, binop( Iop_And32, gfield_0_4, mkU32( 0x7 ) ) );
12356    assign( lmd_8_val, mkU32( 0x8 ) );
12357    assign( lmd_9_val, mkU32( 0x9 ) );
12358 
12359    assign( *lmd,
12360            OR( OR3 ( AND( mkexpr( lmd_07_mask ), mkexpr( lmd_07_val ) ),
12361                      AND( mkexpr( lmd_8_00_mask ), mkexpr( lmd_8_val ) ),
12362                      AND( mkexpr( lmd_8_01_mask ), mkexpr( lmd_8_val ) )),
12363                      OR4( AND( mkexpr( lmd_8_10_mask ), mkexpr( lmd_8_val ) ),
12364                           AND( mkexpr( lmd_9_00_mask ), mkexpr( lmd_9_val ) ),
12365                           AND( mkexpr( lmd_9_01_mask ), mkexpr( lmd_9_val ) ),
12366                           AND( mkexpr( lmd_9_10_mask ), mkexpr( lmd_9_val ) )
12367                      ) ) );
12368 }
12369 
12370 #define DIGIT1_SHR 4    // shift digit 1 to bottom 4 bits
12371 #define DIGIT2_SHR 8    // shift digit 2 to bottom 4 bits
12372 #define DIGIT3_SHR 12
12373 #define DIGIT4_SHR 16
12374 #define DIGIT5_SHR 20
12375 #define DIGIT6_SHR 24
12376 #define DIGIT7_SHR 28
12377 
bcd_digit_inval(IRExpr * bcd_u,IRExpr * bcd_l)12378 static IRExpr * bcd_digit_inval( IRExpr * bcd_u, IRExpr * bcd_l )
12379 {
12380    /* 60-bit BCD string stored in two 32-bit values.  Check that each,
12381     * digit is a valid BCD number, i.e. less then 9.
12382     */
12383    IRTemp valid = newTemp( Ity_I32 );
12384 
12385    assign( valid,
12386            AND4( AND4 ( unop( Iop_1Sto32,
12387                               binop( Iop_CmpLE32U,
12388                                      binop( Iop_And32,
12389                                             bcd_l,
12390                                             mkU32 ( 0xF ) ),
12391                                       mkU32( 0x9 ) ) ),
12392                         unop( Iop_1Sto32,
12393                               binop( Iop_CmpLE32U,
12394                                      binop( Iop_And32,
12395                                             binop( Iop_Shr32,
12396                                                    bcd_l,
12397                                                    mkU8 ( DIGIT1_SHR ) ),
12398                                              mkU32 ( 0xF ) ),
12399                                       mkU32( 0x9 ) ) ),
12400                         unop( Iop_1Sto32,
12401                               binop( Iop_CmpLE32U,
12402                                      binop( Iop_And32,
12403                                             binop( Iop_Shr32,
12404                                                    bcd_l,
12405                                                    mkU8 ( DIGIT2_SHR ) ),
12406                                             mkU32 ( 0xF ) ),
12407                                       mkU32( 0x9 ) ) ),
12408                         unop( Iop_1Sto32,
12409                               binop( Iop_CmpLE32U,
12410                                      binop( Iop_And32,
12411                                             binop( Iop_Shr32,
12412                                                    bcd_l,
12413                                                    mkU8 ( DIGIT3_SHR ) ),
12414                                              mkU32 ( 0xF ) ),
12415                                       mkU32( 0x9 ) ) ) ),
12416                  AND4 ( unop( Iop_1Sto32,
12417                               binop( Iop_CmpLE32U,
12418                                      binop( Iop_And32,
12419                                             binop( Iop_Shr32,
12420                                                    bcd_l,
12421                                                    mkU8 ( DIGIT4_SHR ) ),
12422                                             mkU32 ( 0xF ) ),
12423                                      mkU32( 0x9 ) ) ),
12424                         unop( Iop_1Sto32,
12425                               binop( Iop_CmpLE32U,
12426                                      binop( Iop_And32,
12427                                             binop( Iop_Shr32,
12428                                                    bcd_l,
12429                                                    mkU8 ( DIGIT5_SHR ) ),
12430                                             mkU32 ( 0xF ) ),
12431                                      mkU32( 0x9 ) ) ),
12432                         unop( Iop_1Sto32,
12433                               binop( Iop_CmpLE32U,
12434                                      binop( Iop_And32,
12435                                             binop( Iop_Shr32,
12436                                                    bcd_l,
12437                                                    mkU8 ( DIGIT6_SHR ) ),
12438                                             mkU32 ( 0xF ) ),
12439                                      mkU32( 0x9 ) ) ),
12440                         unop( Iop_1Sto32,
12441                               binop( Iop_CmpLE32U,
12442                                      binop( Iop_And32,
12443                                             binop( Iop_Shr32,
12444                                                    bcd_l,
12445                                                    mkU8 ( DIGIT7_SHR ) ),
12446                                             mkU32 ( 0xF ) ),
12447                                      mkU32( 0x9 ) ) ) ),
12448                  AND4( unop( Iop_1Sto32,
12449                              binop( Iop_CmpLE32U,
12450                                     binop( Iop_And32,
12451                                            bcd_u,
12452                                            mkU32 ( 0xF ) ),
12453                                     mkU32( 0x9 ) ) ),
12454                        unop( Iop_1Sto32,
12455                              binop( Iop_CmpLE32U,
12456                                     binop( Iop_And32,
12457                                            binop( Iop_Shr32,
12458                                                   bcd_u,
12459                                                   mkU8 ( DIGIT1_SHR ) ),
12460                                            mkU32 ( 0xF ) ),
12461                                     mkU32( 0x9 ) ) ),
12462                        unop( Iop_1Sto32,
12463                              binop( Iop_CmpLE32U,
12464                                     binop( Iop_And32,
12465                                            binop( Iop_Shr32,
12466                                                   bcd_u,
12467                                                   mkU8 ( DIGIT2_SHR ) ),
12468                                            mkU32 ( 0xF ) ),
12469                                     mkU32( 0x9 ) ) ),
12470                        unop( Iop_1Sto32,
12471                              binop( Iop_CmpLE32U,
12472                                     binop( Iop_And32,
12473                                            binop( Iop_Shr32,
12474                                                   bcd_u,
12475                                                   mkU8 ( DIGIT3_SHR ) ),
12476                                            mkU32 ( 0xF ) ),
12477                                     mkU32( 0x9 ) ) ) ),
12478                  AND4( unop( Iop_1Sto32,
12479                              binop( Iop_CmpLE32U,
12480                                     binop( Iop_And32,
12481                                            binop( Iop_Shr32,
12482                                                   bcd_u,
12483                                                   mkU8 ( DIGIT4_SHR ) ),
12484                                            mkU32 ( 0xF ) ),
12485                                     mkU32( 0x9 ) ) ),
12486                        unop( Iop_1Sto32,
12487                              binop( Iop_CmpLE32U,
12488                                     binop( Iop_And32,
12489                                            binop( Iop_Shr32,
12490                                                   bcd_u,
12491                                                   mkU8 ( DIGIT5_SHR ) ),
12492                                            mkU32 ( 0xF ) ),
12493                                     mkU32( 0x9 ) ) ),
12494                        unop( Iop_1Sto32,
12495                              binop( Iop_CmpLE32U,
12496                                     binop( Iop_And32,
12497                                            binop( Iop_Shr32,
12498                                                   bcd_u,
12499                                                   mkU8 ( DIGIT6_SHR ) ),
12500                                            mkU32 ( 0xF ) ),
12501                                     mkU32( 0x9 ) ) ),
12502                        unop( Iop_1Sto32,
12503                              binop( Iop_CmpLE32U,
12504                                     binop( Iop_And32,
12505                                            binop( Iop_Shr32,
12506                                                   bcd_u,
12507                                                   mkU8 ( DIGIT7_SHR ) ),
12508                                            mkU32 ( 0xF ) ),
12509                                     mkU32( 0x9 ) ) ) ) ) );
12510 
12511    return unop( Iop_Not32, mkexpr( valid ) );
12512 }
12513 #undef DIGIT1_SHR
12514 #undef DIGIT2_SHR
12515 #undef DIGIT3_SHR
12516 #undef DIGIT4_SHR
12517 #undef DIGIT5_SHR
12518 #undef DIGIT6_SHR
12519 #undef DIGIT7_SHR
12520 
Generate_neg_sign_mask(IRExpr * sign)12521 static IRExpr * Generate_neg_sign_mask( IRExpr * sign )
12522 {
12523    return binop( Iop_Or32,
12524                  unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xB ) ) ),
12525                  unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xD ) ) )
12526                );
12527 }
12528 
Generate_pos_sign_mask(IRExpr * sign)12529 static IRExpr * Generate_pos_sign_mask( IRExpr * sign )
12530 {
12531    return binop( Iop_Or32,
12532                  binop( Iop_Or32,
12533                         unop( Iop_1Sto32,
12534                               binop( Iop_CmpEQ32, sign, mkU32( 0xA ) ) ),
12535                         unop( Iop_1Sto32,
12536                               binop( Iop_CmpEQ32, sign, mkU32( 0xC ) ) ) ),
12537                  binop( Iop_Or32,
12538                         unop( Iop_1Sto32,
12539                               binop( Iop_CmpEQ32, sign, mkU32( 0xE ) ) ),
12540                         unop( Iop_1Sto32,
12541                               binop( Iop_CmpEQ32, sign, mkU32( 0xF ) ) ) ) );
12542 }
12543 
Generate_sign_bit(IRExpr * pos_sign_mask,IRExpr * neg_sign_mask)12544 static IRExpr * Generate_sign_bit( IRExpr * pos_sign_mask,
12545                                    IRExpr * neg_sign_mask )
12546 {
12547    return binop( Iop_Or32,
12548                  binop( Iop_And32, neg_sign_mask, mkU32( 0x80000000 ) ),
12549                  binop( Iop_And32, pos_sign_mask, mkU32( 0x00000000 ) ) );
12550 }
12551 
Generate_inv_mask(IRExpr * invalid_bcd_mask,IRExpr * pos_sign_mask,IRExpr * neg_sign_mask)12552 static IRExpr * Generate_inv_mask( IRExpr * invalid_bcd_mask,
12553                                    IRExpr * pos_sign_mask,
12554                                    IRExpr * neg_sign_mask )
12555 /* first argument is all 1's if the BCD string had an invalid digit in it. */
12556 {
12557    return binop( Iop_Or32,
12558                  invalid_bcd_mask,
12559                  unop( Iop_1Sto32,
12560                        binop( Iop_CmpEQ32,
12561                               binop( Iop_Or32, pos_sign_mask, neg_sign_mask ),
12562                               mkU32( 0x0 ) ) ) );
12563 }
12564 
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)12565 static void Generate_132_bit_bcd_string( IRExpr * frBI64_hi, IRExpr * frBI64_lo,
12566                                          IRTemp * top_12_l, IRTemp * mid_60_u,
12567                                          IRTemp * mid_60_l, IRTemp * low_60_u,
12568                                          IRTemp * low_60_l)
12569 {
12570    IRTemp tmplow60 = newTemp( Ity_I64 );
12571    IRTemp tmpmid60 = newTemp( Ity_I64 );
12572    IRTemp tmptop12 = newTemp( Ity_I64 );
12573    IRTemp low_50   = newTemp( Ity_I64 );
12574    IRTemp mid_50   = newTemp( Ity_I64 );
12575    IRTemp top_10   = newTemp( Ity_I64 );
12576    IRTemp top_12_u = newTemp( Ity_I32 ); // only needed for a dummy arg
12577 
12578    /* Convert the 110-bit densely packed BCD string to a 128-bit BCD string */
12579 
12580    /* low_50[49:0] = ((frBI64_lo[49:32]  << 14) | frBI64_lo[31:0]) */
12581    assign( low_50,
12582            binop( Iop_32HLto64,
12583                   binop( Iop_And32,
12584                          unop( Iop_64HIto32, frBI64_lo ),
12585                          mkU32( 0x3FFFF ) ),
12586                          unop( Iop_64to32, frBI64_lo ) ) );
12587 
12588    /* Convert the 50 bit densely packed BCD string to a 60 bit
12589     * BCD string.
12590     */
12591    assign( tmplow60, unop( Iop_DPBtoBCD, mkexpr( low_50 ) ) );
12592    assign( *low_60_u, unop( Iop_64HIto32, mkexpr( tmplow60 ) ) );
12593    assign( *low_60_l, unop( Iop_64to32, mkexpr( tmplow60 ) ) );
12594 
12595    /* mid_50[49:0] =  ((frBI64_hi[35:32] << 14) | frBI64_hi[31:18]) |
12596     *                 ((frBI64_hi[17:0]  << 14) | frBI64_lo[63:50])
12597     */
12598    assign( mid_50,
12599            binop( Iop_32HLto64,
12600                   binop( Iop_Or32,
12601                          binop( Iop_Shl32,
12602                                 binop( Iop_And32,
12603                                        unop( Iop_64HIto32, frBI64_hi ),
12604                                        mkU32( 0xF ) ),
12605                                 mkU8( 14 ) ),
12606                          binop( Iop_Shr32,
12607                                 unop( Iop_64to32, frBI64_hi ),
12608                                 mkU8( 18 ) ) ),
12609                   binop( Iop_Or32,
12610                          binop( Iop_Shl32,
12611                                 unop( Iop_64to32, frBI64_hi ),
12612                                 mkU8( 14 ) ),
12613                          binop( Iop_Shr32,
12614                                 unop( Iop_64HIto32, frBI64_lo ),
12615                                 mkU8( 18 ) ) ) ) );
12616 
12617    /* Convert the 50 bit densely packed BCD string to a 60 bit
12618     * BCD string.
12619     */
12620    assign( tmpmid60, unop( Iop_DPBtoBCD, mkexpr( mid_50 ) ) );
12621    assign( *mid_60_u, unop( Iop_64HIto32, mkexpr( tmpmid60 ) ) );
12622    assign( *mid_60_l, unop( Iop_64to32, mkexpr( tmpmid60 ) ) );
12623 
12624    /* top_10[49:0] = frBI64_hi[45:36]) |  */
12625    assign( top_10,
12626            binop( Iop_32HLto64,
12627                   mkU32( 0 ),
12628                   binop( Iop_And32,
12629                          binop( Iop_Shr32,
12630                                 unop( Iop_64HIto32, frBI64_hi ),
12631                                 mkU8( 4 ) ),
12632                          mkU32( 0x3FF ) ) ) );
12633 
12634    /* Convert the 10 bit densely packed BCD string to a 12 bit
12635     * BCD string.
12636     */
12637    assign( tmptop12, unop( Iop_DPBtoBCD, mkexpr( top_10 ) ) );
12638    assign( top_12_u, unop( Iop_64HIto32, mkexpr( tmptop12 ) ) );
12639    assign( *top_12_l, unop( Iop_64to32, mkexpr( tmptop12 ) ) );
12640 }
12641 
Count_zeros(int start,IRExpr * init_cnt,IRExpr * init_flag,IRTemp * final_cnt,IRTemp * final_flag,IRExpr * string)12642 static void Count_zeros( int start, IRExpr * init_cnt, IRExpr * init_flag,
12643                          IRTemp * final_cnt, IRTemp * final_flag,
12644                          IRExpr * string )
12645 {
12646    IRTemp cnt[MAX_DIGITS_IN_STRING + 1];IRTemp flag[MAX_DIGITS_IN_STRING+1];
12647    int digits = MAX_DIGITS_IN_STRING;
12648    int i;
12649 
12650    cnt[start-1] = newTemp( Ity_I8 );
12651    flag[start-1] = newTemp( Ity_I8 );
12652    assign( cnt[start-1], init_cnt);
12653    assign( flag[start-1], init_flag);
12654 
12655    for ( i = start; i <= digits; i++) {
12656       cnt[i] = newTemp( Ity_I8 );
12657       flag[i] = newTemp( Ity_I8 );
12658       assign( cnt[i],
12659               binop( Iop_Add8,
12660                      mkexpr( cnt[i-1] ),
12661                      binop(Iop_And8,
12662                            unop( Iop_1Uto8,
12663                                  binop(Iop_CmpEQ32,
12664                                        binop(Iop_And32,
12665                                              string,
12666                                              mkU32( 0xF <<
12667                                                     ( ( digits - i ) * 4) ) ),
12668                                        mkU32( 0 ) ) ),
12669                            binop( Iop_Xor8, /* complement flag */
12670                                   mkexpr( flag[i - 1] ),
12671                                   mkU8( 0xFF ) ) ) ) );
12672 
12673       /* set flag to 1 if digit was not a zero */
12674       assign( flag[i],
12675               binop(Iop_Or8,
12676                     unop( Iop_1Sto8,
12677                           binop(Iop_CmpNE32,
12678                                 binop(Iop_And32,
12679                                       string,
12680                                       mkU32( 0xF <<
12681                                              ( (digits - i) * 4) ) ),
12682                                 mkU32( 0 ) ) ),
12683                     mkexpr( flag[i - 1] ) ) );
12684    }
12685 
12686    *final_cnt = cnt[digits];
12687    *final_flag = flag[digits];
12688 }
12689 
Count_leading_zeros_60(IRExpr * lmd,IRExpr * upper_28,IRExpr * low_32)12690 static IRExpr * Count_leading_zeros_60( IRExpr * lmd, IRExpr * upper_28,
12691                                         IRExpr * low_32 )
12692 {
12693    IRTemp num_lmd    = newTemp( Ity_I8 );
12694    IRTemp num_upper  = newTemp( Ity_I8 );
12695    IRTemp num_low    = newTemp( Ity_I8 );
12696    IRTemp lmd_flag   = newTemp( Ity_I8 );
12697    IRTemp upper_flag = newTemp( Ity_I8 );
12698    IRTemp low_flag   = newTemp( Ity_I8 );
12699 
12700    assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) );
12701    assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) );
12702 
12703    Count_zeros( 2,
12704                 mkexpr( num_lmd ),
12705                 mkexpr( lmd_flag ),
12706                 &num_upper,
12707                 &upper_flag,
12708                 upper_28 );
12709 
12710    Count_zeros( 1,
12711                 mkexpr( num_upper ),
12712                 mkexpr( upper_flag ),
12713                 &num_low,
12714                 &low_flag,
12715                 low_32 );
12716 
12717    return mkexpr( num_low );
12718 }
12719 
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)12720 static IRExpr * Count_leading_zeros_128( IRExpr * lmd, IRExpr * top_12_l,
12721                                          IRExpr * mid_60_u, IRExpr * mid_60_l,
12722                                          IRExpr * low_60_u, IRExpr * low_60_l)
12723 {
12724    IRTemp num_lmd   = newTemp( Ity_I8 );
12725    IRTemp num_top   = newTemp( Ity_I8 );
12726    IRTemp num_mid_u = newTemp( Ity_I8 );
12727    IRTemp num_mid_l = newTemp( Ity_I8 );
12728    IRTemp num_low_u = newTemp( Ity_I8 );
12729    IRTemp num_low_l = newTemp( Ity_I8 );
12730 
12731    IRTemp lmd_flag   = newTemp( Ity_I8 );
12732    IRTemp top_flag   = newTemp( Ity_I8 );
12733    IRTemp mid_u_flag = newTemp( Ity_I8 );
12734    IRTemp mid_l_flag = newTemp( Ity_I8 );
12735    IRTemp low_u_flag = newTemp( Ity_I8 );
12736    IRTemp low_l_flag = newTemp( Ity_I8 );
12737 
12738    /* Check the LMD, digit 34, to see if it is zero. */
12739    assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) );
12740 
12741    assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) );
12742 
12743    Count_zeros( 6,
12744                 mkexpr( num_lmd ),
12745                 mkexpr( lmd_flag ),
12746                 &num_top,
12747                 &top_flag,
12748                 top_12_l );
12749 
12750    Count_zeros( 2,
12751                 mkexpr( num_top ),
12752                 mkexpr( top_flag ),
12753                 &num_mid_u,
12754                 &mid_u_flag,
12755                 binop( Iop_Or32,
12756                        binop( Iop_Shl32, mid_60_u, mkU8( 2 ) ),
12757                        binop( Iop_Shr32, mid_60_l, mkU8( 30 ) ) ) );
12758 
12759    Count_zeros( 1,
12760                 mkexpr( num_mid_u ),
12761                 mkexpr( mid_u_flag ),
12762                 &num_mid_l,
12763                 &mid_l_flag,
12764                 mid_60_l );
12765 
12766    Count_zeros( 2,
12767                 mkexpr( num_mid_l ),
12768                 mkexpr( mid_l_flag ),
12769                 &num_low_u,
12770                 &low_u_flag,
12771                 binop( Iop_Or32,
12772                        binop( Iop_Shl32, low_60_u, mkU8( 2 ) ),
12773                        binop( Iop_Shr32, low_60_l, mkU8( 30 ) ) ) );
12774 
12775    Count_zeros( 1,
12776                 mkexpr( num_low_u ),
12777                 mkexpr( low_u_flag ),
12778                 &num_low_l,
12779                 &low_l_flag,
12780                 low_60_l );
12781 
12782    return mkexpr( num_low_l );
12783 }
12784 
Check_unordered(IRExpr * val)12785 static IRExpr * Check_unordered(IRExpr * val)
12786 {
12787    IRTemp gfield0to5 = newTemp( Ity_I32 );
12788 
12789    /* Extract G[0:4] */
12790    assign( gfield0to5,
12791            binop( Iop_And32,
12792                   binop( Iop_Shr32, unop( Iop_64HIto32, val ), mkU8( 26 ) ),
12793                   mkU32( 0x1F ) ) );
12794 
12795    /* Check for unordered, return all 1'x if true */
12796    return binop( Iop_Or32, /* QNaN check */
12797                  unop( Iop_1Sto32,
12798                        binop( Iop_CmpEQ32,
12799                               mkexpr( gfield0to5 ),
12800                               mkU32( 0x1E ) ) ),
12801                  unop( Iop_1Sto32, /* SNaN check */
12802                        binop( Iop_CmpEQ32,
12803                               mkexpr( gfield0to5 ),
12804                               mkU32( 0x1F ) ) ) );
12805 }
12806 
12807 #undef AND
12808 #undef AND4
12809 #undef OR
12810 #undef OR3
12811 #undef OR4
12812 #undef NOT
12813 #undef SHR
12814 #undef SHL
12815 #undef BITS5
12816 
12817 /*------------------------------------------------------------*/
12818 /*--- Decimal Floating Point (DFP) instruction translation ---*/
12819 /*------------------------------------------------------------*/
12820 
12821 /* DFP Arithmetic instructions */
dis_dfp_arith(UInt theInstr)12822 static Bool dis_dfp_arith(UInt theInstr)
12823 {
12824    UInt opc2 = ifieldOPClo10( theInstr );
12825    UChar frS_addr = ifieldRegDS( theInstr );
12826    UChar frA_addr = ifieldRegA( theInstr );
12827    UChar frB_addr = ifieldRegB( theInstr );
12828    UChar flag_rC = ifieldBIT0( theInstr );
12829 
12830    IRTemp frA = newTemp( Ity_D64 );
12831    IRTemp frB = newTemp( Ity_D64 );
12832    IRTemp frS = newTemp( Ity_D64 );
12833    IRExpr* round = get_IR_roundingmode_DFP();
12834 
12835    /* By default, if flag_RC is set, we will clear cr1 after the
12836     * operation.  In reality we should set cr1 to indicate the
12837     * exception status of the operation, but since we're not
12838     * simulating exceptions, the exception status will appear to be
12839     * zero.  Hence cr1 should be cleared if this is a . form insn.
12840     */
12841    Bool clear_CR1 = True;
12842 
12843    assign( frA, getDReg( frA_addr ) );
12844    assign( frB, getDReg( frB_addr ) );
12845 
12846    switch (opc2) {
12847    case 0x2: // dadd
12848       DIP( "dadd%s fr%u,fr%u,fr%u\n",
12849            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
12850       assign( frS, triop( Iop_AddD64, round, mkexpr( frA ), mkexpr( frB ) ) );
12851       break;
12852    case 0x202: // dsub
12853       DIP( "dsub%s fr%u,fr%u,fr%u\n",
12854            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
12855       assign( frS, triop( Iop_SubD64, round, mkexpr( frA ), mkexpr( frB ) ) );
12856       break;
12857    case 0x22: // dmul
12858       DIP( "dmul%s fr%u,fr%u,fr%u\n",
12859            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
12860       assign( frS, triop( Iop_MulD64, round, mkexpr( frA ), mkexpr( frB ) ) );
12861       break;
12862    case 0x222: // ddiv
12863       DIP( "ddiv%s fr%u,fr%u,fr%u\n",
12864            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
12865       assign( frS, triop( Iop_DivD64, round, mkexpr( frA ), mkexpr( frB ) ) );
12866       break;
12867    }
12868 
12869    putDReg( frS_addr, mkexpr( frS ) );
12870 
12871    if (flag_rC && clear_CR1) {
12872       putCR321( 1, mkU8( 0 ) );
12873       putCR0( 1, mkU8( 0 ) );
12874    }
12875 
12876    return True;
12877 }
12878 
12879 /* Quad DFP Arithmetic instructions */
dis_dfp_arithq(UInt theInstr)12880 static Bool dis_dfp_arithq(UInt theInstr)
12881 {
12882    UInt opc2 = ifieldOPClo10( theInstr );
12883    UChar frS_addr = ifieldRegDS( theInstr );
12884    UChar frA_addr = ifieldRegA( theInstr );
12885    UChar frB_addr = ifieldRegB( theInstr );
12886    UChar flag_rC = ifieldBIT0( theInstr );
12887 
12888    IRTemp frA = newTemp( Ity_D128 );
12889    IRTemp frB = newTemp( Ity_D128 );
12890    IRTemp frS = newTemp( Ity_D128 );
12891    IRExpr* round = get_IR_roundingmode_DFP();
12892 
12893    /* By default, if flag_RC is set, we will clear cr1 after the
12894     * operation.  In reality we should set cr1 to indicate the
12895     * exception status of the operation, but since we're not
12896     * simulating exceptions, the exception status will appear to be
12897     * zero.  Hence cr1 should be cleared if this is a . form insn.
12898     */
12899    Bool clear_CR1 = True;
12900 
12901    assign( frA, getDReg_pair( frA_addr ) );
12902    assign( frB, getDReg_pair( frB_addr ) );
12903 
12904    switch (opc2) {
12905    case 0x2: // daddq
12906       DIP( "daddq%s fr%u,fr%u,fr%u\n",
12907            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
12908       assign( frS, triop( Iop_AddD128, round, mkexpr( frA ), mkexpr( frB ) ) );
12909       break;
12910    case 0x202: // dsubq
12911       DIP( "dsubq%s fr%u,fr%u,fr%u\n",
12912            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
12913       assign( frS, triop( Iop_SubD128, round, mkexpr( frA ), mkexpr( frB ) ) );
12914       break;
12915    case 0x22: // dmulq
12916       DIP( "dmulq%s fr%u,fr%u,fr%u\n",
12917            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
12918       assign( frS, triop( Iop_MulD128, round, mkexpr( frA ), mkexpr( frB ) ) );
12919       break;
12920    case 0x222: // ddivq
12921       DIP( "ddivq%s fr%u,fr%u,fr%u\n",
12922            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
12923       assign( frS, triop( Iop_DivD128, round, mkexpr( frA ), mkexpr( frB ) ) );
12924       break;
12925    }
12926 
12927    putDReg_pair( frS_addr, mkexpr( frS ) );
12928 
12929    if (flag_rC && clear_CR1) {
12930       putCR321( 1, mkU8( 0 ) );
12931       putCR0( 1, mkU8( 0 ) );
12932    }
12933 
12934    return True;
12935 }
12936 
12937 /* DFP 64-bit logical shift instructions  */
dis_dfp_shift(UInt theInstr)12938 static Bool dis_dfp_shift(UInt theInstr) {
12939    UInt opc2       = ifieldOPClo9( theInstr );
12940    UChar frS_addr  = ifieldRegDS( theInstr );
12941    UChar frA_addr  = ifieldRegA( theInstr );
12942    UChar shift_val = IFIELD(theInstr, 10, 6);
12943    UChar flag_rC   = ifieldBIT0( theInstr );
12944 
12945    IRTemp frA = newTemp( Ity_D64 );
12946    IRTemp frS = newTemp( Ity_D64 );
12947    Bool clear_CR1 = True;
12948 
12949    assign( frA, getDReg( frA_addr ) );
12950 
12951    switch (opc2) {
12952    case 0x42: // dscli
12953       DIP( "dscli%s fr%u,fr%u,%u\n",
12954            flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
12955       assign( frS, binop( Iop_ShlD64, mkexpr( frA ), mkU8( shift_val ) ) );
12956       break;
12957    case 0x62: // dscri
12958       DIP( "dscri%s fr%u,fr%u,%u\n",
12959            flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
12960       assign( frS, binop( Iop_ShrD64, mkexpr( frA ), mkU8( shift_val ) ) );
12961       break;
12962    }
12963 
12964    putDReg( frS_addr, mkexpr( frS ) );
12965 
12966    if (flag_rC && clear_CR1) {
12967       putCR321( 1, mkU8( 0 ) );
12968       putCR0( 1, mkU8( 0 ) );
12969    }
12970 
12971    return True;
12972 }
12973 
12974 /* Quad DFP  logical shift instructions  */
dis_dfp_shiftq(UInt theInstr)12975 static Bool dis_dfp_shiftq(UInt theInstr) {
12976    UInt opc2       = ifieldOPClo9( theInstr );
12977    UChar frS_addr  = ifieldRegDS( theInstr );
12978    UChar frA_addr  = ifieldRegA( theInstr );
12979    UChar shift_val = IFIELD(theInstr, 10, 6);
12980    UChar flag_rC   = ifieldBIT0( theInstr );
12981 
12982    IRTemp frA = newTemp( Ity_D128 );
12983    IRTemp frS = newTemp( Ity_D128 );
12984    Bool clear_CR1 = True;
12985 
12986    assign( frA, getDReg_pair( frA_addr ) );
12987 
12988    switch (opc2) {
12989    case 0x42: // dscliq
12990       DIP( "dscliq%s fr%u,fr%u,%u\n",
12991            flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
12992       assign( frS, binop( Iop_ShlD128, mkexpr( frA ), mkU8( shift_val ) ) );
12993       break;
12994    case 0x62: // dscriq
12995       DIP( "dscriq%s fr%u,fr%u,%u\n",
12996            flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
12997       assign( frS, binop( Iop_ShrD128, mkexpr( frA ), mkU8( shift_val ) ) );
12998       break;
12999    }
13000 
13001    putDReg_pair( frS_addr, mkexpr( frS ) );
13002 
13003    if (flag_rC && clear_CR1) {
13004       putCR321( 1, mkU8( 0 ) );
13005       putCR0( 1, mkU8( 0 ) );
13006    }
13007 
13008    return True;
13009 }
13010 
13011 /* DFP 64-bit format conversion instructions */
dis_dfp_fmt_conv(UInt theInstr)13012 static Bool dis_dfp_fmt_conv(UInt theInstr) {
13013    UInt opc2      = ifieldOPClo10( theInstr );
13014    UChar frS_addr = ifieldRegDS( theInstr );
13015    UChar frB_addr = ifieldRegB( theInstr );
13016    IRExpr* round  = get_IR_roundingmode_DFP();
13017    UChar flag_rC  = ifieldBIT0( theInstr );
13018    IRTemp frB;
13019    IRTemp frS;
13020    Bool clear_CR1 = True;
13021 
13022    switch (opc2) {
13023    case 0x102: //dctdp
13024       DIP( "dctdp%s fr%u,fr%u\n",
13025            flag_rC ? ".":"", frS_addr, frB_addr );
13026 
13027       frB = newTemp( Ity_D32 );
13028       frS = newTemp( Ity_D64 );
13029       assign( frB, getDReg32( frB_addr ) );
13030       assign( frS, unop( Iop_D32toD64, mkexpr( frB ) ) );
13031       putDReg( frS_addr, mkexpr( frS ) );
13032       break;
13033    case 0x302: // drsp
13034       DIP( "drsp%s fr%u,fr%u\n",
13035            flag_rC ? ".":"", frS_addr, frB_addr );
13036       frB = newTemp( Ity_D64 );
13037       frS = newTemp( Ity_D32 );
13038       assign( frB, getDReg( frB_addr ) );
13039       assign( frS, binop( Iop_D64toD32, round, mkexpr( frB ) ) );
13040       putDReg32( frS_addr, mkexpr( frS ) );
13041       break;
13042    case 0x122: // dctfix
13043       {
13044          IRTemp tmp = newTemp( Ity_I64 );
13045 
13046          DIP( "dctfix%s fr%u,fr%u\n",
13047               flag_rC ? ".":"", frS_addr, frB_addr );
13048          frB = newTemp( Ity_D64 );
13049          frS = newTemp( Ity_D64 );
13050          assign( frB, getDReg( frB_addr ) );
13051          assign( tmp, binop( Iop_D64toI64S, round, mkexpr( frB ) ) );
13052          assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
13053          putDReg( frS_addr, mkexpr( frS ) );
13054       }
13055       break;
13056    case 0x322: // dcffix
13057       DIP( "dcffix%s fr%u,fr%u\n",
13058            flag_rC ? ".":"", frS_addr, frB_addr );
13059       frB = newTemp( Ity_D64 );
13060       frS = newTemp( Ity_D64 );
13061       assign( frB, getDReg( frB_addr ) );
13062       assign( frS, binop( Iop_I64StoD64,
13063                           round,
13064                           unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ) );
13065       putDReg( frS_addr, mkexpr( frS ) );
13066       break;
13067    }
13068 
13069    if (flag_rC && clear_CR1) {
13070       putCR321( 1, mkU8( 0 ) );
13071       putCR0( 1, mkU8( 0 ) );
13072    }
13073 
13074    return True;
13075 }
13076 
13077 /* Quad DFP format conversion instructions */
dis_dfp_fmt_convq(UInt theInstr)13078 static Bool dis_dfp_fmt_convq(UInt theInstr) {
13079    UInt opc2      = ifieldOPClo10( theInstr );
13080    UChar frS_addr = ifieldRegDS( theInstr );
13081    UChar frB_addr = ifieldRegB( theInstr );
13082    IRExpr* round  = get_IR_roundingmode_DFP();
13083    IRTemp frB64   = newTemp( Ity_D64 );
13084    IRTemp frB128  = newTemp( Ity_D128 );
13085    IRTemp frS64   = newTemp( Ity_D64 );
13086    IRTemp frS128  = newTemp( Ity_D128 );
13087    UChar flag_rC  = ifieldBIT0( theInstr );
13088    Bool clear_CR1 = True;
13089 
13090    switch (opc2) {
13091    case 0x102: // dctqpq
13092       DIP( "dctqpq%s fr%u,fr%u\n",
13093            flag_rC ? ".":"", frS_addr, frB_addr );
13094       assign( frB64, getDReg( frB_addr ) );
13095       assign( frS128, unop( Iop_D64toD128, mkexpr( frB64 ) ) );
13096       putDReg_pair( frS_addr, mkexpr( frS128 ) );
13097       break;
13098    case 0x122: // dctfixq
13099       {
13100          IRTemp tmp = newTemp( Ity_I64 );
13101 
13102          DIP( "dctfixq%s fr%u,fr%u\n",
13103               flag_rC ? ".":"", frS_addr, frB_addr );
13104          assign( frB128, getDReg_pair( frB_addr ) );
13105          assign( tmp, binop( Iop_D128toI64S, round, mkexpr( frB128 ) ) );
13106          assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
13107          putDReg( frS_addr, mkexpr( frS64 ) );
13108       }
13109       break;
13110    case 0x302: //drdpq
13111       DIP( "drdpq%s fr%u,fr%u\n",
13112            flag_rC ? ".":"", frS_addr, frB_addr );
13113       assign( frB128, getDReg_pair( frB_addr ) );
13114       assign( frS64, binop( Iop_D128toD64, round, mkexpr( frB128 ) ) );
13115       putDReg( frS_addr, mkexpr( frS64 ) );
13116       break;
13117    case 0x322: // dcffixq
13118      {
13119       /* Have to introduce an IOP for this instruction so it will work
13120        * on POWER 6 because emulating the instruction requires a POWER 7
13121        * DFP instruction in the emulation code.
13122        */
13123       DIP( "dcffixq%s fr%u,fr%u\n",
13124            flag_rC ? ".":"", frS_addr, frB_addr );
13125       assign( frB64, getDReg( frB_addr ) );
13126       assign( frS128, unop( Iop_I64StoD128,
13127                             unop( Iop_ReinterpD64asI64,
13128                                   mkexpr( frB64 ) ) ) );
13129       putDReg_pair( frS_addr, mkexpr( frS128 ) );
13130       break;
13131      }
13132    }
13133 
13134    if (flag_rC && clear_CR1) {
13135       putCR321( 1, mkU8( 0 ) );
13136       putCR0( 1, mkU8( 0 ) );
13137    }
13138 
13139    return True;
13140 }
13141 
dis_dfp_round(UInt theInstr)13142 static Bool dis_dfp_round( UInt theInstr ) {
13143    UChar frS_addr = ifieldRegDS(theInstr);
13144    UChar R        = IFIELD(theInstr, 16, 1);
13145    UChar RMC      = IFIELD(theInstr, 9, 2);
13146    UChar frB_addr = ifieldRegB( theInstr );
13147    UChar flag_rC  = ifieldBIT0( theInstr );
13148    IRTemp frB     = newTemp( Ity_D64 );
13149    IRTemp frS     = newTemp( Ity_D64 );
13150    UInt opc2      = ifieldOPClo8( theInstr );
13151    Bool clear_CR1 = True;
13152 
13153    switch (opc2) {
13154    /* drintn, is the same as drintx.  The only difference is this
13155     * instruction does not generate an exception for an inexact operation.
13156     * Currently not supporting inexact exceptions.
13157     */
13158    case 0x63: // drintx
13159    case 0xE3: // drintn
13160       DIP( "drintx/drintn%s fr%u,fr%u\n",
13161            flag_rC ? ".":"", frS_addr, frB_addr );
13162 
13163       /* NOTE, this instruction takes a DFP value and rounds to the
13164        * neares floating point integer value, i.e. fractional part
13165        * is zero.  The result is a floating point number.
13166        */
13167       /* pass the value of R and RMC in the same field */
13168       assign( frB, getDReg( frB_addr ) );
13169       assign( frS, binop( Iop_RoundD64toInt,
13170                           mkU32( ( R << 3 ) | RMC ),
13171                           mkexpr( frB ) ) );
13172       putDReg( frS_addr, mkexpr( frS ) );
13173       break;
13174    default:
13175       vex_printf("dis_dfp_round(ppc)(opc2)\n");
13176       return False;
13177    }
13178 
13179    if (flag_rC && clear_CR1) {
13180       putCR321( 1, mkU8( 0 ) );
13181       putCR0( 1, mkU8( 0 ) );
13182    }
13183 
13184    return True;
13185 }
13186 
dis_dfp_roundq(UInt theInstr)13187 static Bool dis_dfp_roundq(UInt theInstr) {
13188    UChar frS_addr = ifieldRegDS( theInstr );
13189    UChar frB_addr = ifieldRegB( theInstr );
13190    UChar R = IFIELD(theInstr, 16, 1);
13191    UChar RMC = IFIELD(theInstr, 9, 2);
13192    UChar flag_rC = ifieldBIT0( theInstr );
13193    IRTemp frB = newTemp( Ity_D128 );
13194    IRTemp frS = newTemp( Ity_D128 );
13195    Bool clear_CR1 = True;
13196    UInt opc2 = ifieldOPClo8( theInstr );
13197 
13198    switch (opc2) {
13199    /* drintnq, is the same as drintxq.  The only difference is this
13200     * instruction does not generate an exception for an inexact operation.
13201     * Currently not supporting inexact exceptions.
13202     */
13203    case 0x63: // drintxq
13204    case 0xE3: // drintnq
13205       DIP( "drintxq/drintnq%s fr%u,fr%u\n",
13206            flag_rC ? ".":"", frS_addr, frB_addr );
13207 
13208       /* pass the value of R and RMC in the same field */
13209       assign( frB, getDReg_pair( frB_addr ) );
13210       assign( frS, binop( Iop_RoundD128toInt,
13211                           mkU32( ( R << 3 ) | RMC ),
13212                           mkexpr( frB ) ) );
13213       putDReg_pair( frS_addr, mkexpr( frS ) );
13214       break;
13215    default:
13216       vex_printf("dis_dfp_roundq(ppc)(opc2)\n");
13217       return False;
13218    }
13219 
13220    if (flag_rC && clear_CR1) {
13221       putCR321( 1, mkU8( 0 ) );
13222       putCR0( 1, mkU8( 0 ) );
13223    }
13224 
13225    return True;
13226 }
13227 
dis_dfp_quantize_sig_rrnd(UInt theInstr)13228 static Bool dis_dfp_quantize_sig_rrnd(UInt theInstr) {
13229    UInt opc2 = ifieldOPClo8( theInstr );
13230    UChar frS_addr = ifieldRegDS( theInstr );
13231    UChar frA_addr = ifieldRegA( theInstr );
13232    UChar frB_addr = ifieldRegB( theInstr );
13233    UChar flag_rC = ifieldBIT0( theInstr );
13234    UInt TE_value = IFIELD(theInstr, 16, 4);
13235    UInt TE_sign  = IFIELD(theInstr, 20, 1);
13236    UInt RMC = IFIELD(theInstr, 9, 2);
13237    IRTemp frA = newTemp( Ity_D64 );
13238    IRTemp frB = newTemp( Ity_D64 );
13239    IRTemp frS = newTemp( Ity_D64 );
13240    Bool clear_CR1 = True;
13241 
13242    assign( frB, getDReg( frB_addr ) );
13243 
13244    switch (opc2) {
13245    case 0x43: // dquai
13246       DIP( "dquai%s fr%u,fr%u,fr%u\n",
13247            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
13248       IRTemp TE_I64 = newTemp( Ity_I64 );
13249 
13250       /* Generate a reference DFP value frA with the desired exponent
13251        * given by TE using significand from frB.  Need to add the bias
13252        * 398 to TE.  TE is stored as a 2's complement number.
13253        */
13254       if (TE_sign == 1) {
13255          /* Take 2's complement of the 5-bit value and subtract from bias.
13256           *  Bias is adjusted for the +1 required when taking 2's complement.
13257           */
13258          assign( TE_I64,
13259                  unop( Iop_32Uto64,
13260                        binop( Iop_Sub32, mkU32( 397 ),
13261                               binop( Iop_And32, mkU32( 0xF ),
13262                                      unop( Iop_Not32, mkU32( TE_value ) )
13263                                      ) ) ) );
13264 
13265       } else {
13266           assign( TE_I64,
13267                   unop( Iop_32Uto64,
13268                         binop( Iop_Add32, mkU32( 398 ), mkU32( TE_value ) )
13269                         ) );
13270       }
13271 
13272       assign( frA, binop( Iop_InsertExpD64, mkexpr( TE_I64 ),
13273                           unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) );
13274 
13275       assign( frS, triop( Iop_QuantizeD64,
13276                           mkU32( RMC ),
13277                           mkexpr( frA ),
13278                           mkexpr( frB ) ) );
13279       break;
13280 
13281    case 0x3: // dqua
13282       DIP( "dqua%s fr%u,fr%u,fr%u\n",
13283            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
13284       assign( frA, getDReg( frA_addr ) );
13285       assign( frS, triop( Iop_QuantizeD64,
13286                           mkU32( RMC ),
13287                           mkexpr( frA ),
13288                           mkexpr( frB ) ) );
13289       break;
13290    case 0x23: // drrnd
13291       {
13292          IRTemp tmp = newTemp( Ity_I8 );
13293 
13294          DIP( "drrnd%s fr%u,fr%u,fr%u\n",
13295               flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
13296          assign( frA, getDReg( frA_addr ) );
13297          /* Iop_64to8 not supported in 32 bit mode, do it in two steps. */
13298          assign( tmp, unop( Iop_32to8,
13299                             unop( Iop_64to32,
13300                                   unop( Iop_ReinterpD64asI64,
13301                                         mkexpr( frA ) ) ) ) );
13302          assign( frS, triop( Iop_SignificanceRoundD64,
13303                              mkU32( RMC ),
13304                              mkexpr( tmp ),
13305                              mkexpr( frB ) ) );
13306       }
13307       break;
13308    default:
13309       vex_printf("dis_dfp_quantize_sig_rrnd(ppc)(opc2)\n");
13310       return False;
13311    }
13312    putDReg( frS_addr, mkexpr( frS ) );
13313 
13314    if (flag_rC && clear_CR1) {
13315       putCR321( 1, mkU8( 0 ) );
13316       putCR0( 1, mkU8( 0 ) );
13317    }
13318 
13319    return True;
13320 }
13321 
dis_dfp_quantize_sig_rrndq(UInt theInstr)13322 static Bool dis_dfp_quantize_sig_rrndq(UInt theInstr) {
13323    UInt opc2 = ifieldOPClo8( theInstr );
13324    UChar frS_addr = ifieldRegDS( theInstr );
13325    UChar frA_addr = ifieldRegA( theInstr );
13326    UChar frB_addr = ifieldRegB( theInstr );
13327    UChar flag_rC = ifieldBIT0( theInstr );
13328    UInt TE_value = IFIELD(theInstr, 16, 4);
13329    UInt TE_sign  = IFIELD(theInstr, 20, 1);
13330    UInt RMC = IFIELD(theInstr, 9, 2);
13331    IRTemp frA = newTemp( Ity_D128 );
13332    IRTemp frB = newTemp( Ity_D128 );
13333    IRTemp frS = newTemp( Ity_D128 );
13334    Bool clear_CR1 = True;
13335 
13336    assign( frB, getDReg_pair( frB_addr ) );
13337 
13338    switch (opc2) {
13339    case 0x43: // dquaiq
13340       DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
13341            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
13342       IRTemp TE_I64 = newTemp( Ity_I64 );
13343 
13344       /* Generate a reference DFP value frA with the desired exponent
13345        * given by TE using significand of 1.  Need to add the bias
13346        * 6176 to TE.
13347        */
13348       if (TE_sign == 1) {
13349          /* Take 2's complement of the 5-bit value and subtract from bias.
13350           *  Bias adjusted for the +1 required when taking 2's complement.
13351           */
13352          assign( TE_I64,
13353                  unop( Iop_32Uto64,
13354                        binop( Iop_Sub32, mkU32( 6175 ),
13355                               binop( Iop_And32, mkU32( 0xF ),
13356                                      unop( Iop_Not32, mkU32( TE_value ) )
13357                                      ) ) ) );
13358 
13359       } else {
13360          assign( TE_I64,
13361                  unop( Iop_32Uto64,
13362                        binop( Iop_Add32,
13363                              mkU32( 6176 ),
13364                              mkU32( TE_value ) ) ) );
13365       }
13366 
13367       assign( frA,
13368               binop( Iop_InsertExpD128, mkexpr( TE_I64 ),
13369                      unop( Iop_D64toD128,
13370                            unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) ) );
13371       assign( frS, triop( Iop_QuantizeD128,
13372                           mkU32( RMC ),
13373                           mkexpr( frA ),
13374                           mkexpr( frB ) ) );
13375       break;
13376    case 0x3: // dquaq
13377       DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
13378            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
13379       assign( frA, getDReg_pair( frA_addr ) );
13380       assign( frS, triop( Iop_QuantizeD128,
13381                           mkU32( RMC ),
13382                           mkexpr( frA ),
13383                           mkexpr( frB ) ) );
13384       break;
13385    case 0x23: // drrndq
13386       {
13387          IRTemp tmp = newTemp( Ity_I8 );
13388 
13389          DIP( "drrndq%s fr%u,fr%u,fr%u\n",
13390               flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
13391          assign( frA, getDReg_pair( frA_addr ) );
13392          assign( tmp, unop( Iop_32to8,
13393                             unop( Iop_64to32,
13394                                   unop( Iop_ReinterpD64asI64,
13395                                         unop( Iop_D128HItoD64,
13396                                               mkexpr( frA ) ) ) ) ) );
13397          assign( frS, triop( Iop_SignificanceRoundD128,
13398                              mkU32( RMC ),
13399                              mkexpr( tmp ),
13400                              mkexpr( frB ) ) );
13401       }
13402       break;
13403    default:
13404       vex_printf("dis_dfp_quantize_sig_rrndq(ppc)(opc2)\n");
13405       return False;
13406    }
13407    putDReg_pair( frS_addr, mkexpr( frS ) );
13408 
13409    if (flag_rC && clear_CR1) {
13410       putCR321( 1, mkU8( 0 ) );
13411       putCR0( 1, mkU8( 0 ) );
13412    }
13413 
13414    return True;
13415 }
13416 
dis_dfp_extract_insert(UInt theInstr)13417 static Bool dis_dfp_extract_insert(UInt theInstr) {
13418    UInt opc2 = ifieldOPClo10( theInstr );
13419    UChar frS_addr = ifieldRegDS( theInstr );
13420    UChar frA_addr = ifieldRegA( theInstr );
13421    UChar frB_addr = ifieldRegB( theInstr );
13422    UChar flag_rC = ifieldBIT0( theInstr );
13423    Bool clear_CR1 = True;
13424 
13425    IRTemp frA = newTemp( Ity_D64 );
13426    IRTemp frB = newTemp( Ity_D64 );
13427    IRTemp frS = newTemp( Ity_D64 );
13428    IRTemp tmp = newTemp( Ity_I64 );
13429 
13430    assign( frA, getDReg( frA_addr ) );
13431    assign( frB, getDReg( frB_addr ) );
13432 
13433    switch (opc2) {
13434    case 0x162: // dxex
13435       DIP( "dxex%s fr%u,fr%u,fr%u\n",
13436            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
13437       assign( tmp, unop( Iop_ExtractExpD64, mkexpr( frB ) ) );
13438       assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
13439       break;
13440    case 0x362: // diex
13441       DIP( "diex%s fr%u,fr%u,fr%u\n",
13442            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
13443       assign( frS, binop( Iop_InsertExpD64,
13444                           unop( Iop_ReinterpD64asI64,
13445                                 mkexpr( frA ) ),
13446                           mkexpr( frB ) ) );
13447       break;
13448    default:
13449       vex_printf("dis_dfp_extract_insert(ppc)(opc2)\n");
13450       return False;
13451    }
13452 
13453    putDReg( frS_addr, mkexpr( frS ) );
13454 
13455    if (flag_rC && clear_CR1) {
13456       putCR321( 1, mkU8( 0 ) );
13457       putCR0( 1, mkU8( 0 ) );
13458    }
13459 
13460    return True;
13461 }
13462 
dis_dfp_extract_insertq(UInt theInstr)13463 static Bool dis_dfp_extract_insertq(UInt theInstr) {
13464    UInt opc2 = ifieldOPClo10( theInstr );
13465    UChar frS_addr = ifieldRegDS( theInstr );
13466    UChar frA_addr = ifieldRegA( theInstr );
13467    UChar frB_addr = ifieldRegB( theInstr );
13468    UChar flag_rC = ifieldBIT0( theInstr );
13469 
13470    IRTemp frA   = newTemp( Ity_D64 );
13471    IRTemp frB   = newTemp( Ity_D128 );
13472    IRTemp frS64 = newTemp( Ity_D64 );
13473    IRTemp frS   = newTemp( Ity_D128 );
13474    IRTemp tmp   = newTemp( Ity_I64 );
13475    Bool clear_CR1 = True;
13476 
13477    assign( frB, getDReg_pair( frB_addr ) );
13478 
13479    switch (opc2) {
13480    case 0x162:  // dxexq
13481       DIP( "dxexq%s fr%u,fr%u\n",
13482            flag_rC ? ".":"", frS_addr,  frB_addr );
13483       /* Instruction actually returns a 64-bit result.  So as to be
13484        * consistent and not have to add a new struct, the emulation returns
13485        * the 64-bit result in the upper and lower register.
13486        */
13487       assign( tmp, unop( Iop_ExtractExpD128, mkexpr( frB ) ) );
13488       assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
13489       putDReg( frS_addr, mkexpr( frS64 ) );
13490       break;
13491    case 0x362:  // diexq
13492       DIP( "diexq%s fr%u,fr%u,fr%u\n",
13493            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
13494       assign( frA, getDReg( frA_addr ) );
13495       assign( frS, binop( Iop_InsertExpD128,
13496                           unop( Iop_ReinterpD64asI64, mkexpr( frA ) ),
13497                           mkexpr( frB ) ) );
13498       putDReg_pair( frS_addr, mkexpr( frS ) );
13499       break;
13500    default:
13501       vex_printf("dis_dfp_extract_insertq(ppc)(opc2)\n");
13502       return False;
13503    }
13504 
13505    if (flag_rC && clear_CR1) {
13506       putCR321( 1, mkU8( 0 ) );
13507       putCR0( 1, mkU8( 0 ) );
13508    }
13509 
13510    return True;
13511 }
13512 
13513 /* DFP 64-bit comparison instructions */
dis_dfp_compare(UInt theInstr)13514 static Bool dis_dfp_compare(UInt theInstr) {
13515    /* X-Form */
13516    UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF
13517    UChar frA_addr = ifieldRegA( theInstr );
13518    UChar frB_addr = ifieldRegB( theInstr );
13519    UInt opc1 = ifieldOPC( theInstr );
13520    IRTemp frA;
13521    IRTemp frB;
13522 
13523    IRTemp ccIR = newTemp( Ity_I32 );
13524    IRTemp ccPPC32 = newTemp( Ity_I32 );
13525 
13526 
13527    /* Note: Differences between dcmpu and dcmpo are only in exception
13528     flag settings, which aren't supported anyway. */
13529    switch (opc1) {
13530    case 0x3B: /* dcmpo and dcmpu, DFP 64-bit */
13531       DIP( "dcmpo %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr );
13532       frA = newTemp( Ity_D64 );
13533       frB = newTemp( Ity_D64 );
13534 
13535       assign( frA, getDReg( frA_addr ) );
13536       assign( frB, getDReg( frB_addr ) );
13537 
13538       assign( ccIR, binop( Iop_CmpD64, mkexpr( frA ), mkexpr( frB ) ) );
13539       break;
13540    case 0x3F: /* dcmpoq and dcmpuq,DFP 128-bit */
13541       DIP( "dcmpoq %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr );
13542       frA = newTemp( Ity_D128 );
13543       frB = newTemp( Ity_D128 );
13544 
13545       assign( frA, getDReg_pair( frA_addr ) );
13546       assign( frB, getDReg_pair( frB_addr ) );
13547       assign( ccIR, binop( Iop_CmpD128, mkexpr( frA ), mkexpr( frB ) ) );
13548       break;
13549    default:
13550       vex_printf("dis_dfp_compare(ppc)(opc2)\n");
13551       return False;
13552    }
13553 
13554    /* Map compare result from IR to PPC32 */
13555    /*
13556     FP cmp result | PPC | IR
13557     --------------------------
13558     UN            | 0x1 | 0x45
13559     EQ            | 0x2 | 0x40
13560     GT            | 0x4 | 0x00
13561     LT            | 0x8 | 0x01
13562     */
13563 
13564    assign( ccPPC32,
13565            binop( Iop_Shl32,
13566                   mkU32( 1 ),
13567                   unop( Iop_32to8,
13568                         binop( Iop_Or32,
13569                                binop( Iop_And32,
13570                                       unop( Iop_Not32,
13571                                             binop( Iop_Shr32,
13572                                                    mkexpr( ccIR ),
13573                                                    mkU8( 5 ) ) ),
13574                                       mkU32( 2 ) ),
13575                                binop( Iop_And32,
13576                                       binop( Iop_Xor32,
13577                                              mkexpr( ccIR ),
13578                                              binop( Iop_Shr32,
13579                                                     mkexpr( ccIR ),
13580                                                     mkU8( 6 ) ) ),
13581                                       mkU32( 1 ) ) ) ) ) );
13582 
13583    putGST_field( PPC_GST_CR, mkexpr( ccPPC32 ), crfD );
13584    putFPCC( mkexpr( ccPPC32 ) );
13585    return True;
13586 }
13587 
13588 /* Test class/group/exponent/significance instructions. */
dis_dfp_exponent_test(UInt theInstr)13589 static Bool dis_dfp_exponent_test ( UInt theInstr )
13590 {
13591    UChar frA_addr   = ifieldRegA( theInstr );
13592    UChar frB_addr   = ifieldRegB( theInstr );
13593    UChar crfD       = toUChar( IFIELD( theInstr, 23, 3 ) );
13594    IRTemp frA       = newTemp( Ity_D64 );
13595    IRTemp frB       = newTemp( Ity_D64 );
13596    IRTemp frA128    = newTemp( Ity_D128 );
13597    IRTemp frB128    = newTemp( Ity_D128 );
13598    UInt opc1        = ifieldOPC( theInstr );
13599    IRTemp gfield_A  = newTemp( Ity_I32 );
13600    IRTemp gfield_B  = newTemp( Ity_I32 );
13601    IRTemp gfield_mask   = newTemp( Ity_I32 );
13602    IRTemp exponent_A    = newTemp( Ity_I32 );
13603    IRTemp exponent_B    = newTemp( Ity_I32 );
13604    IRTemp A_NaN_true    = newTemp( Ity_I32 );
13605    IRTemp B_NaN_true    = newTemp( Ity_I32 );
13606    IRTemp A_inf_true    = newTemp( Ity_I32 );
13607    IRTemp B_inf_true    = newTemp( Ity_I32 );
13608    IRTemp A_equals_B    = newTemp( Ity_I32 );
13609    IRTemp finite_number = newTemp( Ity_I32 );
13610    IRTemp cc0 = newTemp( Ity_I32 );
13611    IRTemp cc1 = newTemp( Ity_I32 );
13612    IRTemp cc2 = newTemp( Ity_I32 );
13613    IRTemp cc3 = newTemp( Ity_I32 );
13614    IRTemp cc  = newTemp( Ity_I32 );
13615 
13616    /* The dtstex and dtstexg instructions only differ in the size of the
13617     * exponent field.  The following switch statement takes care of the size
13618     * specific setup.  Once the value of the exponents, the G-field shift
13619     * and mask is setup the remaining code is identical.
13620     */
13621    switch (opc1) {
13622    case 0x3b: // dtstex       Extended instruction setup
13623       DIP("dtstex %u,r%u,r%d\n", crfD, frA_addr, frB_addr);
13624       assign( frA, getDReg( frA_addr ) );
13625       assign( frB, getDReg( frB_addr ) );
13626       assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) );
13627       assign(exponent_A, unop( Iop_64to32,
13628                                unop( Iop_ExtractExpD64,
13629                                      mkexpr( frA ) ) ) );
13630       assign(exponent_B, unop( Iop_64to32,
13631                                unop( Iop_ExtractExpD64,
13632                                      mkexpr( frB ) ) ) );
13633       break;
13634 
13635    case 0x3F: //  dtstexq      Quad instruction setup
13636       DIP("dtstexq %u,r%u,r%d\n", crfD, frA_addr, frB_addr);
13637       assign( frA128, getDReg_pair( frA_addr ) );
13638       assign( frB128, getDReg_pair( frB_addr ) );
13639       assign( frA, unop( Iop_D128HItoD64, mkexpr( frA128 ) ) );
13640       assign( frB, unop( Iop_D128HItoD64, mkexpr( frB128 ) ) );
13641       assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) );
13642       assign( exponent_A, unop( Iop_64to32,
13643                                 unop( Iop_ExtractExpD128,
13644                                       mkexpr( frA128 ) ) ) );
13645       assign( exponent_B, unop( Iop_64to32,
13646                                 unop( Iop_ExtractExpD128,
13647                                       mkexpr( frB128 ) ) ) );
13648       break;
13649    default:
13650       vex_printf("dis_dfp_exponent_test(ppc)(opc2)\n");
13651       return False;
13652    }
13653 
13654    /* Extract the Gfield */
13655    assign( gfield_A, binop( Iop_And32,
13656                             mkexpr( gfield_mask ),
13657                             unop( Iop_64HIto32,
13658                                   unop( Iop_ReinterpD64asI64,
13659                                         mkexpr(frA) ) ) ) );
13660 
13661    assign( gfield_B, binop( Iop_And32,
13662                             mkexpr( gfield_mask ),
13663                             unop( Iop_64HIto32,
13664                                   unop( Iop_ReinterpD64asI64,
13665                                         mkexpr(frB) ) ) ) );
13666 
13667    /* check for NAN */
13668    assign( A_NaN_true, binop(Iop_Or32,
13669                              unop( Iop_1Sto32,
13670                                    binop( Iop_CmpEQ32,
13671                                           mkexpr( gfield_A ),
13672                                           mkU32( 0x7C000000 ) ) ),
13673                              unop( Iop_1Sto32,
13674                                    binop( Iop_CmpEQ32,
13675                                           mkexpr( gfield_A ),
13676                                           mkU32( 0x7E000000 ) )
13677                                    ) ) );
13678    assign( B_NaN_true, binop(Iop_Or32,
13679                              unop( Iop_1Sto32,
13680                                    binop( Iop_CmpEQ32,
13681                                           mkexpr( gfield_B ),
13682                                           mkU32( 0x7C000000 ) ) ),
13683                              unop( Iop_1Sto32,
13684                                    binop( Iop_CmpEQ32,
13685                                           mkexpr( gfield_B ),
13686                                           mkU32( 0x7E000000 ) )
13687                              ) ) );
13688 
13689    /* check for infinity */
13690    assign( A_inf_true,
13691            unop( Iop_1Sto32,
13692                  binop( Iop_CmpEQ32,
13693                         mkexpr( gfield_A ),
13694                         mkU32( 0x78000000 ) ) ) );
13695 
13696    assign( B_inf_true,
13697            unop( Iop_1Sto32,
13698                  binop( Iop_CmpEQ32,
13699                         mkexpr( gfield_B ),
13700                         mkU32( 0x78000000 ) ) ) );
13701 
13702    assign( finite_number,
13703            unop( Iop_Not32,
13704                  binop( Iop_Or32,
13705                         binop( Iop_Or32,
13706                                mkexpr( A_NaN_true ),
13707                                mkexpr( B_NaN_true ) ),
13708                         binop( Iop_Or32,
13709                                mkexpr( A_inf_true ),
13710                                mkexpr( B_inf_true ) ) ) ) );
13711 
13712    /* Calculate the condition code bits
13713     * If QNaN,SNaN, +infinity, -infinity then cc0, cc1 and cc2 are zero
13714     * regardless of the value of the comparisons and cc3 is 1.  Otherwise,
13715     * cc0, cc1 and cc0 reflect the results of the comparisons.
13716     */
13717    assign( A_equals_B,
13718            binop( Iop_Or32,
13719                   unop( Iop_1Uto32,
13720                   binop( Iop_CmpEQ32,
13721                          mkexpr( exponent_A ),
13722                          mkexpr( exponent_B ) ) ),
13723                   binop( Iop_Or32,
13724                          binop( Iop_And32,
13725                                 mkexpr( A_inf_true ),
13726                                 mkexpr( B_inf_true ) ),
13727                          binop( Iop_And32,
13728                                 mkexpr( A_NaN_true ),
13729                                 mkexpr( B_NaN_true ) ) ) ) );
13730 
13731    assign( cc0, binop( Iop_And32,
13732                        mkexpr( finite_number ),
13733                        binop( Iop_Shl32,
13734                               unop( Iop_1Uto32,
13735                                     binop( Iop_CmpLT32U,
13736                                            mkexpr( exponent_A ),
13737                                            mkexpr( exponent_B ) ) ),
13738                                            mkU8( 3 ) ) ) );
13739 
13740    assign( cc1, binop( Iop_And32,
13741                        mkexpr( finite_number ),
13742                        binop( Iop_Shl32,
13743                               unop( Iop_1Uto32,
13744                                     binop( Iop_CmpLT32U,
13745                                            mkexpr( exponent_B ),
13746                                            mkexpr( exponent_A ) ) ),
13747                                            mkU8( 2 ) ) ) );
13748 
13749    assign( cc2, binop( Iop_Shl32,
13750                        binop( Iop_And32,
13751                               mkexpr( A_equals_B ),
13752                               mkU32( 1 ) ),
13753                               mkU8( 1 ) ) );
13754 
13755    assign( cc3, binop( Iop_And32,
13756                        unop( Iop_Not32, mkexpr( A_equals_B ) ),
13757                        binop( Iop_And32,
13758                               mkU32( 0x1 ),
13759                               binop( Iop_Or32,
13760                                      binop( Iop_Or32,
13761                                             mkexpr ( A_inf_true ),
13762                                             mkexpr ( B_inf_true ) ),
13763                                             binop( Iop_Or32,
13764                                                    mkexpr ( A_NaN_true ),
13765                                                    mkexpr ( B_NaN_true ) ) )
13766                               ) ) );
13767 
13768    /* store the condition code */
13769    assign( cc, binop( Iop_Or32,
13770                       mkexpr( cc0 ),
13771                       binop( Iop_Or32,
13772                              mkexpr( cc1 ),
13773                              binop( Iop_Or32,
13774                                     mkexpr( cc2 ),
13775                                     mkexpr( cc3 ) ) ) ) );
13776    putGST_field( PPC_GST_CR, mkexpr( cc ), crfD );
13777    putFPCC( mkexpr( cc ) );
13778    return True;
13779 }
13780 
13781 /* Test class/group/exponent/significance instructions. */
dis_dfp_class_test(UInt theInstr)13782 static Bool dis_dfp_class_test ( UInt theInstr )
13783 {
13784    UChar frA_addr   = ifieldRegA( theInstr );
13785    IRTemp frA       = newTemp( Ity_D64 );
13786    IRTemp abs_frA   = newTemp( Ity_D64 );
13787    IRTemp frAI64_hi = newTemp( Ity_I64 );
13788    IRTemp frAI64_lo = newTemp( Ity_I64 );
13789    UInt opc1        = ifieldOPC( theInstr );
13790    UInt opc2        = ifieldOPClo9( theInstr );
13791    UChar crfD       = toUChar( IFIELD( theInstr, 23, 3 ) );  // AKA BF
13792    UInt DCM         = IFIELD( theInstr, 10, 6 );
13793    IRTemp DCM_calc  = newTemp( Ity_I32 );
13794    UInt max_exp     = 0;
13795    UInt min_exp     = 0;
13796    IRTemp min_subnormalD64  = newTemp( Ity_D64 );
13797    IRTemp min_subnormalD128 = newTemp( Ity_D128 );
13798    IRTemp significand64  = newTemp( Ity_D64 );
13799    IRTemp significand128 = newTemp( Ity_D128 );
13800    IRTemp exp_min_normal = newTemp( Ity_I64 );
13801    IRTemp exponent       = newTemp( Ity_I32 );
13802 
13803    IRTemp infinity_true  = newTemp( Ity_I32 );
13804    IRTemp SNaN_true      = newTemp( Ity_I32 );
13805    IRTemp QNaN_true      = newTemp( Ity_I32 );
13806    IRTemp subnormal_true = newTemp( Ity_I32 );
13807    IRTemp normal_true    = newTemp( Ity_I32 );
13808    IRTemp extreme_true   = newTemp( Ity_I32 );
13809    IRTemp lmd            = newTemp( Ity_I32 );
13810    IRTemp lmd_zero_true  = newTemp( Ity_I32 );
13811    IRTemp zero_true      = newTemp( Ity_I32 );
13812    IRTemp sign           = newTemp( Ity_I32 );
13813    IRTemp field          = newTemp( Ity_I32 );
13814    IRTemp ccIR_zero      = newTemp( Ity_I32 );
13815    IRTemp ccIR_subnormal = newTemp( Ity_I32 );
13816 
13817    /* UInt size     = DFP_LONG;  JRS:unused */
13818    IRTemp gfield = newTemp( Ity_I32 );
13819    IRTemp gfield_0_4_shift  = newTemp( Ity_I8 );
13820    IRTemp gfield_mask       = newTemp( Ity_I32 );
13821    IRTemp dcm0 = newTemp( Ity_I32 );
13822    IRTemp dcm1 = newTemp( Ity_I32 );
13823    IRTemp dcm2 = newTemp( Ity_I32 );
13824    IRTemp dcm3 = newTemp( Ity_I32 );
13825    IRTemp dcm4 = newTemp( Ity_I32 );
13826    IRTemp dcm5 = newTemp( Ity_I32 );
13827 
13828    /* The only difference between the dtstdc and dtstdcq instructions is
13829     * size of the T and G fields.  The calculation of the 4 bit field
13830     * is the same.  Setup the parameters and values that are DFP size
13831     * specific.  The rest of the code is independent of the DFP size.
13832     *
13833     * The Io_CmpD64 is used below.  The instruction sets the ccIR values.
13834     * The interpretation of the ccIR values is as follows:
13835     *
13836     *    DFP cmp result | IR
13837     * --------------------------
13838     *	 UN             | 0x45
13839     *	 EQ             | 0x40
13840     *	 GT             | 0x00
13841     *	 LT             | 0x01
13842     */
13843 
13844    assign( frA, getDReg( frA_addr ) );
13845    assign( frAI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frA ) ) );
13846 
13847    assign( abs_frA, unop( Iop_ReinterpI64asD64,
13848                           binop( Iop_And64,
13849                                  unop( Iop_ReinterpD64asI64,
13850                                        mkexpr( frA ) ),
13851                                  mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ) );
13852    assign( gfield_0_4_shift, mkU8( 31 - 5 ) );  // G-field[0:4]
13853    switch (opc1) {
13854    case 0x3b: // dtstdc, dtstdg
13855       DIP("dtstd%s %u,r%u,%u\n", opc2 == 0xc2 ? "c" : "g",
13856                crfD, frA_addr, DCM);
13857       /* setup the parameters for the long format of the two instructions */
13858       assign( frAI64_lo, mkU64( 0 ) );
13859       assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) );
13860       max_exp = DFP_LONG_EXP_MAX;
13861       min_exp = DFP_LONG_EXP_MIN;
13862 
13863       assign( exponent, unop( Iop_64to32,
13864                               unop( Iop_ExtractExpD64,
13865                                     mkexpr( frA ) ) ) );
13866       assign( significand64,
13867               unop( Iop_ReinterpI64asD64,
13868                     mkU64( 0x2234000000000001ULL ) ) );  // dfp 1.0
13869       assign( exp_min_normal,mkU64( 398 - 383 ) );
13870       assign( min_subnormalD64,
13871               binop( Iop_InsertExpD64,
13872                      mkexpr( exp_min_normal ),
13873                      mkexpr( significand64 ) ) );
13874 
13875       assign( ccIR_subnormal,
13876               binop( Iop_CmpD64,
13877                      mkexpr( abs_frA ),
13878                      mkexpr( min_subnormalD64 ) ) );
13879 
13880       /* compare absolute value of frA with zero */
13881       assign( ccIR_zero,
13882               binop( Iop_CmpD64,
13883                      mkexpr( abs_frA ),
13884                      unop( Iop_ReinterpI64asD64,
13885                            mkU64( 0x2238000000000000ULL ) ) ) );
13886 
13887       /* size = DFP_LONG; JRS: unused */
13888       break;
13889 
13890    case 0x3F:   // dtstdcq, dtstdgq
13891       DIP("dtstd%sq %u,r%u,%u\n", opc2 == 0xc2 ? "c" : "g",
13892                crfD, frA_addr, DCM);
13893       /* setup the parameters for the extended format of the
13894        * two instructions
13895        */
13896       assign( frAI64_lo, unop( Iop_ReinterpD64asI64,
13897                                getDReg( frA_addr+1 ) ) );
13898 
13899       assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) );
13900       max_exp = DFP_EXTND_EXP_MAX;
13901       min_exp = DFP_EXTND_EXP_MIN;
13902       assign( exponent, unop( Iop_64to32,
13903                               unop( Iop_ExtractExpD128,
13904                                     getDReg_pair( frA_addr) ) ) );
13905 
13906       /* create quand exponent for minimum normal number */
13907       assign( exp_min_normal, mkU64( 6176 - 6143 ) );
13908       assign( significand128,
13909               unop( Iop_D64toD128,
13910                     unop( Iop_ReinterpI64asD64,
13911                           mkU64( 0x2234000000000001ULL ) ) ) );  // dfp 1.0
13912 
13913       assign( min_subnormalD128,
13914               binop( Iop_InsertExpD128,
13915                      mkexpr( exp_min_normal ),
13916                      mkexpr( significand128 ) ) );
13917 
13918       assign( ccIR_subnormal,
13919               binop( Iop_CmpD128,
13920                      binop( Iop_D64HLtoD128,
13921                             unop( Iop_ReinterpI64asD64,
13922                                   binop( Iop_And64,
13923                                          unop( Iop_ReinterpD64asI64,
13924                                                mkexpr( frA ) ),
13925                                          mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ),
13926                             getDReg( frA_addr+1 ) ),
13927                      mkexpr( min_subnormalD128 ) ) );
13928       assign( ccIR_zero,
13929               binop( Iop_CmpD128,
13930                      binop( Iop_D64HLtoD128,
13931                             mkexpr( abs_frA ),
13932                             getDReg( frA_addr+1 ) ),
13933                      unop( Iop_D64toD128,
13934                            unop( Iop_ReinterpI64asD64,
13935                                  mkU64( 0x0ULL ) ) ) ) );
13936 
13937       /* size = DFP_EXTND; JRS:unused */
13938       break;
13939    default:
13940       vex_printf("dis_dfp_class_test(ppc)(opc2)\n");
13941       return False;
13942    }
13943 
13944    /* The G-field is in the upper 32-bits.  The I64 logical operations
13945     * do not seem to be supported in 32-bit mode so keep things as 32-bit
13946     * operations.
13947     */
13948    assign( gfield, binop( Iop_And32,
13949                           mkexpr( gfield_mask ),
13950                           unop( Iop_64HIto32,
13951                                 mkexpr(frAI64_hi) ) ) );
13952 
13953    /* There is a lot of code that is the same to do the class and group
13954     * instructions.  Later there is an if statement to handle the specific
13955     * instruction.
13956     *
13957     * Will be using I32 values, compares, shifts and logical operations for
13958     * this code as the 64-bit compare, shifts, logical operations are not
13959     * supported in 32-bit mode.
13960     */
13961 
13962    /* Check the bits for Infinity, QNaN or Signaling NaN */
13963    assign( infinity_true,
13964            unop( Iop_1Sto32,
13965                  binop( Iop_CmpEQ32,
13966                         binop( Iop_And32,
13967                                mkU32( 0x7C000000 ),
13968                                mkexpr( gfield ) ),
13969                         mkU32( 0x78000000 ) ) ) );
13970 
13971    assign( SNaN_true,
13972            unop( Iop_1Sto32,
13973                  binop( Iop_CmpEQ32,
13974                         binop( Iop_And32,
13975                                mkU32( 0x7E000000 ),
13976                                mkexpr( gfield ) ),
13977                         mkU32( 0x7E000000 ) ) ) );
13978 
13979    assign( QNaN_true,
13980            binop( Iop_And32,
13981                   unop( Iop_1Sto32,
13982                        binop( Iop_CmpEQ32,
13983                               binop( Iop_And32,
13984                                      mkU32( 0x7E000000 ),
13985                                      mkexpr( gfield ) ),
13986                               mkU32( 0x7C000000 ) ) ),
13987                   unop( Iop_Not32,
13988                         mkexpr( SNaN_true ) ) ) );
13989 
13990    assign( zero_true,
13991            binop( Iop_And32,
13992                   unop(Iop_1Sto32,
13993                        binop( Iop_CmpEQ32,
13994                               mkexpr( ccIR_zero ),
13995                               mkU32( 0x40 ) ) ),  // ccIR code for Equal
13996                   unop( Iop_Not32,
13997                         binop( Iop_Or32,
13998                                mkexpr( infinity_true ),
13999                                binop( Iop_Or32,
14000                                       mkexpr( QNaN_true ),
14001                                       mkexpr( SNaN_true ) ) ) ) ) );
14002 
14003    /* Do compare of frA the minimum normal value.  Comparison is size
14004     * depenent and was done above to get the ccIR value.
14005     */
14006    assign( subnormal_true,
14007            binop( Iop_And32,
14008                   binop( Iop_Or32,
14009                          unop( Iop_1Sto32,
14010                                binop( Iop_CmpEQ32,
14011                                       mkexpr( ccIR_subnormal ),
14012                                       mkU32( 0x40 ) ) ), // ccIR code for Equal
14013                          unop( Iop_1Sto32,
14014                                binop( Iop_CmpEQ32,
14015                                       mkexpr( ccIR_subnormal ),
14016                                       mkU32( 0x1 ) ) ) ), // ccIR code for LT
14017            unop( Iop_Not32,
14018                  binop( Iop_Or32,
14019                         binop( Iop_Or32,
14020                                mkexpr( infinity_true ),
14021                                mkexpr( zero_true) ),
14022                         binop( Iop_Or32,
14023                                mkexpr( QNaN_true ),
14024                                mkexpr( SNaN_true ) ) ) ) ) );
14025 
14026    /* Normal number is not subnormal, infinity, NaN or Zero */
14027    assign( normal_true,
14028            unop( Iop_Not32,
14029                  binop( Iop_Or32,
14030                         binop( Iop_Or32,
14031                                mkexpr( infinity_true ),
14032                                mkexpr( zero_true ) ),
14033                         binop( Iop_Or32,
14034                                mkexpr( subnormal_true ),
14035                                binop( Iop_Or32,
14036                                       mkexpr( QNaN_true ),
14037                                       mkexpr( SNaN_true ) ) ) ) ) );
14038 
14039    /* Calculate the DCM bit field based on the tests for the specific
14040     * instruction
14041     */
14042    if (opc2 == 0xC2) {    // dtstdc, dtstdcq
14043       /* DCM[0:5] Bit   Data Class definition
14044        *   0   Zero
14045        *   1   Subnormal
14046        *   2   Normal
14047        *   3   Infinity
14048        *   4   Quiet NaN
14049        *   5   Signaling NaN
14050        */
14051 
14052       assign( dcm0, binop( Iop_Shl32,
14053                            mkexpr( zero_true ),
14054                            mkU8( 5 ) ) );
14055       assign( dcm1, binop( Iop_Shl32,
14056                            binop( Iop_And32,
14057                                   mkexpr( subnormal_true ),
14058                                   mkU32( 1 ) ),
14059                            mkU8( 4 ) ) );
14060       assign( dcm2, binop( Iop_Shl32,
14061                            binop( Iop_And32,
14062                                   mkexpr( normal_true ),
14063                                   mkU32( 1 ) ),
14064                            mkU8( 3 ) ) );
14065       assign( dcm3, binop( Iop_Shl32,
14066                            binop( Iop_And32,
14067                                   mkexpr( infinity_true),
14068                                   mkU32( 1 ) ),
14069                            mkU8( 2 ) ) );
14070       assign( dcm4, binop( Iop_Shl32,
14071                            binop( Iop_And32,
14072                                   mkexpr( QNaN_true ),
14073                                   mkU32( 1 ) ),
14074                            mkU8( 1 ) ) );
14075       assign( dcm5, binop( Iop_And32, mkexpr( SNaN_true), mkU32( 1 ) ) );
14076 
14077    } else if (opc2 == 0xE2) {   // dtstdg, dtstdgq
14078       /* check if the exponent is extreme */
14079       assign( extreme_true, binop( Iop_Or32,
14080                                    unop( Iop_1Sto32,
14081                                          binop( Iop_CmpEQ32,
14082                                                 mkexpr( exponent ),
14083                                                 mkU32( max_exp ) ) ),
14084                                    unop( Iop_1Sto32,
14085                                          binop( Iop_CmpEQ32,
14086                                                 mkexpr( exponent ),
14087                                                 mkU32( min_exp ) ) ) ) );
14088 
14089       /* Check if LMD is zero */
14090       Get_lmd( &lmd, binop( Iop_Shr32,
14091                             mkexpr( gfield ), mkU8( 31 - 5 ) ) );
14092 
14093       assign( lmd_zero_true, unop( Iop_1Sto32,
14094                                    binop( Iop_CmpEQ32,
14095                                           mkexpr( lmd ),
14096                                           mkU32( 0 ) ) ) );
14097 
14098       /* DCM[0:5] Bit   Data Class definition
14099        *  0   Zero with non-extreme exponent
14100        *  1   Zero with extreme exponent
14101        *  2   Subnormal or (Normal with extreme exponent)
14102        *  3   Normal with non-extreme exponent and
14103        *      leftmost zero digit in significand
14104        *  4   Normal with non-extreme exponent and
14105        *      leftmost nonzero digit in significand
14106        *  5   Special symbol (Infinity, QNaN, or SNaN)
14107        */
14108       assign( dcm0, binop( Iop_Shl32,
14109                            binop( Iop_And32,
14110                                   binop( Iop_And32,
14111                                          unop( Iop_Not32,
14112                                                mkexpr( extreme_true ) ),
14113                                          mkexpr( zero_true ) ),
14114                                   mkU32( 0x1 ) ),
14115                            mkU8( 5 ) ) );
14116 
14117       assign( dcm1, binop( Iop_Shl32,
14118                            binop( Iop_And32,
14119                                   binop( Iop_And32,
14120                                          mkexpr( extreme_true ),
14121                                          mkexpr( zero_true ) ),
14122                                   mkU32( 0x1 ) ),
14123                            mkU8( 4 ) ) );
14124 
14125       assign( dcm2, binop( Iop_Shl32,
14126                            binop( Iop_And32,
14127                                   binop( Iop_Or32,
14128                                          binop( Iop_And32,
14129                                                 mkexpr( extreme_true ),
14130                                                 mkexpr( normal_true ) ),
14131                                          mkexpr( subnormal_true ) ),
14132                                   mkU32( 0x1 ) ),
14133                            mkU8( 3 ) ) );
14134 
14135       assign( dcm3, binop( Iop_Shl32,
14136                            binop( Iop_And32,
14137                                   binop( Iop_And32,
14138                                          binop( Iop_And32,
14139                                                 unop( Iop_Not32,
14140                                                       mkexpr( extreme_true ) ),
14141                                                       mkexpr( normal_true ) ),
14142                                          unop( Iop_1Sto32,
14143                                                binop( Iop_CmpEQ32,
14144                                                       mkexpr( lmd ),
14145                                                       mkU32( 0 ) ) ) ),
14146                                   mkU32( 0x1 ) ),
14147                            mkU8( 2 ) ) );
14148 
14149       assign( dcm4, binop( Iop_Shl32,
14150                            binop( Iop_And32,
14151                                   binop( Iop_And32,
14152                                          binop( Iop_And32,
14153                                                 unop( Iop_Not32,
14154                                                       mkexpr( extreme_true ) ),
14155                                                 mkexpr( normal_true ) ),
14156                                           unop( Iop_1Sto32,
14157                                                 binop( Iop_CmpNE32,
14158                                                        mkexpr( lmd ),
14159                                                        mkU32( 0 ) ) ) ),
14160                                   mkU32( 0x1 ) ),
14161                            mkU8( 1 ) ) );
14162 
14163       assign( dcm5, binop( Iop_And32,
14164                            binop( Iop_Or32,
14165                                   mkexpr( SNaN_true),
14166                                   binop( Iop_Or32,
14167                                          mkexpr( QNaN_true),
14168                                          mkexpr( infinity_true) ) ),
14169                            mkU32( 0x1 ) ) );
14170    }
14171 
14172    /* create DCM field */
14173    assign( DCM_calc,
14174            binop( Iop_Or32,
14175                   mkexpr( dcm0 ),
14176                   binop( Iop_Or32,
14177                          mkexpr( dcm1 ),
14178                          binop( Iop_Or32,
14179                                 mkexpr( dcm2 ),
14180                                 binop( Iop_Or32,
14181                                        mkexpr( dcm3 ),
14182                                        binop( Iop_Or32,
14183                                               mkexpr( dcm4 ),
14184                                               mkexpr( dcm5 ) ) ) ) ) ) );
14185 
14186    /* Get the sign of the DFP number, ignore sign for QNaN */
14187    assign( sign,
14188            unop( Iop_1Uto32,
14189                  binop( Iop_CmpEQ32,
14190                         binop( Iop_Shr32,
14191                                unop( Iop_64HIto32, mkexpr( frAI64_hi ) ),
14192                                mkU8( 63 - 32 ) ),
14193                         mkU32( 1 ) ) ) );
14194 
14195    /* This instruction generates a four bit field to be stored in the
14196     * condition code register.  The condition code register consists of 7
14197     * fields.  The field to be written to is specified by the BF (AKA crfD)
14198     * field.
14199     *
14200     * The field layout is as follows:
14201     *
14202     *      Field          Meaning
14203     *      0000           Operand positive with no match
14204     *      0100           Operand positive with at least one match
14205     *      0001           Operand negative with no match
14206     *      0101           Operand negative with at least one match
14207     */
14208    assign( field, binop( Iop_Or32,
14209                          binop( Iop_Shl32,
14210                                 mkexpr( sign ),
14211                                 mkU8( 3 ) ),
14212                                 binop( Iop_Shl32,
14213                                        unop( Iop_1Uto32,
14214                                              binop( Iop_CmpNE32,
14215                                                     binop( Iop_And32,
14216                                                            mkU32( DCM ),
14217                                                            mkexpr( DCM_calc ) ),
14218                                                      mkU32( 0 ) ) ),
14219                                        mkU8( 1 ) ) ) );
14220 
14221    putGST_field( PPC_GST_CR, mkexpr( field ), crfD );
14222    putFPCC( mkexpr( field ) );
14223    return True;
14224 }
14225 
dis_dfp_bcd(UInt theInstr)14226 static Bool dis_dfp_bcd(UInt theInstr) {
14227    UInt opc2        = ifieldOPClo10( theInstr );
14228    ULong sp         = IFIELD(theInstr, 19, 2);
14229    ULong s          = IFIELD(theInstr, 20, 1);
14230    UChar frT_addr   = ifieldRegDS( theInstr );
14231    UChar frB_addr   = ifieldRegB( theInstr );
14232    IRTemp frB       = newTemp( Ity_D64 );
14233    IRTemp frBI64    = newTemp( Ity_I64 );
14234    IRTemp result    = newTemp( Ity_I64 );
14235    IRTemp resultD64 = newTemp( Ity_D64 );
14236    IRTemp bcd64     = newTemp( Ity_I64 );
14237    IRTemp bcd_u     = newTemp( Ity_I32 );
14238    IRTemp bcd_l     = newTemp( Ity_I32 );
14239    IRTemp dbcd_u    = newTemp( Ity_I32 );
14240    IRTemp dbcd_l    = newTemp( Ity_I32 );
14241    IRTemp lmd       = newTemp( Ity_I32 );
14242 
14243    assign( frB, getDReg( frB_addr ) );
14244    assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) );
14245 
14246    switch ( opc2 ) {
14247    case 0x142: // ddedpd   DFP Decode DPD to BCD
14248       DIP( "ddedpd %llu,r%u,r%u\n", sp, frT_addr, frB_addr );
14249 
14250          assign( bcd64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) );
14251          assign( bcd_u, unop( Iop_64HIto32, mkexpr( bcd64 ) ) );
14252          assign( bcd_l, unop( Iop_64to32, mkexpr( bcd64 ) ) );
14253 
14254       if ( ( sp == 0 ) || ( sp == 1 ) ) {
14255          /* Unsigned BCD string */
14256          Get_lmd( &lmd,
14257                   binop( Iop_Shr32,
14258                          unop( Iop_64HIto32, mkexpr( frBI64 ) ),
14259                          mkU8( 31 - 5 ) ) ); // G-field[0:4]
14260 
14261          assign( result,
14262                  binop( Iop_32HLto64,
14263                         binop( Iop_Or32,
14264                                binop( Iop_Shl32, mkexpr( lmd ), mkU8( 28 ) ),
14265                                mkexpr( bcd_u ) ),
14266                         mkexpr( bcd_l ) ) );
14267 
14268       } else {
14269          /* Signed BCD string, the cases for sp 2 and 3 only differ in how
14270           * the positive and negative values are encoded in the least
14271           * significant bits.
14272           */
14273          IRTemp sign = newTemp( Ity_I32 );
14274 
14275          if (sp == 2) {
14276             /* Positive sign = 0xC, negative sign = 0xD */
14277 
14278             assign( sign,
14279                     binop( Iop_Or32,
14280                            binop( Iop_Shr32,
14281                                   unop( Iop_64HIto32, mkexpr( frBI64 ) ),
14282                                   mkU8( 31 ) ),
14283                            mkU32( 0xC ) ) );
14284 
14285          } else if ( sp == 3 ) {
14286             /* Positive sign = 0xF, negative sign = 0xD */
14287             IRTemp tmp32 = newTemp( Ity_I32 );
14288 
14289             /* Complement sign bit then OR into bit position 1 */
14290             assign( tmp32,
14291                     binop( Iop_Xor32,
14292                            binop( Iop_Shr32,
14293                                   unop( Iop_64HIto32, mkexpr( frBI64 ) ),
14294                                   mkU8( 30 ) ),
14295                            mkU32( 0x2 ) ) );
14296 
14297             assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) );
14298 
14299          } else {
14300             vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
14301          }
14302 
14303          /* Put sign in bottom 4 bits, move most significant 4-bits from
14304           * bcd_l to bcd_u.
14305           */
14306          assign( result,
14307                  binop( Iop_32HLto64,
14308                         binop( Iop_Or32,
14309                                binop( Iop_Shr32,
14310                                       mkexpr( bcd_l ),
14311                                       mkU8( 28 ) ),
14312                                binop( Iop_Shl32,
14313                                       mkexpr( bcd_u ),
14314                                       mkU8( 4 ) ) ),
14315                         binop( Iop_Or32,
14316                                       mkexpr( sign ),
14317                                binop( Iop_Shl32,
14318                                       mkexpr( bcd_l ),
14319                                       mkU8( 4 ) ) ) ) );
14320       }
14321 
14322       putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result ) ) );
14323       break;
14324 
14325    case 0x342: // denbcd   DFP Encode BCD to DPD
14326    {
14327       IRTemp valid_mask   = newTemp( Ity_I32 );
14328       IRTemp invalid_mask = newTemp( Ity_I32 );
14329       IRTemp without_lmd  = newTemp( Ity_I64 );
14330       IRTemp tmp64        = newTemp( Ity_I64 );
14331       IRTemp dbcd64       = newTemp( Ity_I64 );
14332       IRTemp left_exp     = newTemp( Ity_I32 );
14333       IRTemp g0_4         = newTemp( Ity_I32 );
14334 
14335       DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr );
14336 
14337       if ( s == 0 ) {
14338          /* Unsigned BCD string */
14339          assign( dbcd64, unop( Iop_BCDtoDPB, mkexpr(frBI64 ) ) );
14340          assign( dbcd_u, unop( Iop_64HIto32, mkexpr( dbcd64 ) ) );
14341          assign( dbcd_l, unop( Iop_64to32, mkexpr( dbcd64 ) ) );
14342 
14343          assign( lmd,
14344                  binop( Iop_Shr32,
14345                         binop( Iop_And32,
14346                                unop( Iop_64HIto32, mkexpr( frBI64 ) ),
14347                                mkU32( 0xF0000000 ) ),
14348                         mkU8( 28 ) ) );
14349 
14350          assign( invalid_mask,
14351                  bcd_digit_inval( unop( Iop_64HIto32, mkexpr( frBI64 ) ),
14352                                   unop( Iop_64to32, mkexpr( frBI64 ) ) ) );
14353          assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
14354 
14355          assign( without_lmd,
14356                  unop( Iop_ReinterpD64asI64,
14357                        binop( Iop_InsertExpD64,
14358                               mkU64( DFP_LONG_BIAS ),
14359                               unop( Iop_ReinterpI64asD64,
14360                                     binop( Iop_32HLto64,
14361                                            mkexpr( dbcd_u ),
14362                                            mkexpr( dbcd_l ) ) ) ) ) );
14363          assign( left_exp,
14364                  binop( Iop_Shr32,
14365                         binop( Iop_And32,
14366                                unop( Iop_64HIto32, mkexpr( without_lmd ) ),
14367                                mkU32( 0x60000000 ) ),
14368                         mkU8( 29 ) ) );
14369 
14370          assign( g0_4,
14371                  binop( Iop_Shl32,
14372                         Gfield_encoding( mkexpr( left_exp ), mkexpr( lmd ) ),
14373                         mkU8( 26 ) ) );
14374 
14375          assign( tmp64,
14376                  binop( Iop_32HLto64,
14377                         binop( Iop_Or32,
14378                                binop( Iop_And32,
14379                                       unop( Iop_64HIto32,
14380                                             mkexpr( without_lmd ) ),
14381                                       mkU32( 0x83FFFFFF ) ),
14382                                mkexpr( g0_4 ) ),
14383                         unop( Iop_64to32, mkexpr( without_lmd ) ) ) );
14384 
14385       } else if ( s == 1 ) {
14386          IRTemp sign = newTemp( Ity_I32 );
14387          IRTemp sign_bit = newTemp( Ity_I32 );
14388          IRTemp pos_sign_mask = newTemp( Ity_I32 );
14389          IRTemp neg_sign_mask = newTemp( Ity_I32 );
14390          IRTemp tmp = newTemp( Ity_I64 );
14391 
14392          /* Signed BCD string, least significant 4 bits are sign bits
14393           * positive sign = 0xC, negative sign = 0xD
14394           */
14395          assign( tmp, unop( Iop_BCDtoDPB,
14396                             binop( Iop_32HLto64,
14397                                    binop( Iop_Shr32,
14398                                           unop( Iop_64HIto32,
14399                                                 mkexpr( frBI64 ) ),
14400                                                 mkU8( 4 ) ),
14401                                    binop( Iop_Or32,
14402                                           binop( Iop_Shr32,
14403                                                  unop( Iop_64to32,
14404                                                        mkexpr( frBI64 ) ),
14405                                                   mkU8( 4 ) ),
14406                                           binop( Iop_Shl32,
14407                                                  unop( Iop_64HIto32,
14408                                                        mkexpr( frBI64 ) ),
14409                                                        mkU8( 28 ) ) ) ) ) );
14410 
14411          assign( dbcd_u, unop( Iop_64HIto32, mkexpr( tmp ) ) );
14412          assign( dbcd_l, unop( Iop_64to32, mkexpr( tmp ) ) );
14413 
14414          /* Get the sign of the BCD string. */
14415          assign( sign,
14416                  binop( Iop_And32,
14417                         unop( Iop_64to32, mkexpr( frBI64 ) ),
14418                         mkU32( 0xF ) ) );
14419 
14420          assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) );
14421          assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) );
14422          assign( sign_bit,
14423                  Generate_sign_bit( mkexpr( pos_sign_mask ),
14424                                     mkexpr( neg_sign_mask ) ) );
14425 
14426          /* Check for invalid sign and BCD digit.  Don't check the bottom
14427           * four bits of bcd_l as that is the sign value.
14428           */
14429          assign( invalid_mask,
14430                  Generate_inv_mask(
14431                                    bcd_digit_inval( unop( Iop_64HIto32,
14432                                                           mkexpr( frBI64 ) ),
14433                                                     binop( Iop_Shr32,
14434                                                            unop( Iop_64to32,
14435                                                                  mkexpr( frBI64 ) ),
14436                                                            mkU8( 4 ) ) ),
14437                                    mkexpr( pos_sign_mask ),
14438                                    mkexpr( neg_sign_mask ) ) );
14439 
14440          assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
14441 
14442          /* Generate the result assuming the sign value was valid. */
14443          assign( tmp64,
14444                  unop( Iop_ReinterpD64asI64,
14445                        binop( Iop_InsertExpD64,
14446                               mkU64( DFP_LONG_BIAS ),
14447                               unop( Iop_ReinterpI64asD64,
14448                                     binop( Iop_32HLto64,
14449                                            binop( Iop_Or32,
14450                                                   mkexpr( dbcd_u ),
14451                                                   mkexpr( sign_bit ) ),
14452                                            mkexpr( dbcd_l ) ) ) ) ) );
14453       }
14454 
14455       /* Generate the value to store depending on the validity of the
14456        * sign value and the validity of the BCD digits.
14457        */
14458       assign( resultD64,
14459               unop( Iop_ReinterpI64asD64,
14460                     binop( Iop_32HLto64,
14461                            binop( Iop_Or32,
14462                                   binop( Iop_And32,
14463                                          mkexpr( valid_mask ),
14464                                          unop( Iop_64HIto32,
14465                                                mkexpr( tmp64 ) ) ),
14466                                   binop( Iop_And32,
14467                                          mkU32( 0x7C000000 ),
14468                                          mkexpr( invalid_mask ) ) ),
14469                            binop( Iop_Or32,
14470                                   binop( Iop_And32,
14471                                          mkexpr( valid_mask ),
14472                                          unop( Iop_64to32, mkexpr( tmp64 ) ) ),
14473                                   binop( Iop_And32,
14474                                          mkU32( 0x0 ),
14475                                          mkexpr( invalid_mask ) ) ) ) ) );
14476       putDReg( frT_addr, mkexpr( resultD64 ) );
14477    }
14478    break;
14479    default:
14480       vpanic( "ERROR: dis_dfp_bcd(ppc), undefined opc2 case " );
14481       return False;
14482    }
14483    return True;
14484 }
14485 
dis_dfp_bcdq(UInt theInstr)14486 static Bool dis_dfp_bcdq( UInt theInstr )
14487 {
14488    UInt opc2        = ifieldOPClo10( theInstr );
14489    ULong sp         = IFIELD(theInstr, 19, 2);
14490    ULong s          = IFIELD(theInstr, 20, 1);
14491    IRTemp frB_hi    = newTemp( Ity_D64 );
14492    IRTemp frB_lo    = newTemp( Ity_D64 );
14493    IRTemp frBI64_hi = newTemp( Ity_I64 );
14494    IRTemp frBI64_lo = newTemp( Ity_I64 );
14495    UChar frT_addr   = ifieldRegDS( theInstr );
14496    UChar frB_addr   = ifieldRegB( theInstr );
14497 
14498    IRTemp lmd       = newTemp( Ity_I32 );
14499    IRTemp result_hi = newTemp( Ity_I64 );
14500    IRTemp result_lo = newTemp( Ity_I64 );
14501 
14502    assign( frB_hi, getDReg( frB_addr ) );
14503    assign( frB_lo, getDReg( frB_addr + 1 ) );
14504    assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) );
14505    assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) );
14506 
14507    switch ( opc2 ) {
14508    case 0x142: // ddedpdq   DFP Decode DPD to BCD
14509    {
14510       IRTemp low_60_u = newTemp( Ity_I32 );
14511       IRTemp low_60_l = newTemp( Ity_I32 );
14512       IRTemp mid_60_u = newTemp( Ity_I32 );
14513       IRTemp mid_60_l = newTemp( Ity_I32 );
14514       IRTemp top_12_l = newTemp( Ity_I32 );
14515 
14516       DIP( "ddedpdq %llu,r%u,r%u\n", sp, frT_addr, frB_addr );
14517 
14518       /* Note, instruction only stores the lower 32 BCD digits in
14519        * the result
14520        */
14521       Generate_132_bit_bcd_string( mkexpr( frBI64_hi ),
14522                                    mkexpr( frBI64_lo ),
14523                                    &top_12_l,
14524                                    &mid_60_u,
14525                                    &mid_60_l,
14526                                    &low_60_u,
14527                                    &low_60_l );
14528 
14529       if ( ( sp == 0 ) || ( sp == 1 ) ) {
14530          /* Unsigned BCD string */
14531          assign( result_hi,
14532                  binop( Iop_32HLto64,
14533                         binop( Iop_Or32,
14534                                binop( Iop_Shl32,
14535                                       mkexpr( top_12_l ),
14536                                       mkU8( 24 ) ),
14537                                binop( Iop_Shr32,
14538                                       mkexpr( mid_60_u ),
14539                                       mkU8( 4 ) ) ),
14540                         binop( Iop_Or32,
14541                                binop( Iop_Shl32,
14542                                       mkexpr( mid_60_u ),
14543                                       mkU8( 28 ) ),
14544                                binop( Iop_Shr32,
14545                                       mkexpr( mid_60_l ),
14546                                       mkU8( 4 ) ) ) ) );
14547 
14548          assign( result_lo,
14549                  binop( Iop_32HLto64,
14550                         binop( Iop_Or32,
14551                                binop( Iop_Shl32,
14552                                       mkexpr( mid_60_l ),
14553                                       mkU8( 28 ) ),
14554                                mkexpr( low_60_u ) ),
14555                         mkexpr( low_60_l ) ) );
14556 
14557       } else {
14558          /* Signed BCD string, the cases for sp 2 and 3 only differ in how
14559           * the positive and negative values are encoded in the least
14560           * significant bits.
14561           */
14562          IRTemp sign = newTemp( Ity_I32 );
14563 
14564          if ( sp == 2 ) {
14565             /* Positive sign = 0xC, negative sign = 0xD */
14566             assign( sign,
14567                     binop( Iop_Or32,
14568                            binop( Iop_Shr32,
14569                                   unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
14570                                   mkU8( 31 ) ),
14571                            mkU32( 0xC ) ) );
14572 
14573          } else if ( sp == 3 ) {
14574             IRTemp tmp32 = newTemp( Ity_I32 );
14575 
14576             /* Positive sign = 0xF, negative sign = 0xD.
14577              * Need to complement sign bit then OR into bit position 1.
14578              */
14579             assign( tmp32,
14580                     binop( Iop_Xor32,
14581                            binop( Iop_Shr32,
14582                                   unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
14583                                   mkU8( 30 ) ),
14584                            mkU32( 0x2 ) ) );
14585 
14586             assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) );
14587 
14588          } else {
14589             vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
14590          }
14591 
14592          assign( result_hi,
14593                  binop( Iop_32HLto64,
14594                         binop( Iop_Or32,
14595                                binop( Iop_Shl32,
14596                                       mkexpr( top_12_l ),
14597                                       mkU8( 28 ) ),
14598                                mkexpr( mid_60_u ) ),
14599                         mkexpr( mid_60_l ) ) );
14600 
14601          assign( result_lo,
14602                  binop( Iop_32HLto64,
14603                         binop( Iop_Or32,
14604                                binop( Iop_Shl32,
14605                                       mkexpr( low_60_u ),
14606                                       mkU8( 4 ) ),
14607                                binop( Iop_Shr32,
14608                                       mkexpr( low_60_l ),
14609                                       mkU8( 28 ) ) ),
14610                         binop( Iop_Or32,
14611                                binop( Iop_Shl32,
14612                                       mkexpr( low_60_l ),
14613                                       mkU8( 4 ) ),
14614                                mkexpr( sign ) ) ) );
14615       }
14616 
14617       putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) );
14618       putDReg( frT_addr + 1,
14619                unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) );
14620    }
14621    break;
14622    case 0x342: // denbcdq   DFP Encode BCD to DPD
14623    {
14624       IRTemp valid_mask      = newTemp( Ity_I32 );
14625       IRTemp invalid_mask    = newTemp( Ity_I32 );
14626       IRTemp result128       = newTemp( Ity_D128 );
14627       IRTemp dfp_significand = newTemp( Ity_D128 );
14628       IRTemp tmp_hi          = newTemp( Ity_I64 );
14629       IRTemp tmp_lo          = newTemp( Ity_I64 );
14630       IRTemp dbcd_top_l      = newTemp( Ity_I32 );
14631       IRTemp dbcd_mid_u      = newTemp( Ity_I32 );
14632       IRTemp dbcd_mid_l      = newTemp( Ity_I32 );
14633       IRTemp dbcd_low_u      = newTemp( Ity_I32 );
14634       IRTemp dbcd_low_l      = newTemp( Ity_I32 );
14635       IRTemp bcd_top_8       = newTemp( Ity_I64 );
14636       IRTemp bcd_mid_60      = newTemp( Ity_I64 );
14637       IRTemp bcd_low_60      = newTemp( Ity_I64 );
14638       IRTemp sign_bit        = newTemp( Ity_I32 );
14639       IRTemp tmptop10        = newTemp( Ity_I64 );
14640       IRTemp tmpmid50        = newTemp( Ity_I64 );
14641       IRTemp tmplow50        = newTemp( Ity_I64 );
14642       IRTemp inval_bcd_digit_mask = newTemp( Ity_I32 );
14643 
14644       DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr );
14645 
14646       if ( s == 0 ) {
14647          /* Unsigned BCD string */
14648          assign( sign_bit, mkU32( 0 ) ); // set to zero for unsigned string
14649 
14650          assign( bcd_top_8,
14651                  binop( Iop_32HLto64,
14652                         mkU32( 0 ),
14653                         binop( Iop_And32,
14654                                binop( Iop_Shr32,
14655                                       unop( Iop_64HIto32,
14656                                             mkexpr( frBI64_hi ) ),
14657                                       mkU8( 24 ) ),
14658                                mkU32( 0xFF ) ) ) );
14659          assign( bcd_mid_60,
14660                  binop( Iop_32HLto64,
14661                         binop( Iop_Or32,
14662                                binop( Iop_Shr32,
14663                                       unop( Iop_64to32,
14664                                             mkexpr( frBI64_hi ) ),
14665                                       mkU8( 28 ) ),
14666                                binop( Iop_Shl32,
14667                                       unop( Iop_64HIto32,
14668                                             mkexpr( frBI64_hi ) ),
14669                                       mkU8( 4 ) ) ),
14670                         binop( Iop_Or32,
14671                                binop( Iop_Shl32,
14672                                       unop( Iop_64to32,
14673                                             mkexpr( frBI64_hi ) ),
14674                                       mkU8( 4 ) ),
14675                                binop( Iop_Shr32,
14676                                       unop( Iop_64HIto32,
14677                                             mkexpr( frBI64_lo ) ),
14678                                       mkU8( 28 ) ) ) ) );
14679 
14680          /* Note, the various helper functions ignores top 4-bits */
14681          assign( bcd_low_60, mkexpr( frBI64_lo ) );
14682 
14683          assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr( bcd_top_8 ) ) );
14684          assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) );
14685 
14686          assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr( bcd_mid_60 ) ) );
14687          assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) );
14688          assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) );
14689 
14690          assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) );
14691          assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) );
14692          assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) );
14693 
14694          /* The entire BCD string fits in lower 110-bits.  The LMD = 0,
14695           * value is not part of the final result. Only the right most
14696           * BCD digits are stored.
14697           */
14698          assign( lmd, mkU32( 0 ) );
14699 
14700          assign( invalid_mask,
14701                  binop( Iop_Or32,
14702                         bcd_digit_inval( mkU32( 0 ),
14703                                          unop( Iop_64to32,
14704                                                mkexpr( bcd_top_8 ) ) ),
14705                         binop( Iop_Or32,
14706                                bcd_digit_inval( unop( Iop_64HIto32,
14707                                                       mkexpr( bcd_mid_60 ) ),
14708                                                 unop( Iop_64to32,
14709                                                       mkexpr( bcd_mid_60 ) ) ),
14710                                bcd_digit_inval( unop( Iop_64HIto32,
14711                                                       mkexpr( bcd_low_60 ) ),
14712                                                 unop( Iop_64to32,
14713                                                       mkexpr( bcd_low_60 ) )
14714                                                 ) ) ) );
14715 
14716       } else if ( s == 1 ) {
14717          IRTemp sign          = newTemp( Ity_I32 );
14718          IRTemp zero          = newTemp( Ity_I32 );
14719          IRTemp pos_sign_mask = newTemp( Ity_I32 );
14720          IRTemp neg_sign_mask = newTemp( Ity_I32 );
14721 
14722          /* The sign of the BCD string is stored in lower 4 bits */
14723          assign( sign,
14724                  binop( Iop_And32,
14725                         unop( Iop_64to32, mkexpr( frBI64_lo ) ),
14726                         mkU32( 0xF ) ) );
14727          assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) );
14728          assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) );
14729          assign( sign_bit,
14730                  Generate_sign_bit( mkexpr( pos_sign_mask ),
14731                                     mkexpr( neg_sign_mask ) ) );
14732 
14733          /* Generate the value assuminig the sign and BCD digits are vaild */
14734          assign( bcd_top_8,
14735                  binop( Iop_32HLto64,
14736                         mkU32( 0x0 ),
14737                         binop( Iop_Shr32,
14738                                unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
14739                                mkU8( 28 ) ) ) );
14740 
14741          /* The various helper routines ignore the upper 4-bits */
14742          assign( bcd_mid_60, mkexpr( frBI64_hi ) );
14743 
14744          /* Remove bottom four sign bits */
14745          assign( bcd_low_60,
14746                  binop( Iop_32HLto64,
14747                         binop( Iop_Shr32,
14748                                unop( Iop_64HIto32,
14749                                      mkexpr( frBI64_lo ) ),
14750                                mkU8( 4 ) ),
14751                                binop( Iop_Or32,
14752                                       binop( Iop_Shl32,
14753                                              unop( Iop_64HIto32,
14754                                                    mkexpr( frBI64_lo ) ),
14755                                              mkU8( 28 ) ),
14756                                       binop( Iop_Shr32,
14757                                              unop( Iop_64to32,
14758                                                    mkexpr( frBI64_lo ) ),
14759                                              mkU8( 4 ) ) ) ) );
14760          assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr(bcd_top_8 ) ) );
14761          assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) );
14762 
14763          assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr(bcd_mid_60 ) ) );
14764          assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) );
14765          assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) );
14766 
14767          assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) );
14768          assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) );
14769          assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) );
14770 
14771          /* The entire BCD string fits in lower 110-bits.  The LMD value
14772           * is not stored in the final result for the DFP Long instruction.
14773           */
14774          assign( lmd, mkU32( 0 ) );
14775 
14776          /* Check for invalid sign and invalid BCD digit.  Don't check the
14777           *  bottom four bits of frBI64_lo as that is the sign value.
14778           */
14779          assign( zero, mkU32( 0 ) );
14780          assign( inval_bcd_digit_mask,
14781                  binop( Iop_Or32,
14782                         bcd_digit_inval( mkexpr( zero ),
14783                                          unop( Iop_64to32,
14784                                                mkexpr( bcd_top_8 ) ) ),
14785                         binop( Iop_Or32,
14786                                bcd_digit_inval( unop( Iop_64HIto32,
14787                                                      mkexpr( bcd_mid_60 ) ),
14788                                                unop( Iop_64to32,
14789                                                      mkexpr( bcd_mid_60 ) ) ),
14790                                bcd_digit_inval( unop( Iop_64HIto32,
14791                                                      mkexpr( frBI64_lo ) ),
14792                                                binop( Iop_Shr32,
14793                                                       unop( Iop_64to32,
14794                                                             mkexpr( frBI64_lo ) ),
14795                                                         mkU8( 4 ) ) ) ) ) );
14796          assign( invalid_mask,
14797                  Generate_inv_mask( mkexpr( inval_bcd_digit_mask ),
14798                                     mkexpr( pos_sign_mask ),
14799                                     mkexpr( neg_sign_mask ) ) );
14800 
14801       }
14802 
14803       assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
14804 
14805       /* Calculate the value of the result assuming sign and BCD digits
14806        * are all valid.
14807        */
14808       assign( dfp_significand,
14809               binop( Iop_D64HLtoD128,
14810                      unop( Iop_ReinterpI64asD64,
14811                            binop( Iop_32HLto64,
14812                                   binop( Iop_Or32,
14813                                          mkexpr( sign_bit ),
14814                                          mkexpr( dbcd_top_l ) ),
14815                                   binop( Iop_Or32,
14816                                          binop( Iop_Shl32,
14817                                                 mkexpr( dbcd_mid_u ),
14818                                                 mkU8( 18 ) ),
14819                                          binop( Iop_Shr32,
14820                                                 mkexpr( dbcd_mid_l ),
14821                                                 mkU8( 14 ) ) ) ) ),
14822                      unop( Iop_ReinterpI64asD64,
14823                            binop( Iop_32HLto64,
14824                                   binop( Iop_Or32,
14825                                          mkexpr( dbcd_low_u ),
14826                                          binop( Iop_Shl32,
14827                                                 mkexpr( dbcd_mid_l ),
14828                                                 mkU8( 18 ) ) ),
14829                                   mkexpr( dbcd_low_l ) ) ) ) );
14830 
14831       /* Break the result back down to 32-bit chunks and replace chunks.
14832        * If there was an invalid BCD digit or invalid sign value, replace
14833        * the calculated result with the invalid bit string.
14834        */
14835       assign( result128,
14836               binop( Iop_InsertExpD128,
14837                      mkU64( DFP_EXTND_BIAS ),
14838                      mkexpr( dfp_significand ) ) );
14839 
14840       assign( tmp_hi,
14841               unop( Iop_ReinterpD64asI64,
14842                     unop( Iop_D128HItoD64, mkexpr( result128 ) ) ) );
14843 
14844       assign( tmp_lo,
14845               unop( Iop_ReinterpD64asI64,
14846                     unop( Iop_D128LOtoD64, mkexpr( result128 ) ) ) );
14847 
14848       assign( result_hi,
14849               binop( Iop_32HLto64,
14850                      binop( Iop_Or32,
14851                             binop( Iop_And32,
14852                                    mkexpr( valid_mask ),
14853                                    unop( Iop_64HIto32, mkexpr( tmp_hi ) ) ),
14854                             binop( Iop_And32,
14855                                    mkU32( 0x7C000000 ),
14856                                    mkexpr( invalid_mask ) ) ),
14857                      binop( Iop_Or32,
14858                             binop( Iop_And32,
14859                                    mkexpr( valid_mask ),
14860                                    unop( Iop_64to32, mkexpr( tmp_hi ) ) ),
14861                             binop( Iop_And32,
14862                                    mkU32( 0x0 ),
14863                                    mkexpr( invalid_mask ) ) ) ) );
14864 
14865       assign( result_lo,
14866               binop( Iop_32HLto64,
14867                      binop( Iop_Or32,
14868                             binop( Iop_And32,
14869                                    mkexpr( valid_mask ),
14870                                    unop( Iop_64HIto32, mkexpr( tmp_lo ) ) ),
14871                             binop( Iop_And32,
14872                                    mkU32( 0x0 ),
14873                                    mkexpr( invalid_mask ) ) ),
14874                      binop( Iop_Or32,
14875                             binop( Iop_And32,
14876                                    mkexpr( valid_mask ),
14877                                    unop( Iop_64to32, mkexpr( tmp_lo ) ) ),
14878                             binop( Iop_And32,
14879                                    mkU32( 0x0 ),
14880                                    mkexpr( invalid_mask ) ) ) ) );
14881 
14882       putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) );
14883       putDReg( frT_addr + 1,
14884                unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) );
14885 
14886    }
14887    break;
14888    default:
14889       vpanic( "ERROR: dis_dfp_bcdq(ppc), undefined opc2 case " );
14890       break;
14891    }
14892    return True;
14893 }
14894 
dis_dfp_significant_digits(UInt theInstr)14895 static Bool dis_dfp_significant_digits( UInt theInstr )
14896 {
14897    UInt opc1      = ifieldOPC( theInstr );
14898    UInt opc2      = ifieldOPClo10(theInstr);
14899    UChar frA_addr = ifieldRegA( theInstr );
14900    UChar frB_addr = ifieldRegB( theInstr );
14901    IRTemp frA     = newTemp( Ity_D64 );
14902    IRTemp B_sig   = newTemp( Ity_I8 );
14903    IRTemp K       = newTemp( Ity_I8 );
14904    IRTemp lmd_B   = newTemp( Ity_I32 );
14905    IRTemp field   = newTemp( Ity_I32 );
14906    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF
14907    IRTemp Unordered_true     = newTemp( Ity_I32 );
14908    IRTemp Eq_true_mask       = newTemp( Ity_I32 );
14909    IRTemp Lt_true_mask       = newTemp( Ity_I32 );
14910    IRTemp Gt_true_mask       = newTemp( Ity_I32 );
14911    IRTemp KisZero_true_mask  = newTemp( Ity_I32 );
14912    IRTemp KisZero_false_mask = newTemp( Ity_I32 );
14913    IRTemp cc = newTemp( Ity_I32 );
14914    UChar  UIM     = toUChar( IFIELD( theInstr, 16, 6 ) );
14915    IRTemp BCD_valid  = newTemp( Ity_I32 );
14916 
14917    if (opc2 == 0x2A2) {        // dtstsf   DFP Test Significance
14918                                // dtstsfq  DFP Test Significance Quad
14919       /* Get the reference singificance stored in frA */
14920       assign( frA, getDReg( frA_addr ) );
14921 
14922       /* Convert from 64 bit to 8 bits in two steps.  The Iop_64to8 is not
14923        * supported in 32-bit mode.
14924        */
14925       assign( K, unop( Iop_32to8,
14926                        binop( Iop_And32,
14927                               unop( Iop_64to32,
14928                                     unop( Iop_ReinterpD64asI64,
14929                                           mkexpr( frA ) ) ),
14930                               mkU32( 0x3F ) ) ) );
14931 
14932    } else if (opc2 == 0x2A3) { // dtstsfi  DFP Test Significance Immediate
14933                                // dtstsfiq DFP Test Significance Quad Immediate
14934       /* get the significane from the immediate field */
14935       assign( K, mkU8( UIM) );
14936 
14937    } else {
14938       vex_printf("dis_dfp_significant_digits(ppc)(opc2) wrong\n");
14939       return False;
14940    }
14941 
14942    switch ( opc1 ) {
14943    case 0x3b: // dtstsf   DFP Test Significance
14944               // dtstsfi  DFP Test Significance Immediate
14945    {
14946       IRTemp frB     = newTemp( Ity_D64 );
14947       IRTemp frBI64  = newTemp( Ity_I64 );
14948       IRTemp B_bcd_u = newTemp( Ity_I32 );
14949       IRTemp B_bcd_l = newTemp( Ity_I32 );
14950       IRTemp tmp64   = newTemp( Ity_I64 );
14951 
14952       if (opc2 == 0x2A2) {
14953          DIP( "dtstsf %u,r%u,r%u\n", crfD, frA_addr, frB_addr );
14954       } else {
14955          DIP( "dtstsfi %u,%u,r%u\n", crfD, UIM, frB_addr );
14956       }
14957 
14958       assign( frB, getDReg( frB_addr ) );
14959       assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) );
14960 
14961       /* Get the BCD string for the value stored in a series of I32 values.
14962        * Count the number of leading zeros.  Subtract the number of leading
14963        * zeros from 16 (maximum number of significant digits in DFP
14964        * Long).
14965        */
14966       Get_lmd( &lmd_B,
14967                binop( Iop_Shr32,
14968                       unop( Iop_64HIto32, mkexpr( frBI64 ) ),
14969                       mkU8( 31 - 5 ) ) ); // G-field[0:4]
14970 
14971       assign( tmp64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) );
14972       assign( B_bcd_u, unop( Iop_64HIto32, mkexpr( tmp64 ) ) );
14973       assign( B_bcd_l, unop( Iop_64to32, mkexpr( tmp64 ) ) );
14974 
14975       assign( B_sig,
14976               binop( Iop_Sub8,
14977                      mkU8( DFP_LONG_MAX_SIG_DIGITS ),
14978                      Count_leading_zeros_60( mkexpr( lmd_B ),
14979                                              mkexpr( B_bcd_u ),
14980                                              mkexpr( B_bcd_l ) ) ) );
14981 
14982       assign( BCD_valid,
14983               binop( Iop_Or32,
14984                      bcd_digit_inval( mkexpr( B_bcd_u), mkexpr( B_bcd_l) ),
14985                      bcd_digit_inval( mkexpr( lmd_B), mkU32( 0 ) ) ) );
14986 
14987       /* Set unordered to True if the number is NaN, Inf or an invalid
14988        * digit.
14989        */
14990       assign( Unordered_true,
14991               binop( Iop_Or32,
14992                      Check_unordered( mkexpr( frBI64 ) ),
14993                      mkexpr( BCD_valid) ) );
14994    }
14995    break;
14996    case 0x3F: // dtstsfq     DFP Test Significance
14997               // dtstsfqi    DFP Test Significance Immediate
14998    {
14999       IRTemp frB_hi     = newTemp( Ity_D64 );
15000       IRTemp frB_lo     = newTemp( Ity_D64 );
15001       IRTemp frBI64_hi  = newTemp( Ity_I64 );
15002       IRTemp frBI64_lo  = newTemp( Ity_I64 );
15003       IRTemp B_low_60_u = newTemp( Ity_I32 );
15004       IRTemp B_low_60_l = newTemp( Ity_I32 );
15005       IRTemp B_mid_60_u = newTemp( Ity_I32 );
15006       IRTemp B_mid_60_l = newTemp( Ity_I32 );
15007       IRTemp B_top_12_l = newTemp( Ity_I32 );
15008 
15009       if (opc2 == 0x2A2) {
15010          DIP( "dtstsfq %u,r%u,r%u\n", crfD, frA_addr, frB_addr );
15011       } else {
15012          DIP( "dtstsfiq %u,%u,r%u\n", crfD, UIM, frB_addr );
15013       }
15014 
15015       assign( frB_hi, getDReg( frB_addr ) );
15016       assign( frB_lo, getDReg( frB_addr + 1 ) );
15017 
15018       assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) );
15019       assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) );
15020 
15021       /* Get the BCD string for the value stored in a series of I32 values.
15022        * Count the number of leading zeros.  Subtract the number of leading
15023        * zeros from 32 (maximum number of significant digits in DFP
15024        * extended).
15025        */
15026       Get_lmd( &lmd_B,
15027                binop( Iop_Shr32,
15028                       unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
15029                       mkU8( 31 - 5 ) ) ); // G-field[0:4]
15030 
15031       Generate_132_bit_bcd_string( mkexpr( frBI64_hi ),
15032                                    mkexpr( frBI64_lo ),
15033                                    &B_top_12_l,
15034                                    &B_mid_60_u,
15035                                    &B_mid_60_l,
15036                                    &B_low_60_u,
15037                                    &B_low_60_l );
15038 
15039       assign( BCD_valid,
15040               binop( Iop_Or32,
15041                      binop( Iop_Or32,
15042                             bcd_digit_inval( mkexpr( lmd_B ),
15043                                              mkexpr( B_top_12_l ) ),
15044                             bcd_digit_inval( mkexpr( B_mid_60_u ),
15045                                              mkexpr( B_mid_60_l ) ) ),
15046                      bcd_digit_inval( mkexpr( B_low_60_u ),
15047                                       mkexpr( B_low_60_l ) ) ) );
15048 
15049       assign( B_sig,
15050               binop( Iop_Sub8,
15051                      mkU8( DFP_EXTND_MAX_SIG_DIGITS ),
15052                      Count_leading_zeros_128( mkexpr( lmd_B ),
15053                                               mkexpr( B_top_12_l ),
15054                                               mkexpr( B_mid_60_u ),
15055                                               mkexpr( B_mid_60_l ),
15056                                               mkexpr( B_low_60_u ),
15057                                               mkexpr( B_low_60_l ) ) ) );
15058 
15059       /* Set unordered to True if the number is NaN, Inf or an invalid
15060        * digit.
15061        */
15062       assign( Unordered_true,
15063               binop( Iop_Or32,
15064                      Check_unordered( mkexpr( frBI64_hi ) ),
15065                      mkexpr( BCD_valid) ) );
15066    }
15067    break;
15068    }
15069 
15070    /* Compare (16 - cnt[0]) against K and set the condition code field
15071     * accordingly.
15072     *
15073     * The field layout is as follows:
15074     *
15075     * bit[3:0]    Description
15076     *    3     K != 0 and K < Number of significant digits if FRB
15077     *    2     K != 0 and K > Number of significant digits if FRB OR K = 0
15078     *    1     K != 0 and K = Number of significant digits if FRB
15079     *    0     K ? Number of significant digits if FRB
15080     */
15081    assign( Eq_true_mask,
15082            unop( Iop_1Sto32,
15083                  binop( Iop_CmpEQ32,
15084                         unop( Iop_8Uto32, mkexpr( K ) ),
15085                         unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) );
15086    assign( Lt_true_mask,
15087            unop( Iop_1Sto32,
15088                  binop( Iop_CmpLT32U,
15089                         unop( Iop_8Uto32, mkexpr( K ) ),
15090                         unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) );
15091    assign( Gt_true_mask,
15092            unop( Iop_1Sto32,
15093                  binop( Iop_CmpLT32U,
15094                         unop( Iop_8Uto32, mkexpr( B_sig ) ),
15095                         unop( Iop_8Uto32, mkexpr( K ) ) ) ) );
15096 
15097    assign( KisZero_true_mask,
15098            unop( Iop_1Sto32,
15099                  binop( Iop_CmpEQ32,
15100                         unop( Iop_8Uto32, mkexpr( K ) ),
15101                         mkU32( 0 ) ) ) );
15102    assign( KisZero_false_mask,
15103            unop( Iop_1Sto32,
15104                  binop( Iop_CmpNE32,
15105                         unop( Iop_8Uto32, mkexpr( K ) ),
15106                         mkU32( 0 ) ) ) );
15107 
15108    assign( field,
15109            binop( Iop_Or32,
15110                   binop( Iop_And32,
15111                          mkexpr( KisZero_false_mask ),
15112                          binop( Iop_Or32,
15113                                 binop( Iop_And32,
15114                                        mkexpr( Lt_true_mask ),
15115                                        mkU32( 0x8 ) ),
15116                                 binop( Iop_Or32,
15117                                        binop( Iop_And32,
15118                                               mkexpr( Gt_true_mask ),
15119                                               mkU32( 0x4 ) ),
15120                                        binop( Iop_And32,
15121                                               mkexpr( Eq_true_mask ),
15122                                               mkU32( 0x2 ) ) ) ) ),
15123                   binop( Iop_And32,
15124                          mkexpr( KisZero_true_mask ),
15125                          mkU32( 0x4 ) ) ) );
15126 
15127    assign( cc, binop( Iop_Or32,
15128                       binop( Iop_And32,
15129                              mkexpr( Unordered_true ),
15130                              mkU32( 0x1 ) ),
15131                       binop( Iop_And32,
15132                              unop( Iop_Not32, mkexpr( Unordered_true ) ),
15133                              mkexpr( field ) ) ) );
15134 
15135    putGST_field( PPC_GST_CR, mkexpr( cc ), crfD );
15136    putFPCC( mkexpr( cc ) );
15137 
15138    return True;
15139 }
15140 /*------------------------------------------------------------*/
15141 /*--- AltiVec Instruction Translation                      ---*/
15142 /*------------------------------------------------------------*/
15143 
15144 /*
15145   Altivec Cache Control Instructions (Data Streams)
15146 */
dis_av_datastream(UInt theInstr)15147 static Bool dis_av_datastream ( UInt theInstr )
15148 {
15149    /* X-Form */
15150    UChar opc1     = ifieldOPC(theInstr);
15151    UChar flag_T   = toUChar( IFIELD( theInstr, 25, 1 ) );
15152    UChar flag_A   = flag_T;
15153    UChar b23to24  = toUChar( IFIELD( theInstr, 23, 2 ) );
15154    UChar STRM     = toUChar( IFIELD( theInstr, 21, 2 ) );
15155    UChar rA_addr  = ifieldRegA(theInstr);
15156    UChar rB_addr  = ifieldRegB(theInstr);
15157    UInt  opc2     = ifieldOPClo10(theInstr);
15158    UChar b0       = ifieldBIT0(theInstr);
15159 
15160    if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) {
15161       vex_printf("dis_av_datastream(ppc)(instr)\n");
15162       return False;
15163    }
15164 
15165    switch (opc2) {
15166    case 0x156: // dst (Data Stream Touch, AV p115)
15167       DIP("dst%s r%u,r%u,%d\n", flag_T ? "t" : "",
15168                                 rA_addr, rB_addr, STRM);
15169       break;
15170 
15171    case 0x176: // dstst (Data Stream Touch for Store, AV p117)
15172       DIP("dstst%s r%u,r%u,%d\n", flag_T ? "t" : "",
15173                                   rA_addr, rB_addr, STRM);
15174       break;
15175 
15176    case 0x336: // dss (Data Stream Stop, AV p114)
15177       if (rA_addr != 0 || rB_addr != 0) {
15178          vex_printf("dis_av_datastream(ppc)(opc2,dst)\n");
15179          return False;
15180       }
15181       if (flag_A == 0) {
15182          DIP("dss %d\n", STRM);
15183       } else {
15184          DIP("dssall\n");
15185       }
15186       break;
15187 
15188    default:
15189       vex_printf("dis_av_datastream(ppc)(opc2)\n");
15190       return False;
15191    }
15192    return True;
15193 }
15194 
15195 /*
15196   AltiVec Processor Control Instructions
15197 */
dis_av_procctl(UInt theInstr)15198 static Bool dis_av_procctl ( UInt theInstr )
15199 {
15200    /* VX-Form */
15201    UChar opc1    = ifieldOPC(theInstr);
15202    UChar vD_addr = ifieldRegDS(theInstr);
15203    UChar vA_addr = ifieldRegA(theInstr);
15204    UChar vB_addr = ifieldRegB(theInstr);
15205    UInt  opc2    = IFIELD( theInstr, 0, 11 );
15206 
15207    if (opc1 != 0x4) {
15208       vex_printf("dis_av_procctl(ppc)(instr)\n");
15209       return False;
15210    }
15211 
15212    switch (opc2) {
15213    case 0x604: // mfvscr (Move from VSCR, AV p129)
15214       if (vA_addr != 0 || vB_addr != 0) {
15215          vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
15216          return False;
15217       }
15218       DIP("mfvscr v%d\n", vD_addr);
15219       putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) );
15220       break;
15221 
15222    case 0x644: { // mtvscr (Move to VSCR, AV p130)
15223       IRTemp vB = newTemp(Ity_V128);
15224       if (vD_addr != 0 || vA_addr != 0) {
15225          vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
15226          return False;
15227       }
15228       DIP("mtvscr v%d\n", vB_addr);
15229       assign( vB, getVReg(vB_addr));
15230       putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) );
15231       break;
15232    }
15233    default:
15234       vex_printf("dis_av_procctl(ppc)(opc2)\n");
15235       return False;
15236    }
15237    return True;
15238 }
15239 
15240 /*
15241 Vector Extend Sign Instructions
15242 */
dis_av_extend_sign_count_zero(UInt theInstr,UInt allow_isa_3_0)15243 static Bool dis_av_extend_sign_count_zero ( UInt theInstr, UInt allow_isa_3_0 )
15244 {
15245    /* VX-Form, sort of, the A register field is used to select the specific
15246     * sign extension instruction or count leading/trailing zero LSB
15247     * instruction.
15248     */
15249 
15250    UChar opc1    = ifieldOPC( theInstr );
15251    UChar rT_addr = ifieldRegDS (theInstr );
15252    UChar rA_addr = ifieldRegA( theInstr );
15253    UChar vB_addr = ifieldRegB( theInstr );
15254    UInt  opc2    = IFIELD( theInstr, 0, 11 );
15255 
15256    IRTemp vB    = newTemp( Ity_V128 );
15257    IRTemp vT    = newTemp( Ity_V128 );
15258 
15259    assign( vB, getVReg ( vB_addr ) );
15260 
15261    if ( ( opc1 != 0x4 ) && ( opc2 != 0x602 ) )  {
15262       vex_printf("dis_av_extend_sign(ppc)(instr)\n");
15263       return False;
15264    }
15265 
15266    switch ( rA_addr ) {
15267    case 0:
15268    case 1:
15269    {
15270       UInt i;
15271       IRTemp count[17];
15272       IRTemp bit_zero[16];
15273       IRTemp byte_mask[17];
15274 
15275       /* These instructions store the result in the general purpose
15276        * register in the rT_addr field.
15277        */
15278 
15279       byte_mask[0] = newTemp( Ity_I32 );
15280       count[0] = newTemp( Ity_I32 );
15281       assign( count[0], mkU32( 0 ) );
15282       assign( byte_mask[0], mkU32( 0x1 ) );
15283 
15284       if ( rA_addr == 0 ) {
15285          // vclzlsbb (Vector Count Leading Zero Least-Significant Bits Byte)
15286          DIP("vclzlsbb %d,v%d\n", rT_addr, vB_addr);
15287 
15288       } else {
15289          // vctzlsbb (Vector Count Trailing Zero Least-Significant Bits Byte)
15290          DIP("vctzlsbb %d,v%d\n", rT_addr, vB_addr);
15291       }
15292 
15293       for( i = 0; i < 16; i++ ) {
15294          byte_mask[i+1] = newTemp( Ity_I32 );
15295          count[i+1] = newTemp( Ity_I32 );
15296          bit_zero[i] = newTemp( Ity_I1 );
15297 
15298          /* bit_zero[i] = 0x0 until the first 1 bit is found in lsb of
15299           * byte.  When the first 1 bit is found it causes the byte_mask
15300           * to change from 0x1 to 0x0.  Thus the AND of the lsb and byte_mask
15301           * will be zero  which will be equal to the zero byte_mask causing
15302           * the value of bit_zero[i] to be equal to 0x1 for all remaining bits.
15303           */
15304 
15305          if ( rA_addr == 0 )
15306             /* leading zero bit in byte count,
15307                work bytes from left to right
15308             */
15309             assign( bit_zero[i],
15310                     binop( Iop_CmpEQ32,
15311                            binop( Iop_And32,
15312                                   unop( Iop_V128to32,
15313                                         binop( Iop_ShrV128,
15314                                                mkexpr( vB ),
15315                                                mkU8( ( 15 - i) * 8 ) ) ),
15316                                   mkexpr( byte_mask[i] ) ),
15317                            mkexpr( byte_mask[i] ) ) );
15318 
15319          else if ( rA_addr == 1 )
15320             /* trailing zero bit in byte count,
15321              * work bytes from right to left
15322              */
15323             assign( bit_zero[i],
15324                     binop( Iop_CmpEQ32,
15325                            binop( Iop_And32,
15326                                   unop( Iop_V128to32,
15327                                         binop( Iop_ShrV128,
15328                                                mkexpr( vB ),
15329                                                mkU8( i * 8 ) ) ),
15330                                   mkexpr( byte_mask[i] ) ),
15331                            mkexpr( byte_mask[i] ) ) );
15332 
15333          /* Increment count as long as bit_zero = 0 */
15334          assign( count[i+1], binop( Iop_Add32,
15335                                     mkexpr( count[i] ),
15336                                     unop( Iop_1Uto32,
15337                                           unop( Iop_Not1,
15338                                                 mkexpr( bit_zero[i] ) ) ) ) );
15339 
15340          /* If comparison fails to find a zero bit, set the byte_mask to zero
15341           * for all future comparisons so there will be no more matches.
15342           */
15343          assign( byte_mask[i+1],
15344                  binop( Iop_And32,
15345                         unop( Iop_1Uto32,
15346                               unop( Iop_Not1,
15347                                     mkexpr( bit_zero[i] ) ) ),
15348                         mkexpr( byte_mask[i] )  ) );
15349       }
15350       putIReg( rT_addr, unop( Iop_32Uto64, mkexpr( count[16] ) ) );
15351       return True;
15352    }
15353 
15354    case 6: // vnegw,  Vector Negate Word
15355       DIP("vnegw  v%d,%d,v%d", rT_addr, rA_addr, vB_addr);
15356 
15357       /* multiply each word by -1 */
15358       assign( vT, binop( Iop_Mul32x4, mkexpr( vB ), mkV128( 0xFFFF ) ) );
15359       break;
15360 
15361    case 7: // vnegd,  Vector Negate Doubleword
15362       DIP("vnegd  v%d,%d,v%d", rT_addr, rA_addr, vB_addr);
15363 
15364       /* multiply each word by -1 */
15365       assign( vT, binop( Iop_64HLtoV128,
15366                          binop( Iop_Mul64,
15367                                 unop( Iop_V128HIto64,
15368                                       mkexpr( vB ) ),
15369                                 mkU64( 0xFFFFFFFFFFFFFFFF ) ),
15370                          binop( Iop_Mul64,
15371                                unop( Iop_V128to64,
15372                                       mkexpr( vB ) ),
15373                                 mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) );
15374       break;
15375 
15376    case 8:  // vprtybw,  Vector Parity Byte Word
15377    case 9:  // vprtybd,  Vector Parity Byte Doubleword
15378    case 10: // vprtybq,  Vector Parity Byte Quadword
15379       {
15380          UInt i;
15381          IRTemp bit_in_byte[16];
15382          IRTemp word_parity[4];
15383 
15384          for( i = 0; i < 16; i++ ) {
15385             bit_in_byte[i] = newTemp( Ity_I32 );
15386             assign( bit_in_byte[i],
15387                     binop( Iop_And32,
15388                            unop( Iop_V128to32,
15389                                  binop( Iop_ShrV128,
15390                                         mkexpr( vB ),
15391                                         mkU8( ( 15 - i ) * 8 ) ) ),
15392                            mkU32( 0x1 ) ) );
15393          }
15394 
15395          for( i = 0; i < 4; i++ ) {
15396             word_parity[i] = newTemp(Ity_I32);
15397             assign( word_parity[i],
15398                     mkXOr4_32( bit_in_byte[0 + i * 4],
15399                                bit_in_byte[1 + i * 4],
15400                                bit_in_byte[2 + i * 4],
15401                                bit_in_byte[3 + i * 4] ) );
15402          }
15403 
15404          if ( rA_addr == 8 ) {
15405             DIP("vprtybw  v%d,v%d", rT_addr, vB_addr);
15406 
15407             assign( vT, mkV128from32( word_parity[0], word_parity[1],
15408                                       word_parity[2], word_parity[3] ) );
15409 
15410          } else if ( rA_addr == 9 ) {
15411             DIP("vprtybd  v%d,v%d", rT_addr, vB_addr);
15412 
15413             assign( vT,
15414                     binop( Iop_64HLtoV128,
15415                            binop( Iop_32HLto64,
15416                                   mkU32( 0 ),
15417                                   binop( Iop_Xor32,
15418                                          mkexpr( word_parity[0] ),
15419                                          mkexpr( word_parity[1] ) ) ),
15420                            binop( Iop_32HLto64,
15421                                   mkU32( 0 ),
15422                                   binop( Iop_Xor32,
15423                                          mkexpr( word_parity[2] ),
15424                                          mkexpr( word_parity[3] ) ) ) ) );
15425 
15426          } else if ( rA_addr == 10 ) {
15427             DIP("vprtybq  v%d,v%d", rT_addr, vB_addr);
15428 
15429             assign( vT,
15430                     binop( Iop_64HLtoV128,
15431                            mkU64( 0 ),
15432                            unop( Iop_32Uto64,
15433                                  mkXOr4_32( word_parity[0],
15434                                             word_parity[1],
15435                                             word_parity[2],
15436                                             word_parity[3] ) ) ) );
15437          }
15438       }
15439       break;
15440 
15441    case 16: // vextsb2w,  Vector Extend Sign Byte to Word
15442       DIP("vextsb2w  v%d,%d,v%d", rT_addr, rA_addr, vB_addr);
15443 
15444       /* Iop_MullEven8Sx16 does a signed widening multiplication of byte to
15445        * two byte sign extended result.  Then do a two byte to four byte sign
15446        * extended multiply.  Note contents of upper three bytes in word are
15447        * "over written". So just take source and multiply by 1.
15448        */
15449       assign( vT, binop( Iop_MullEven16Sx8,
15450                          binop( Iop_64HLtoV128,
15451                                 mkU64( 0x0000000100000001 ),
15452                                 mkU64( 0x0000000100000001 ) ),
15453                          binop( Iop_MullEven8Sx16,
15454                                 mkexpr( vB ),
15455                                 binop( Iop_64HLtoV128,
15456                                        mkU64( 0x0001000100010001 ),
15457                                        mkU64( 0x0001000100010001 ) ) ) ) );
15458       break;
15459 
15460    case 17: // vextsh2w,  Vector Extend Sign Halfword to Word
15461       DIP("vextsh2w  v%d,%d,v%d", rT_addr, rA_addr, vB_addr);
15462 
15463       /* Iop_MullEven16Sx8 does a signed widening multiply of four byte
15464        * 8 bytes.  Note contents of upper two bytes in word are
15465        * "over written". So just take source and multiply by 1.
15466        */
15467       assign( vT, binop( Iop_MullEven16Sx8,
15468                          binop( Iop_64HLtoV128,
15469                                 mkU64( 0x0000000100000001 ),
15470                                 mkU64( 0x0000000100000001 ) ),
15471                         mkexpr( vB ) ) );
15472 
15473       break;
15474 
15475    case 24: // vextsb2d,  Vector Extend Sign Byte to Doubleword
15476       DIP("vextsb2d  v%d,%d,v%d", rT_addr, rA_addr, vB_addr);
15477 
15478       /* Iop_MullEven8Sx16 does a signed widening multiplication of byte to
15479        * two byte sign extended result.  Then do a two byte to four byte sign
15480        * extended multiply. Then do four byte to eight byte multiply.
15481        */
15482       assign( vT, binop( Iop_MullEven32Sx4,
15483                          binop( Iop_64HLtoV128,
15484                                 mkU64( 0x0000000000000001 ),
15485                                 mkU64( 0x0000000000000001 ) ),
15486                         binop( Iop_MullEven16Sx8,
15487                                binop( Iop_64HLtoV128,
15488                                       mkU64( 0x0000000100000001 ),
15489                                       mkU64( 0x0000000100000001 ) ),
15490                               binop( Iop_MullEven8Sx16,
15491                                      binop( Iop_64HLtoV128,
15492                                             mkU64( 0x0001000100010001 ),
15493                                             mkU64( 0x0001000100010001 ) ),
15494                                     mkexpr( vB ) ) ) ) );
15495       break;
15496 
15497    case 25: // vextsh2d,  Vector Extend Sign Halfword to Doubleword
15498       DIP("vextsh2d  v%d,%d,v%d", rT_addr, rA_addr, vB_addr);
15499 
15500       assign( vT, binop( Iop_MullEven32Sx4,
15501                          binop( Iop_64HLtoV128,
15502                                 mkU64( 0x0000000000000001 ),
15503                                 mkU64( 0x0000000000000001 ) ),
15504                         binop( Iop_MullEven16Sx8,
15505                                binop( Iop_64HLtoV128,
15506                                       mkU64( 0x0000000100000001 ),
15507                                       mkU64( 0x0000000100000001 ) ),
15508                                mkexpr( vB ) ) ) );
15509       break;
15510 
15511    case 26: // vextsw2d,  Vector Extend Sign Word to Doubleword
15512       DIP("vextsw2d  v%d,%d,v%d", rT_addr, rA_addr, vB_addr);
15513 
15514       assign( vT, binop( Iop_MullEven32Sx4,
15515                          binop( Iop_64HLtoV128,
15516                                 mkU64( 0x0000000000000001 ),
15517                                 mkU64( 0x0000000000000001 ) ),
15518                         mkexpr( vB ) ) );
15519       break;
15520 
15521    case 28: // vctzb,  Vector Count Trailing Zeros Byte
15522       {
15523          DIP("vctzb  v%d,v%d", rT_addr, vB_addr);
15524 
15525          /* This instruction is only available in the ISA 3.0 */
15526          if ( !mode64 || !allow_isa_3_0 ) {
15527             vex_printf("\n vctzb instruction not supported on non ISA 3.0 platform\n\n");
15528             return False;
15529          }
15530          assign( vT, unop( Iop_Ctz8x16, mkexpr( vB ) ) );
15531       }
15532       break;
15533 
15534    case 29: // vctzh,  Vector Count Trailing Zeros Halfword
15535       {
15536          DIP("vctzh  v%d,v%d", rT_addr, vB_addr);
15537 
15538          /* This instruction is only available in the ISA 3.0 */
15539          if ( !mode64 || !allow_isa_3_0 ) {
15540             vex_printf("\n vctzh instruction not supported on non ISA 3.0 platform\n\n");
15541             return False;
15542          }
15543          assign( vT, unop( Iop_Ctz16x8, mkexpr( vB ) ) );
15544       }
15545       break;
15546 
15547    case 30: // vctzw,  Vector Count Trailing Zeros Word
15548       {
15549          DIP("vctzw  v%d,v%d", rT_addr, vB_addr);
15550 
15551          /* This instruction is only available in the ISA 3.0 */
15552          if ( !mode64 || !allow_isa_3_0 ) {
15553             vex_printf("\n vctzw instruction not supported on non ISA 3.0 platform\n\n");
15554             return False;
15555          }
15556          assign( vT, unop( Iop_Ctz32x4, mkexpr( vB ) ) );
15557       }
15558       break;
15559 
15560    case 31: // vctzd,  Vector Count Trailing Zeros Double word
15561       {
15562          DIP("vctzd  v%d,v%d", rT_addr, vB_addr);
15563 
15564          /* This instruction is only available in the ISA 3.0 */
15565          if ( !mode64 || !allow_isa_3_0 ) {
15566             vex_printf("\n vctzd instruction not supported on non ISA 3.0 platform\n\n");
15567             return False;
15568          }
15569          assign( vT, unop( Iop_Ctz64x2, mkexpr( vB ) ) );
15570       }
15571       break;
15572 
15573    default:
15574       vex_printf("dis_av_extend_sign(ppc)(Unsupported vector extend sign instruction)\n");
15575       return False;
15576    }
15577 
15578    putVReg( rT_addr, mkexpr( vT ) );
15579    return True;
15580 }
15581 
15582 /*
15583 Vector Rotate Instructions
15584 */
dis_av_rotate(UInt theInstr)15585 static Bool dis_av_rotate ( UInt theInstr )
15586 {
15587    /* VX-Form */
15588 
15589    UChar opc1    = ifieldOPC( theInstr );
15590    UChar vT_addr = ifieldRegDS( theInstr );
15591    UChar vA_addr = ifieldRegA( theInstr );
15592    UChar vB_addr = ifieldRegB( theInstr );
15593    UInt  opc2    = IFIELD( theInstr, 0, 11 );
15594 
15595    IRTemp vA    = newTemp( Ity_V128 );
15596    IRTemp vB    = newTemp( Ity_V128 );
15597    IRTemp src3  = newTemp( Ity_V128 );
15598    IRTemp vT    = newTemp( Ity_V128 );
15599    IRTemp field_mask = newTemp( Ity_V128 );
15600    IRTemp mask128 = newTemp( Ity_V128 );
15601    IRTemp vA_word[4];
15602    IRTemp left_bits[4];
15603    IRTemp right_bits[4];
15604    IRTemp shift[4];
15605    IRTemp mask[4];
15606    IRTemp tmp128[4];
15607    UInt i;
15608    UInt num_words;
15609    UInt word_size;
15610    unsigned long long word_mask;
15611 
15612    if ( opc1 != 0x4 ) {
15613       vex_printf("dis_av_rotate(ppc)(instr)\n");
15614       return False;
15615    }
15616 
15617    assign( vA, getVReg( vA_addr ) );
15618    assign( vB, getVReg( vB_addr ) );
15619 
15620    switch (opc2) {
15621    case 0x85: // vrlwmi,  Vector Rotate Left Word then Mask Insert
15622    case 0x185: // vrlwnm,  Vector Rotate Left Word then AND with Mask
15623       num_words = 4;
15624       word_size = 32;
15625       assign( field_mask, binop( Iop_64HLtoV128,
15626                                  mkU64( 0 ),
15627                                  mkU64( 0x1F ) ) );
15628       word_mask = 0xFFFFFFFF;
15629       break;
15630 
15631    case 0x0C5: // vrldmi,  Vector Rotate Left Doubleword then Mask Insert
15632    case 0x1C5: // vrldnm,  Vector Rotate Left Doubleword then AND with Mask
15633       num_words = 2;
15634       word_size = 64;
15635       assign( field_mask, binop( Iop_64HLtoV128,
15636                                  mkU64( 0 ),
15637                                  mkU64( 0x3F ) ) );
15638       word_mask = 0xFFFFFFFFFFFFFFFFULL;
15639       break;
15640    default:
15641       vex_printf("dis_av_rotate(ppc)(opc2)\n");
15642       return False;
15643    }
15644 
15645    for( i = 0; i < num_words; i++ ) {
15646       left_bits[i]  = newTemp( Ity_I8 );
15647       right_bits[i] = newTemp( Ity_I8 );
15648       shift[i] = newTemp( Ity_I8 );
15649       mask[i]  = newTemp( Ity_V128 );
15650       tmp128[i] = newTemp( Ity_V128 );
15651       vA_word[i] = newTemp( Ity_V128 );
15652 
15653       assign( shift[i],
15654               unop( Iop_64to8,
15655                     unop( Iop_V128to64,
15656                           binop( Iop_AndV128,
15657                                  binop( Iop_ShrV128,
15658                                         mkexpr( vB ),
15659                                         mkU8( (num_words - 1 - i )
15660                                               * word_size ) ),
15661                                  mkexpr( field_mask ) ) ) ) );
15662 
15663       /* left_bits = 63 - mb.  Tells us how many bits to the left
15664        * of mb to clear. Note for a word left_bits = 32+mb, for a double
15665        * word left_bits = mb
15666        */
15667       assign( left_bits[i],
15668               unop( Iop_64to8,
15669                     binop( Iop_Add64,
15670                            mkU64( 64 - word_size ),
15671                            unop( Iop_V128to64,
15672                                  binop( Iop_AndV128,
15673                                         binop( Iop_ShrV128,
15674                                                mkexpr( vB ),
15675                                                mkU8( ( num_words - 1 - i )
15676                                                      * word_size + 16 ) ),
15677                                         mkexpr( field_mask ) ) ) ) ) );
15678       /* right_bits = 63 - me.  Tells us how many bits to the right
15679        * of me to clear. Note for a word, left_bits = me+32, for a double
15680        * word left_bits = me
15681        */
15682       assign( right_bits[i],
15683               unop( Iop_64to8,
15684                     binop( Iop_Sub64,
15685                            mkU64( word_size - 1 ),
15686                            unop( Iop_V128to64,
15687                                  binop( Iop_AndV128,
15688                                         binop( Iop_ShrV128,
15689                                                mkexpr( vB ),
15690                                                mkU8( ( num_words - 1 - i )
15691                                                      * word_size + 8 ) ),
15692                                         mkexpr( field_mask ) ) ) ) ) );
15693 
15694       /* create mask for 32-bit word or 64-bit word */
15695       assign( mask[i],
15696               binop( Iop_64HLtoV128,
15697                      mkU64( 0 ),
15698                      binop( Iop_Shl64,
15699                             binop( Iop_Shr64,
15700                                    binop( Iop_Shr64,
15701                                           binop( Iop_Shl64,
15702                                                  mkU64( 0xFFFFFFFFFFFFFFFF ),
15703                                                  mkexpr( left_bits[i] ) ),
15704                                           mkexpr( left_bits[i] ) ),
15705                                    mkexpr( right_bits[i] ) ),
15706                             mkexpr( right_bits[i] ) ) ) );
15707 
15708       /* Need to rotate vA using a left and right shift of vA OR'd together
15709        * then ANDed with the mask.
15710        */
15711       assign( vA_word[i], binop( Iop_AndV128,
15712                                  mkexpr( vA ),
15713                                  binop( Iop_ShlV128,
15714                                         binop( Iop_64HLtoV128,
15715                                                mkU64( 0 ),
15716                                                mkU64( word_mask ) ),
15717                                         mkU8( ( num_words - 1 - i )
15718                                               * word_size ) ) ) );
15719       assign( tmp128[i],
15720               binop( Iop_AndV128,
15721                      binop( Iop_ShlV128,
15722                             mkexpr( mask[i] ),
15723                             mkU8( ( num_words - 1 - i) * word_size ) ),
15724                      binop( Iop_OrV128,
15725                             binop( Iop_ShlV128,
15726                                    mkexpr( vA_word[i] ),
15727                                    mkexpr( shift[i] ) ),
15728                             binop( Iop_ShrV128,
15729                                    mkexpr( vA_word[i] ),
15730                                    unop( Iop_32to8,
15731                                          binop(Iop_Sub32,
15732                                                mkU32( word_size ),
15733                                                unop( Iop_8Uto32,
15734                                                      mkexpr( shift[i] ) ) )
15735                                          ) ) ) ) );
15736    }
15737 
15738    switch (opc2) {
15739    case 0x85: // vrlwmi,  Vector Rotate Left Word then Mask Insert
15740       DIP("vrlwmi %d,%d,v%d", vT_addr, vA_addr, vB_addr);
15741 
15742       assign( src3, getVReg( vT_addr ) );
15743       assign( mask128, unop( Iop_NotV128,
15744                              mkOr4_V128_expr( binop( Iop_ShlV128,
15745                                                      mkexpr( mask[0] ),
15746                                                      mkU8( 96 ) ),
15747                                               binop( Iop_ShlV128,
15748                                                      mkexpr( mask[1] ),
15749                                                      mkU8( 64 ) ),
15750                                               binop( Iop_ShlV128,
15751                                                      mkexpr( mask[2] ),
15752                                                      mkU8( 32 ) ),
15753                                               mkexpr( mask[3] ) ) ) );
15754       assign( vT, binop( Iop_OrV128,
15755                          binop( Iop_AndV128,
15756                                 mkexpr( src3 ),
15757                                 mkexpr( mask128 ) ),
15758                          mkOr4_V128( tmp128[0], tmp128[1],
15759                                      tmp128[2], tmp128[3] ) ) );
15760       break;
15761 
15762    case 0xC5: // vrldmi,  Vector Rotate Left Double word then Mask Insert
15763       DIP("vrldmi %d,%d,v%d", vT_addr, vA_addr, vB_addr);
15764 
15765       assign( src3, getVReg( vT_addr ) );
15766       assign( mask128, unop( Iop_NotV128,
15767                              binop( Iop_OrV128,
15768                                     binop( Iop_ShlV128,
15769                                            mkexpr( mask[0] ),
15770                                            mkU8( 64 ) ),
15771                                     mkexpr( mask[1] ) ) ) );
15772 
15773       assign( vT, binop( Iop_OrV128,
15774                          binop( Iop_AndV128,
15775                                 mkexpr( src3 ),
15776                                 mkexpr( mask128 ) ),
15777                          binop( Iop_OrV128,
15778                                 mkexpr( tmp128[0] ),
15779                                 mkexpr( tmp128[1] ) ) ) );
15780       break;
15781 
15782    case 0x185: // vrlwnm,  Vector Rotate Left Word then AND with Mask
15783       DIP("vrlwnm %d,%d,v%d", vT_addr, vA_addr, vB_addr);
15784       assign( vT, mkOr4_V128( tmp128[0], tmp128[1], tmp128[2], tmp128[3] ) );
15785       break;
15786 
15787    case 0x1C5: // vrldnm,  Vector Rotate Left Doubleword then AND with Mask
15788       DIP("vrldnm %d,%d,v%d", vT_addr, vA_addr, vB_addr);
15789       assign( vT, binop( Iop_OrV128,
15790                          mkexpr( tmp128[0] ),
15791                          mkexpr( tmp128[1] ) ) );
15792       break;
15793    }
15794 
15795    putVReg( vT_addr, mkexpr( vT ) );
15796    return True;
15797 }
15798 
15799 /*
15800   AltiVec Vector Extract Element Instructions
15801 */
dis_av_extract_element(UInt theInstr)15802 static Bool dis_av_extract_element ( UInt theInstr )
15803 {
15804    /* VX-Form,
15805     * sorta destination and first source are GPR not vector registers
15806     */
15807 
15808    UChar opc1    = ifieldOPC( theInstr );
15809    UChar rT_addr = ifieldRegDS( theInstr );
15810    UChar rA_addr = ifieldRegA( theInstr );
15811    UChar vB_addr = ifieldRegB( theInstr );
15812    UInt  opc2    = IFIELD( theInstr, 0, 11 );
15813 
15814    IRTemp vB = newTemp( Ity_V128 );
15815    IRTemp rA = newTemp( Ity_I64 );
15816    IRTemp rT = newTemp( Ity_I64 );
15817 
15818    assign( vB, getVReg( vB_addr ) );
15819    assign( rA, getIReg( rA_addr ) );
15820 
15821    if ( opc1 != 0x4 ) {
15822       vex_printf("dis_av_extract_element(ppc)(instr)\n");
15823       return False;
15824    }
15825 
15826    switch ( opc2 ) {
15827    case 0x60D: // vextublx, vector extract unsigned Byte Left-indexed
15828       DIP("vextublx %d,%d,v%d", rT_addr, rA_addr, vB_addr);
15829 
15830       assign( rT, extract_field_from_vector( vB,
15831                                              binop( Iop_Sub64,
15832                                                     mkU64( 15 ),
15833                                                     mkexpr( rA ) ),
15834                                              0xFF ) );
15835 
15836       break;
15837 
15838    case 0x64D: // vextuhlx, vector extract unsigned Halfword Left-indexed
15839       DIP("vextuhlx %d,%d,v%d", rT_addr, rA_addr, vB_addr);
15840 
15841       assign( rT, extract_field_from_vector( vB,
15842                                              binop( Iop_Sub64,
15843                                                     mkU64( 14 ),
15844                                                     mkexpr( rA ) ),
15845                                              0xFFFF ) );
15846       break;
15847 
15848    case 0x68D: // vextuwlx, vector extract unsigned Word Left-indexed
15849       DIP("vextuwlx %d,%d,v%d", rT_addr, rA_addr, vB_addr);
15850 
15851       assign( rT, extract_field_from_vector( vB,
15852                                              binop( Iop_Sub64,
15853                                                     mkU64( 12 ),
15854                                                     mkexpr( rA ) ),
15855                                              0xFFFFFFFF ) );
15856       break;
15857 
15858    case 0x70D: // vextubrx, vector extract unsigned Byte Right-indexed
15859       DIP("vextubrx %d,%d,v%d", rT_addr, rA_addr, vB_addr);
15860 
15861       assign( rT, extract_field_from_vector( vB, mkexpr( rA ), 0xFF ) );
15862       break;
15863 
15864    case 0x74D: // vextuhrx, vector extract unsigned Halfword Right-indexed
15865       DIP("vextuhrx %d,%d,v%d", rT_addr, rA_addr, vB_addr);
15866 
15867       assign( rT, extract_field_from_vector( vB, mkexpr( rA ), 0xFFFF ) );
15868       break;
15869 
15870    case 0x78D: // vextuwrx, vector extract unsigned Word Right-indexed
15871       DIP("vextuwrx %d,%d,v%d", rT_addr, rA_addr, vB_addr);
15872 
15873       assign( rT, extract_field_from_vector( vB, mkexpr( rA ), 0xFFFFFFFF ) );
15874       break;
15875 
15876    default:
15877       vex_printf("dis_av_extract_element(ppc)(opc2)\n");
15878       return False;
15879    }
15880    putIReg( rT_addr, mkexpr( rT ) );
15881    return True;
15882 }
15883 
15884 /*
15885  * VSX scalar and vector convert instructions
15886  */
15887 static Bool
dis_vx_conv(UInt theInstr,UInt opc2)15888 dis_vx_conv ( UInt theInstr, UInt opc2 )
15889 {
15890    /* XX2-Form */
15891    UChar opc1 = ifieldOPC( theInstr );
15892    UChar XT = ifieldRegXT( theInstr );
15893    UChar XB = ifieldRegXB( theInstr );
15894    IRTemp xB, xB2;
15895    IRTemp b3, b2, b1, b0;
15896    xB = xB2 = IRTemp_INVALID;
15897 
15898    if (opc1 != 0x3C) {
15899       vex_printf( "dis_vx_conv(ppc)(instr)\n" );
15900       return False;
15901    }
15902 
15903    /* Create and assign temps only as needed for the given instruction. */
15904    switch (opc2) {
15905       // scalar double-precision floating point argument
15906       case 0x2B0: case 0x0b0: case 0x290: case 0x212: case 0x216: case 0x090:
15907          xB = newTemp(Ity_F64);
15908          assign( xB,
15909                  unop( Iop_ReinterpI64asF64,
15910                        unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
15911          break;
15912       // vector double-precision floating point arguments
15913       case 0x1b0: case 0x312: case 0x390: case 0x190: case 0x3B0:
15914 
15915          xB = newTemp(Ity_F64);
15916          xB2 = newTemp(Ity_F64);
15917          assign( xB,
15918                  unop( Iop_ReinterpI64asF64,
15919                        unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
15920          assign( xB2,
15921                  unop( Iop_ReinterpI64asF64,
15922                        unop( Iop_V128to64, getVSReg( XB ) ) ) );
15923          break;
15924       // vector single precision or [un]signed integer word arguments
15925       case 0x130: case 0x392: case 0x330: case 0x310: case 0x110:
15926       case 0x1f0: case 0x1d0:
15927          b3 = b2 = b1 = b0 = IRTemp_INVALID;
15928          breakV128to4x32(getVSReg(XB), &b3, &b2, &b1, &b0);
15929          break;
15930          // vector [un]signed integer doubleword argument
15931       case 0x3f0: case 0x370: case 0x3d0: case 0x350:
15932          xB = newTemp(Ity_I64);
15933          assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
15934          xB2 = newTemp(Ity_I64);
15935          assign( xB2, unop( Iop_V128to64, getVSReg( XB ) ) );
15936          break;
15937       // scalar [un]signed integer doubleword argument
15938       case 0x250: case 0x270: case 0x2D0: case 0x2F0:
15939          xB = newTemp(Ity_I64);
15940          assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
15941          break;
15942       // scalar single precision argument
15943       case 0x292: // xscvspdp
15944          xB  = newTemp(Ity_I32);
15945 
15946          assign( xB, handle_SNaN_to_QNaN_32(unop( Iop_64HIto32,
15947                                                   unop( Iop_V128HIto64,
15948                                                         getVSReg( XB ) ) ) ) );
15949          break;
15950       case 0x296: // xscvspdpn (non signaling version of xscvpdp)
15951          xB = newTemp(Ity_I32);
15952          assign( xB,
15953                  unop( Iop_64HIto32, unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
15954          break;
15955 
15956       /* Certain instructions have their complete implementation in the main switch statement
15957        * that follows this one; thus we have a "do nothing" case for those instructions here.
15958        */
15959       case 0x170: case 0x150:
15960          break; // do nothing
15961 
15962       default:
15963          vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
15964          return False;
15965    }
15966 
15967 
15968    switch (opc2) {
15969       case 0x2B0:
15970          // xscvdpsxds (VSX Scalar truncate Double-Precision to integer and Convert
15971          //             to Signed Integer Doubleword format with Saturate)
15972          DIP("xscvdpsxds v%u,v%u\n", XT, XB);
15973          putVSReg( XT,
15974                    binop( Iop_64HLtoV128, binop( Iop_F64toI64S,
15975                                                  mkU32( Irrm_ZERO ),
15976                                                  mkexpr( xB ) ), mkU64( 0 ) ) );
15977          break;
15978       case 0x0b0: // xscvdpsxws (VSX Scalar truncate Double-Precision to integer and
15979                   //             Convert to Signed Integer Word format with Saturate)
15980          DIP("xscvdpsxws v%u,v%u\n", XT, XB);
15981          putVSReg( XT,
15982                    binop( Iop_64HLtoV128,
15983                           unop( Iop_32Sto64,
15984                                 binop( Iop_F64toI32S,
15985                                        mkU32( Irrm_ZERO ),
15986                                        mkexpr( xB ) ) ),
15987                                        mkU64( 0ULL ) ) );
15988          break;
15989       case 0x290: // xscvdpuxds (VSX Scalar truncate Double-Precision integer and Convert
15990                   //             to Unsigned Integer Doubleword format with Saturate)
15991          DIP("xscvdpuxds v%u,v%u\n", XT, XB);
15992          putVSReg( XT,
15993                    binop( Iop_64HLtoV128,
15994                           binop( Iop_F64toI64U,
15995                                  mkU32( Irrm_ZERO ),
15996                                  mkexpr( xB ) ),
15997                                  mkU64( 0ULL ) ) );
15998          break;
15999       case 0x270:
16000          // xscvsxdsp (VSX Scalar Convert and round Signed Integer Doubleword
16001          //             to Single-Precision format)
16002          DIP("xscvsxdsp v%u,v%u\n", XT, XB);
16003          putVSReg( XT,
16004                    binop( Iop_64HLtoV128,
16005                           unop( Iop_ReinterpF64asI64,
16006                                 binop( Iop_RoundF64toF32,
16007                                        get_IR_roundingmode(),
16008                                        binop( Iop_I64StoF64,
16009                                               get_IR_roundingmode(),
16010                                               mkexpr( xB ) ) ) ),
16011                           mkU64( 0 ) ) );
16012          break;
16013       case 0x2F0:
16014          // xscvsxddp (VSX Scalar Convert and round Signed Integer Doubleword to
16015          //            Double-Precision format)
16016          DIP("xscvsxddp v%u,v%u\n", XT, XB);
16017          putVSReg( XT,
16018                    binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
16019                                                 binop( Iop_I64StoF64, get_IR_roundingmode(),
16020                                                        mkexpr( xB ) ) ),
16021                                                        mkU64( 0 ) ) );
16022          break;
16023       case 0x250:
16024          // xscvuxdsp (VSX Scalar Convert and round Unsigned Integer
16025          //            Doubleword to Singel-Precision format)
16026          DIP("xscvuxdsp v%u,v%u\n", XT, XB);
16027          putVSReg( XT,
16028                    binop( Iop_64HLtoV128,
16029                           unop( Iop_ReinterpF64asI64,
16030                                 binop( Iop_RoundF64toF32,
16031                                        get_IR_roundingmode(),
16032                                        binop( Iop_I64UtoF64,
16033                                               get_IR_roundingmode(),
16034                                               mkexpr( xB ) ) ) ),
16035                           mkU64( 0 ) ) );
16036          break;
16037       case 0x2D0:
16038          // xscvuxddp (VSX Scalar Convert and round Unsigned Integer Doubleword to
16039          //            Double-Precision format)
16040          DIP("xscvuxddp v%u,v%u\n", XT, XB);
16041          putVSReg( XT,
16042                    binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
16043                                                 binop( Iop_I64UtoF64, get_IR_roundingmode(),
16044                                                        mkexpr( xB ) ) ),
16045                                                        mkU64( 0 ) ) );
16046          break;
16047       case 0x1b0: // xvcvdpsxws (VSX Vector truncate Double-Precision to integer and Convert
16048                   //             to Signed Integer Word format with Saturate)
16049       {
16050          IRTemp hiResult_32 = newTemp(Ity_I32);
16051          IRTemp loResult_32 = newTemp(Ity_I32);
16052          IRExpr* rmZero = mkU32(Irrm_ZERO);
16053 
16054          DIP("xvcvdpsxws v%u,v%u\n",  XT, XB);
16055          assign(hiResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB)));
16056          assign(loResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB2)));
16057          putVSReg( XT,
16058                    binop( Iop_64HLtoV128,
16059                           unop( Iop_32Sto64, mkexpr( hiResult_32 ) ),
16060                           unop( Iop_32Sto64, mkexpr( loResult_32 ) ) ) );
16061          break;
16062       }
16063       case 0x130: case 0x110: // xvcvspsxws, xvcvspuxws
16064          //  (VSX Vector truncate Single-Precision to integer and
16065          //   Convert to [Un]signed Integer Word format with Saturate)
16066       {
16067          IRExpr * b0_result, * b1_result, * b2_result, * b3_result;
16068          IRTemp tempResult = newTemp(Ity_V128);
16069          IRTemp res0 = newTemp(Ity_I32);
16070          IRTemp res1 = newTemp(Ity_I32);
16071          IRTemp res2 = newTemp(Ity_I32);
16072          IRTemp res3 = newTemp(Ity_I32);
16073          IRTemp hi64 = newTemp(Ity_I64);
16074          IRTemp lo64 = newTemp(Ity_I64);
16075          Bool un_signed = (opc2 == 0x110);
16076          IROp op = un_signed ? Iop_QFtoI32Ux4_RZ : Iop_QFtoI32Sx4_RZ;
16077 
16078          DIP("xvcvsp%sxws v%u,v%u\n", un_signed ? "u" : "s", XT, XB);
16079          /* The xvcvsp{s|u}xws instruction is similar to vct{s|u}xs, except if src is a NaN,
16080           * then result is set to 0x80000000.  */
16081          assign(tempResult, unop(op, getVSReg(XB)));
16082          assign( hi64, unop(Iop_V128HIto64, mkexpr(tempResult)) );
16083          assign( lo64, unop(Iop_V128to64,   mkexpr(tempResult)) );
16084          assign( res3, unop(Iop_64HIto32, mkexpr(hi64)) );
16085          assign( res2, unop(Iop_64to32,   mkexpr(hi64)) );
16086          assign( res1, unop(Iop_64HIto32, mkexpr(lo64)) );
16087          assign( res0, unop(Iop_64to32,   mkexpr(lo64)) );
16088 
16089          b3_result = IRExpr_ITE(is_NaN(Ity_I32, b3),
16090                                 // then: result is 0x{8|0}80000000
16091                                 mkU32(un_signed ? 0x00000000 : 0x80000000),
16092                                 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
16093                                 mkexpr(res3));
16094          b2_result = IRExpr_ITE(is_NaN(Ity_I32, b2),
16095                                 // then: result is 0x{8|0}80000000
16096                                 mkU32(un_signed ? 0x00000000 : 0x80000000),
16097                                 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
16098                                 mkexpr(res2));
16099          b1_result = IRExpr_ITE(is_NaN(Ity_I32, b1),
16100                                 // then: result is 0x{8|0}80000000
16101                                 mkU32(un_signed ? 0x00000000 : 0x80000000),
16102                                 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
16103                                 mkexpr(res1));
16104          b0_result = IRExpr_ITE(is_NaN(Ity_I32, b0),
16105                                 // then: result is 0x{8|0}80000000
16106                                 mkU32(un_signed ? 0x00000000 : 0x80000000),
16107                                 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
16108                                 mkexpr(res0));
16109 
16110          putVSReg( XT,
16111                    binop( Iop_64HLtoV128,
16112                           binop( Iop_32HLto64, b3_result, b2_result ),
16113                           binop( Iop_32HLto64, b1_result, b0_result ) ) );
16114          break;
16115       }
16116       case 0x212: // xscvdpsp (VSX Scalar round Double-Precision to single-precision and
16117                   //           Convert to Single-Precision format
16118          DIP("xscvdpsp v%u,v%u\n", XT, XB);
16119          putVSReg( XT,
16120                    binop( Iop_64HLtoV128,
16121                           binop( Iop_32HLto64,
16122                                  unop( Iop_ReinterpF32asI32,
16123                                        unop( Iop_TruncF64asF32,
16124                                              binop( Iop_RoundF64toF32,
16125                                                     get_IR_roundingmode(),
16126                                                     mkexpr( xB ) ) ) ),
16127                                  mkU32( 0 ) ),
16128                           mkU64( 0ULL ) ) );
16129          break;
16130       case 0x216: /* xscvdpspn (VSX Scalar convert scalar Single-Precision to
16131                               vector Single-Precision non-signalling */
16132          DIP("xscvdpspn v%u,v%u\n", XT, XB);
16133          putVSReg( XT,
16134                    binop( Iop_64HLtoV128,
16135                           binop( Iop_32HLto64,
16136                                  unop( Iop_ReinterpF32asI32,
16137                                        unop( Iop_TruncF64asF32,
16138                                              mkexpr( xB ) ) ),
16139                                  mkU32( 0 ) ),
16140                           mkU64( 0ULL ) ) );
16141          break;
16142       case 0x090: // xscvdpuxws (VSX Scalar truncate Double-Precision to integer
16143                   //             and Convert to Unsigned Integer Word format with Saturate)
16144          DIP("xscvdpuxws v%u,v%u\n", XT, XB);
16145          putVSReg( XT,
16146                    binop( Iop_64HLtoV128,
16147                           binop( Iop_32HLto64,
16148                                  mkU32( 0 ),
16149                                  binop( Iop_F64toI32U,
16150                                         mkU32( Irrm_ZERO ),
16151                                         mkexpr( xB ) ) ),
16152                           mkU64( 0ULL ) ) );
16153          break;
16154       case 0x292: // xscvspdp (VSX Scalar Convert Single-Precision to Double-Precision format, signaling)
16155          DIP("xscvspdp v%u,v%u\n", XT, XB);
16156          putVSReg( XT,
16157                    binop( Iop_64HLtoV128,
16158                           unop( Iop_ReinterpF64asI64,
16159                                 unop( Iop_F32toF64,
16160                                       unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
16161                           mkU64( 0ULL ) ) );
16162          break;
16163       case 0x296: // xscvspdpn (VSX Scalar Convert Single-Precision to Double-Precision format Non signaling)
16164          DIP("xscvspdpn v%u,v%u\n", XT, XB);
16165          putVSReg( XT,
16166                    binop( Iop_64HLtoV128,
16167                           unop( Iop_ReinterpF64asI64,
16168                                 unop( Iop_F32toF64,
16169                                       unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
16170                                       mkU64( 0ULL ) ) );
16171          break;
16172       case 0x312: // xvcvdpsp (VSX Vector round Double-Precision to single-precision
16173                   //           and Convert to Single-Precision format)
16174          DIP("xvcvdpsp v%u,v%u\n", XT, XB);
16175          putVSReg( XT,
16176                    binop( Iop_64HLtoV128,
16177                           binop( Iop_32HLto64,
16178                                  unop( Iop_ReinterpF32asI32,
16179                                        unop( Iop_TruncF64asF32,
16180                                              binop( Iop_RoundF64toF32,
16181                                                     get_IR_roundingmode(),
16182                                                     mkexpr( xB ) ) ) ),
16183                                  mkU32( 0 ) ),
16184                           binop( Iop_32HLto64,
16185                                  unop( Iop_ReinterpF32asI32,
16186                                        unop( Iop_TruncF64asF32,
16187                                              binop( Iop_RoundF64toF32,
16188                                                     get_IR_roundingmode(),
16189                                                     mkexpr( xB2 ) ) ) ),
16190                                  mkU32( 0 ) ) ) );
16191          break;
16192       case 0x390: // xvcvdpuxds (VSX Vector truncate Double-Precision to integer
16193                   //             and Convert to Unsigned Integer Doubleword format
16194                   //             with Saturate)
16195          DIP("xvcvdpuxds v%u,v%u\n", XT, XB);
16196          putVSReg( XT,
16197                    binop( Iop_64HLtoV128,
16198                           binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
16199                           binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
16200          break;
16201       case 0x190: // xvcvdpuxws (VSX Vector truncate Double-Precision to integer and
16202                   //             Convert to Unsigned Integer Word format with Saturate)
16203          DIP("xvcvdpuxws v%u,v%u\n", XT, XB);
16204          putVSReg( XT,
16205                    binop( Iop_64HLtoV128,
16206                           binop( Iop_32HLto64,
16207                                  binop( Iop_F64toI32U,
16208                                         mkU32( Irrm_ZERO ),
16209                                         mkexpr( xB ) ),
16210                                  mkU32( 0 ) ),
16211                           binop( Iop_32HLto64,
16212                                  binop( Iop_F64toI32U,
16213                                         mkU32( Irrm_ZERO ),
16214                                         mkexpr( xB2 ) ),
16215                                  mkU32( 0 ) ) ) );
16216          break;
16217       case 0x392: // xvcvspdp (VSX Vector Convert Single-Precision to Double-Precision format)
16218          DIP("xvcvspdp v%u,v%u\n", XT, XB);
16219          putVSReg( XT,
16220                    binop( Iop_64HLtoV128,
16221                           unop( Iop_ReinterpF64asI64,
16222                                 unop( Iop_F32toF64,
16223                                       unop( Iop_ReinterpI32asF32,
16224                                             handle_SNaN_to_QNaN_32( mkexpr( b3 ) ) ) ) ),
16225                           unop( Iop_ReinterpF64asI64,
16226                                 unop( Iop_F32toF64,
16227                                       unop( Iop_ReinterpI32asF32,
16228                                             handle_SNaN_to_QNaN_32( mkexpr( b1 ) ) ) ) ) ) );
16229          break;
16230       case 0x330: // xvcvspsxds (VSX Vector truncate Single-Precision to integer and
16231                   //           Convert to Signed Integer Doubleword format with Saturate)
16232          DIP("xvcvspsxds v%u,v%u\n", XT, XB);
16233          putVSReg( XT,
16234                    binop( Iop_64HLtoV128,
16235                           binop( Iop_F64toI64S,
16236                                  mkU32( Irrm_ZERO ),
16237                                  unop( Iop_F32toF64,
16238                                        unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
16239                           binop( Iop_F64toI64S,
16240                                  mkU32( Irrm_ZERO ),
16241                                  unop( Iop_F32toF64,
16242                                        unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
16243          break;
16244       case 0x310: // xvcvspuxds (VSX Vector truncate Single-Precision to integer and
16245                   //            Convert to Unsigned Integer Doubleword format with Saturate)
16246          DIP("xvcvspuxds v%u,v%u\n", XT, XB);
16247          putVSReg( XT,
16248                    binop( Iop_64HLtoV128,
16249                           binop( Iop_F64toI64U,
16250                                  mkU32( Irrm_ZERO ),
16251                                  unop( Iop_F32toF64,
16252                                        unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
16253                           binop( Iop_F64toI64U,
16254                                  mkU32( Irrm_ZERO ),
16255                                  unop( Iop_F32toF64,
16256                                        unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
16257          break;
16258       case 0x3B0: // xvcvdpsxds (VSX Vector truncate Double-Precision to integer and
16259                   //             Convert to Signed Integer Doubleword format with Saturate)
16260          DIP("xvcvdpsxds v%u,v%u\n", XT, XB);
16261          putVSReg( XT,
16262                    binop( Iop_64HLtoV128,
16263                           binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
16264                           binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
16265          break;
16266       case 0x3f0: // xvcvsxddp (VSX Vector Convert and round Signed Integer Doubleword
16267                   //            to Double-Precision format)
16268          DIP("xvcvsxddp v%u,v%u\n", XT, XB);
16269          putVSReg( XT,
16270                    binop( Iop_64HLtoV128,
16271                           unop( Iop_ReinterpF64asI64,
16272                                 binop( Iop_I64StoF64,
16273                                        get_IR_roundingmode(),
16274                                        mkexpr( xB ) ) ),
16275                           unop( Iop_ReinterpF64asI64,
16276                                 binop( Iop_I64StoF64,
16277                                        get_IR_roundingmode(),
16278                                        mkexpr( xB2 ) ) ) ) );
16279          break;
16280       case 0x3d0: // xvcvuxddp (VSX Vector Convert and round Unsigned Integer Doubleword
16281                   //            to Double-Precision format)
16282          DIP("xvcvuxddp v%u,v%u\n", XT, XB);
16283          putVSReg( XT,
16284                    binop( Iop_64HLtoV128,
16285                           unop( Iop_ReinterpF64asI64,
16286                                 binop( Iop_I64UtoF64,
16287                                        get_IR_roundingmode(),
16288                                        mkexpr( xB ) ) ),
16289                           unop( Iop_ReinterpF64asI64,
16290                                 binop( Iop_I64UtoF64,
16291                                        get_IR_roundingmode(),
16292                                        mkexpr( xB2 ) ) ) ) );
16293 
16294          break;
16295       case 0x370: // xvcvsxdsp (VSX Vector Convert and round Signed Integer Doubleword
16296                   //            to Single-Precision format)
16297          DIP("xvcvsxddp v%u,v%u\n",  XT, XB);
16298          putVSReg( XT,
16299                    binop( Iop_64HLtoV128,
16300                           binop( Iop_32HLto64,
16301                                  unop( Iop_ReinterpF32asI32,
16302                                        unop( Iop_TruncF64asF32,
16303                                              binop( Iop_RoundF64toF32,
16304                                                     get_IR_roundingmode(),
16305                                                     binop( Iop_I64StoF64,
16306                                                            get_IR_roundingmode(),
16307                                                            mkexpr( xB ) ) ) ) ),
16308                                  mkU32( 0 ) ),
16309                           binop( Iop_32HLto64,
16310                                  unop( Iop_ReinterpF32asI32,
16311                                        unop( Iop_TruncF64asF32,
16312                                              binop( Iop_RoundF64toF32,
16313                                                     get_IR_roundingmode(),
16314                                                     binop( Iop_I64StoF64,
16315                                                            get_IR_roundingmode(),
16316                                                            mkexpr( xB2 ) ) ) ) ),
16317                                  mkU32( 0 ) ) ) );
16318          break;
16319       case 0x350: // xvcvuxdsp (VSX Vector Convert and round Unsigned Integer Doubleword
16320                   //            to Single-Precision format)
16321          DIP("xvcvuxddp v%u,v%u\n", XT, XB);
16322          putVSReg( XT,
16323                    binop( Iop_64HLtoV128,
16324                           binop( Iop_32HLto64,
16325                                  unop( Iop_ReinterpF32asI32,
16326                                        unop( Iop_TruncF64asF32,
16327                                              binop( Iop_RoundF64toF32,
16328                                                     get_IR_roundingmode(),
16329                                                     binop( Iop_I64UtoF64,
16330                                                            get_IR_roundingmode(),
16331                                                            mkexpr( xB ) ) ) ) ),
16332                                  mkU32( 0 ) ),
16333                           binop( Iop_32HLto64,
16334                                  unop( Iop_ReinterpF32asI32,
16335                                        unop( Iop_TruncF64asF32,
16336                                              binop( Iop_RoundF64toF32,
16337                                                     get_IR_roundingmode(),
16338                                                     binop( Iop_I64UtoF64,
16339                                                            get_IR_roundingmode(),
16340                                                            mkexpr( xB2 ) ) ) ) ),
16341                                  mkU32( 0 ) ) ) );
16342          break;
16343 
16344       case 0x1f0: // xvcvsxwdp (VSX Vector Convert Signed Integer Word to Double-Precision format)
16345          DIP("xvcvsxwdp v%u,v%u\n",  XT, XB);
16346          putVSReg( XT,
16347                    binop( Iop_64HLtoV128,
16348                           unop( Iop_ReinterpF64asI64,
16349                                 binop( Iop_I64StoF64, get_IR_roundingmode(),
16350                                        unop( Iop_32Sto64, mkexpr( b3 ) ) ) ),
16351                           unop( Iop_ReinterpF64asI64,
16352                                 binop( Iop_I64StoF64, get_IR_roundingmode(),
16353                                        unop( Iop_32Sto64, mkexpr( b1 ) ) ) ) ) );
16354          break;
16355       case 0x1d0: // xvcvuxwdp (VSX Vector Convert Unsigned Integer Word to Double-Precision format)
16356          DIP("xvcvuxwdp v%u,v%u\n",  XT, XB);
16357          putVSReg( XT,
16358                    binop( Iop_64HLtoV128,
16359                           unop( Iop_ReinterpF64asI64,
16360                                 binop( Iop_I64UtoF64, get_IR_roundingmode(),
16361                                        unop( Iop_32Uto64, mkexpr( b3 ) ) ) ),
16362                           unop( Iop_ReinterpF64asI64,
16363                                 binop( Iop_I64UtoF64, get_IR_roundingmode(),
16364                                        unop( Iop_32Uto64, mkexpr( b1 ) ) ) ) ) );
16365          break;
16366       case 0x170: // xvcvsxwsp (VSX Vector Convert Signed Integer Word to Single-Precision format)
16367          DIP("xvcvsxwsp v%u,v%u\n",  XT, XB);
16368          putVSReg( XT, unop( Iop_I32StoFx4, getVSReg( XB ) ) );
16369          break;
16370       case 0x150: // xvcvuxwsp (VSX Vector Convert Unsigned Integer Word to Single-Precision format)
16371          DIP("xvcvuxwsp v%u,v%u\n",  XT, XB);
16372          putVSReg( XT, unop( Iop_I32UtoFx4, getVSReg( XB ) ) );
16373          break;
16374 
16375       default:
16376          vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
16377          return False;
16378    }
16379    return True;
16380 }
16381 
16382 /*
16383  * VSX vector Double Precision Floating Point Arithmetic Instructions
16384  */
16385 static Bool
dis_vxv_dp_arith(UInt theInstr,UInt opc2)16386 dis_vxv_dp_arith ( UInt theInstr, UInt opc2 )
16387 {
16388    /* XX3-Form */
16389    UChar opc1 = ifieldOPC( theInstr );
16390    UChar XT = ifieldRegXT( theInstr );
16391    UChar XA = ifieldRegXA( theInstr );
16392    UChar XB = ifieldRegXB( theInstr );
16393    IRExpr* rm = get_IR_roundingmode();
16394    IRTemp frA = newTemp(Ity_F64);
16395    IRTemp frB = newTemp(Ity_F64);
16396    IRTemp frA2 = newTemp(Ity_F64);
16397    IRTemp frB2 = newTemp(Ity_F64);
16398 
16399    if (opc1 != 0x3C) {
16400       vex_printf( "dis_vxv_dp_arith(ppc)(instr)\n" );
16401       return False;
16402    }
16403 
16404    assign(frA,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
16405    assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
16406    assign(frA2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XA ))));
16407    assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XB ))));
16408 
16409    switch (opc2) {
16410       case 0x1E0: // xvdivdp (VSX Vector Divide Double-Precision)
16411       case 0x1C0: // xvmuldp (VSX Vector Multiply Double-Precision)
16412       case 0x180: // xvadddp (VSX Vector Add Double-Precision)
16413       case 0x1A0: // xvsubdp (VSX Vector Subtract Double-Precision)
16414       {
16415          IROp mOp;
16416          const HChar * oper_name;
16417          switch (opc2) {
16418             case 0x1E0:
16419                mOp = Iop_DivF64;
16420                oper_name = "div";
16421                break;
16422             case 0x1C0:
16423                mOp = Iop_MulF64;
16424                oper_name = "mul";
16425                break;
16426             case 0x180:
16427                mOp = Iop_AddF64;
16428                oper_name = "add";
16429                break;
16430             case 0x1A0:
16431                mOp = Iop_SubF64;
16432                oper_name = "sub";
16433                break;
16434 
16435             default:
16436                vpanic("The impossible happened: dis_vxv_dp_arith(ppc)");
16437          }
16438          IRTemp hiResult = newTemp(Ity_I64);
16439          IRTemp loResult = newTemp(Ity_I64);
16440          DIP("xv%sdp v%d,v%d,v%d\n", oper_name, XT, XA, XB);
16441 
16442          assign( hiResult,
16443                  unop( Iop_ReinterpF64asI64,
16444                        triop( mOp, rm, mkexpr( frA ), mkexpr( frB ) ) ) );
16445          assign( loResult,
16446                  unop( Iop_ReinterpF64asI64,
16447                        triop( mOp, rm, mkexpr( frA2 ), mkexpr( frB2 ) ) ) );
16448          putVSReg( XT,
16449                    binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
16450          break;
16451       }
16452       case 0x196: // xvsqrtdp
16453       {
16454          IRTemp hiResult = newTemp(Ity_I64);
16455          IRTemp loResult = newTemp(Ity_I64);
16456          DIP("xvsqrtdp v%d,v%d\n", XT, XB);
16457 
16458          assign( hiResult,
16459                  unop( Iop_ReinterpF64asI64,
16460                        binop( Iop_SqrtF64, rm, mkexpr( frB ) ) ) );
16461          assign( loResult,
16462                  unop( Iop_ReinterpF64asI64,
16463                        binop( Iop_SqrtF64, rm, mkexpr( frB2 ) ) ) );
16464          putVSReg( XT,
16465                    binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
16466          break;
16467       }
16468       case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp (VSX Vector Multiply-Add Double-Precision)
16469       case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp (VSX Vector Multiply-Subtract Double-Precision)
16470       case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp (VSX Vector Negate Multiply-Add Double-Precision)
16471       case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp (VSX Vector Negate Multiply-Subtract Double-Precision)
16472       {
16473          /* xvm{add|sub}mdp XT,XA,XB is element-wise equivalent to fm{add|sub} FRT,FRA,FRC,FRB with . . .
16474           *    XT == FRC
16475           *    XA == FRA
16476           *    XB == FRB
16477           *
16478           * and for xvm{add|sub}adp . . .
16479           *    XT == FRB
16480           *    XA == FRA
16481           *    XB == FRC
16482           */
16483          Bool negate;
16484          IROp mOp = Iop_INVALID;
16485          const HChar * oper_name = NULL;
16486          Bool mdp = False;
16487 
16488          switch (opc2) {
16489             case 0x184: case 0x1A4:
16490             case 0x384: case 0x3A4:
16491                mOp = Iop_MAddF64;
16492                oper_name = "add";
16493                mdp = (opc2 & 0x0FF) == 0x0A4;
16494                break;
16495 
16496             case 0x1C4: case 0x1E4:
16497             case 0x3C4: case 0x3E4:
16498                mOp = Iop_MSubF64;
16499                oper_name = "sub";
16500                mdp = (opc2 & 0x0FF) == 0x0E4;
16501                break;
16502 
16503             default:
16504                vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
16505          }
16506 
16507          switch (opc2) {
16508             case 0x384: case 0x3A4:
16509             case 0x3C4: case 0x3E4:
16510                negate = True;
16511                break;
16512             default:
16513                negate = False;
16514          }
16515          IRTemp hiResult = newTemp(Ity_I64);
16516          IRTemp loResult = newTemp(Ity_I64);
16517          IRTemp frT = newTemp(Ity_F64);
16518          IRTemp frT2 = newTemp(Ity_F64);
16519          DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, mdp ? "mdp" : "adp",
16520              XT, XA, XB);
16521          assign(frT,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XT ) ) ) );
16522          assign(frT2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XT ) ) ) );
16523 
16524          assign( hiResult,
16525                  unop( Iop_ReinterpF64asI64,
16526                        qop( mOp,
16527                             rm,
16528                             mkexpr( frA ),
16529                             mkexpr( mdp ? frT : frB ),
16530                             mkexpr( mdp ? frB : frT ) ) ) );
16531          assign( loResult,
16532                  unop( Iop_ReinterpF64asI64,
16533                        qop( mOp,
16534                             rm,
16535                             mkexpr( frA2 ),
16536                             mkexpr( mdp ? frT2 : frB2 ),
16537                             mkexpr( mdp ? frB2 : frT2 ) ) ) );
16538          putVSReg( XT,
16539                    binop( Iop_64HLtoV128,
16540                           mkexpr( negate ? getNegatedResult( hiResult )
16541                                          : hiResult ),
16542                           mkexpr( negate ? getNegatedResult( loResult )
16543                                          : loResult ) ) );
16544          break;
16545       }
16546       case 0x1D4: // xvtsqrtdp (VSX Vector Test for software Square Root Double-Precision)
16547       {
16548          IRTemp frBHi_I64 = newTemp(Ity_I64);
16549          IRTemp frBLo_I64 = newTemp(Ity_I64);
16550          IRTemp flagsHi = newTemp(Ity_I32);
16551          IRTemp flagsLo = newTemp(Ity_I32);
16552          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
16553          IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
16554          fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
16555 
16556          DIP("xvtsqrtdp cr%d,v%d\n", crfD, XB);
16557          assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
16558          assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
16559          do_fp_tsqrt(frBHi_I64, False /*not single precision*/, &fe_flagHi, &fg_flagHi);
16560          do_fp_tsqrt(frBLo_I64, False /*not single precision*/, &fe_flagLo, &fg_flagLo);
16561          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
16562           * where fl_flag == 1 on ppc64.
16563           */
16564          assign( flagsHi,
16565                  binop( Iop_Or32,
16566                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
16567                                binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
16568                         binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
16569          assign( flagsLo,
16570                  binop( Iop_Or32,
16571                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
16572                                binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
16573                         binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
16574          putGST_field( PPC_GST_CR,
16575                        binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
16576                        crfD );
16577          break;
16578       }
16579       case 0x1F4: // xvtdivdp (VSX Vector Test for software Divide Double-Precision)
16580       {
16581          IRTemp frBHi_I64 = newTemp(Ity_I64);
16582          IRTemp frBLo_I64 = newTemp(Ity_I64);
16583          IRTemp frAHi_I64 = newTemp(Ity_I64);
16584          IRTemp frALo_I64 = newTemp(Ity_I64);
16585          IRTemp flagsHi = newTemp(Ity_I32);
16586          IRTemp flagsLo = newTemp(Ity_I32);
16587          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
16588          IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
16589          fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
16590 
16591          DIP("xvtdivdp cr%d,v%d,v%d\n", crfD, XA, XB);
16592          assign( frAHi_I64, unop(Iop_V128HIto64, getVSReg( XA )) );
16593          assign( frALo_I64, unop(Iop_V128to64, getVSReg( XA )) );
16594          assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
16595          assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
16596 
16597          _do_fp_tdiv(frAHi_I64, frBHi_I64, False/*dp*/, &fe_flagHi, &fg_flagHi);
16598          _do_fp_tdiv(frALo_I64, frBLo_I64, False/*dp*/, &fe_flagLo, &fg_flagLo);
16599          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
16600           * where fl_flag == 1 on ppc64.
16601           */
16602          assign( flagsHi,
16603                  binop( Iop_Or32,
16604                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
16605                                binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
16606                         binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
16607          assign( flagsLo,
16608                  binop( Iop_Or32,
16609                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
16610                                binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
16611                         binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
16612          putGST_field( PPC_GST_CR,
16613                        binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
16614                        crfD );
16615          break;
16616       }
16617 
16618       default:
16619          vex_printf( "dis_vxv_dp_arith(ppc)(opc2)\n" );
16620          return False;
16621    }
16622    return True;
16623 }
16624 
16625 /*
16626  * VSX vector Single Precision Floating Point Arithmetic Instructions
16627  */
16628 static Bool
dis_vxv_sp_arith(UInt theInstr,UInt opc2)16629 dis_vxv_sp_arith ( UInt theInstr, UInt opc2 )
16630 {
16631    /* XX3-Form */
16632    UChar opc1 = ifieldOPC( theInstr );
16633    UChar XT = ifieldRegXT( theInstr );
16634    UChar XA = ifieldRegXA( theInstr );
16635    UChar XB = ifieldRegXB( theInstr );
16636    IRExpr* rm = get_IR_roundingmode();
16637    IRTemp a3, a2, a1, a0;
16638    IRTemp b3, b2, b1, b0;
16639    IRTemp res0 = newTemp(Ity_I32);
16640    IRTemp res1 = newTemp(Ity_I32);
16641    IRTemp res2 = newTemp(Ity_I32);
16642    IRTemp res3 = newTemp(Ity_I32);
16643 
16644    a3 = a2 = a1 = a0 = IRTemp_INVALID;
16645    b3 = b2 = b1 = b0 = IRTemp_INVALID;
16646 
16647    if (opc1 != 0x3C) {
16648       vex_printf( "dis_vxv_sp_arith(ppc)(instr)\n" );
16649       return False;
16650    }
16651 
16652    switch (opc2) {
16653       case 0x100: // xvaddsp (VSX Vector Add Single-Precision)
16654          DIP("xvaddsp v%d,v%d,v%d\n", XT, XA, XB);
16655          // WARNING: BOGUS! The backend ignores rm on Iop_Add32Fx4
16656          putVSReg( XT, triop(Iop_Add32Fx4, rm,
16657                              getVSReg( XA ), getVSReg( XB )) );
16658          break;
16659 
16660       case 0x140: // xvmulsp (VSX Vector Multiply Single-Precision)
16661          DIP("xvmulsp v%d,v%d,v%d\n", XT, XA, XB);
16662          // WARNING: BOGUS! The backend ignores rm on Iop_Mul32Fx4
16663          putVSReg( XT, triop(Iop_Mul32Fx4, rm,
16664                              getVSReg( XA ), getVSReg( XB )) );
16665          break;
16666 
16667       case 0x120: // xvsubsp (VSX Vector Subtract Single-Precision)
16668          DIP("xvsubsp v%d,v%d,v%d\n", XT, XA, XB);
16669          // WARNING: BOGUS! The backend ignores rm on Iop_Sub32Fx4
16670          putVSReg( XT, triop(Iop_Sub32Fx4, rm,
16671                              getVSReg( XA ), getVSReg( XB )) );
16672          break;
16673 
16674       case 0x160: // xvdivsp (VSX Vector Divide Single-Precision)
16675       {
16676          /* Iop_Div32Fx4 is not implemented for ppc64 (in host_ppc_{isel|defs}.c.
16677           * So there are two choices:
16678           *   1. Implement the xvdivsp with a native insn; or
16679           *   2. Extract the 4 single precision floats from each vector
16680           *      register inputs and perform fdivs on each pair
16681           * I will do the latter, due to the general philosophy of
16682           * reusing existing implementations when practical.
16683           */
16684          DIP("xvdivsp v%d,v%d,v%d\n", XT, XA, XB);
16685          breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
16686          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
16687 
16688          assign( res0,
16689               unop( Iop_ReinterpF32asI32,
16690                     unop( Iop_TruncF64asF32,
16691                           triop( Iop_DivF64r32, rm, mkexpr( a0 ), mkexpr( b0 ) ) ) ) );
16692          assign( res1,
16693                  unop( Iop_ReinterpF32asI32,
16694                        unop( Iop_TruncF64asF32,
16695                              triop( Iop_DivF64r32, rm, mkexpr( a1 ), mkexpr( b1 ) ) ) ) );
16696          assign( res2,
16697                  unop( Iop_ReinterpF32asI32,
16698                        unop( Iop_TruncF64asF32,
16699                              triop( Iop_DivF64r32, rm, mkexpr( a2 ), mkexpr( b2 ) ) ) ) );
16700          assign( res3,
16701                  unop( Iop_ReinterpF32asI32,
16702                        unop( Iop_TruncF64asF32,
16703                              triop( Iop_DivF64r32, rm, mkexpr( a3 ), mkexpr( b3 ) ) ) ) );
16704 
16705          putVSReg( XT,
16706                    binop( Iop_64HLtoV128,
16707                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
16708                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
16709          break;
16710       }
16711       case 0x116: // xvsqrtsp (VSX Vector Square Root Single-Precision)
16712       {
16713          DIP("xvsqrtsp v%d,v%d\n", XT, XB);
16714          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
16715          /* Note: The native xvsqrtsp insruction does not always give the same precision
16716           * as what we get with Iop_SqrtF64.  But it doesn't seem worthwhile to implement
16717           * an Iop_SqrtF32 that would give us a lower precision result, albeit more true
16718           * to the actual instruction.
16719           */
16720 
16721          assign( res0,
16722                  unop( Iop_ReinterpF32asI32,
16723                        unop( Iop_TruncF64asF32,
16724                              binop(Iop_SqrtF64, rm, mkexpr( b0 ) ) ) ) );
16725          assign( res1,
16726                  unop( Iop_ReinterpF32asI32,
16727                        unop( Iop_TruncF64asF32,
16728                              binop(Iop_SqrtF64, rm, mkexpr( b1 ) ) ) ) );
16729          assign( res2,
16730                  unop( Iop_ReinterpF32asI32,
16731                        unop( Iop_TruncF64asF32,
16732                              binop(Iop_SqrtF64, rm, mkexpr( b2) ) ) ) );
16733          assign( res3,
16734                  unop( Iop_ReinterpF32asI32,
16735                        unop( Iop_TruncF64asF32,
16736                              binop(Iop_SqrtF64, rm, mkexpr( b3 ) ) ) ) );
16737 
16738          putVSReg( XT,
16739                    binop( Iop_64HLtoV128,
16740                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
16741                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
16742          break;
16743       }
16744 
16745       case 0x104: case 0x124: // xvmaddasp, xvmaddmsp (VSX Vector Multiply-Add Single-Precision)
16746       case 0x144: case 0x164: // xvmsubasp, xvmsubmsp (VSX Vector Multiply-Subtract Single-Precision)
16747       case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp (VSX Vector Negate Multiply-Add Single-Precision)
16748       case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp (VSX Vector Negate Multiply-Subtract Single-Precision)
16749       {
16750          IRTemp t3, t2, t1, t0;
16751          Bool msp = False;
16752          Bool negate;
16753          const HChar * oper_name = NULL;
16754          IROp mOp = Iop_INVALID;
16755          switch (opc2) {
16756             case 0x104: case 0x124:
16757             case 0x304: case 0x324:
16758                msp = (opc2 & 0x0FF) == 0x024;
16759                mOp = Iop_MAddF64r32;
16760                oper_name = "madd";
16761                break;
16762 
16763             case 0x144: case 0x164:
16764             case 0x344: case 0x364:
16765                msp = (opc2 & 0x0FF) == 0x064;
16766                mOp = Iop_MSubF64r32;
16767                oper_name = "sub";
16768                break;
16769 
16770             default:
16771                vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
16772          }
16773 
16774          switch (opc2) {
16775             case 0x304: case 0x324:
16776             case 0x344: case 0x364:
16777                negate = True;
16778                break;
16779 
16780             default:
16781                negate = False;
16782          }
16783 
16784          DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name,
16785              msp ? "msp" : "asp", XT, XA, XB);
16786 
16787          t3 = t2 = t1 = t0 = IRTemp_INVALID;
16788          breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
16789          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
16790          breakV128to4xF64( getVSReg( XT ), &t3, &t2, &t1, &t0 );
16791 
16792          assign( res0,
16793                  unop( Iop_ReinterpF32asI32,
16794                        unop( Iop_TruncF64asF32,
16795                              qop( mOp,
16796                                   rm,
16797                                   mkexpr( a0 ),
16798                                   mkexpr( msp ? t0 : b0 ),
16799                                   mkexpr( msp ? b0 : t0 ) ) ) ) );
16800          assign( res1,
16801                  unop( Iop_ReinterpF32asI32,
16802                        unop( Iop_TruncF64asF32,
16803                              qop( mOp,
16804                                   rm,
16805                                   mkexpr( a1 ),
16806                                   mkexpr( msp ? t1 : b1 ),
16807                                   mkexpr( msp ? b1 : t1 ) ) ) ) );
16808          assign( res2,
16809                  unop( Iop_ReinterpF32asI32,
16810                        unop( Iop_TruncF64asF32,
16811                              qop( mOp,
16812                                   rm,
16813                                   mkexpr( a2 ),
16814                                   mkexpr( msp ? t2 : b2 ),
16815                                   mkexpr( msp ? b2 : t2 ) ) ) ) );
16816          assign( res3,
16817                  unop( Iop_ReinterpF32asI32,
16818                        unop( Iop_TruncF64asF32,
16819                              qop( mOp,
16820                                   rm,
16821                                   mkexpr( a3 ),
16822                                   mkexpr( msp ? t3 : b3 ),
16823                                   mkexpr( msp ? b3 : t3 ) ) ) ) );
16824 
16825          putVSReg( XT,
16826                    binop( Iop_64HLtoV128,
16827                           binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res3 ) : res3 ),
16828                                  mkexpr( negate ? getNegatedResult_32( res2 ) : res2 ) ),
16829                           binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res1 ) : res1 ),
16830                                  mkexpr( negate ? getNegatedResult_32( res0 ) : res0 ) ) ) );
16831 
16832          break;
16833       }
16834       case 0x154: // xvtsqrtsp (VSX Vector Test for software Square Root Single-Precision)
16835       {
16836          IRTemp flags0 = newTemp(Ity_I32);
16837          IRTemp flags1 = newTemp(Ity_I32);
16838          IRTemp flags2 = newTemp(Ity_I32);
16839          IRTemp flags3 = newTemp(Ity_I32);
16840          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
16841          IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
16842          IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
16843          fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
16844          fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
16845          DIP("xvtsqrtsp cr%d,v%d\n", crfD, XB);
16846 
16847          breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
16848          do_fp_tsqrt(b0, True /* single precision*/, &fe_flag0, &fg_flag0);
16849          do_fp_tsqrt(b1, True /* single precision*/, &fe_flag1, &fg_flag1);
16850          do_fp_tsqrt(b2, True /* single precision*/, &fe_flag2, &fg_flag2);
16851          do_fp_tsqrt(b3, True /* single precision*/, &fe_flag3, &fg_flag3);
16852 
16853          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
16854           * where fl_flag == 1 on ppc64.
16855           */
16856          assign( flags0,
16857                  binop( Iop_Or32,
16858                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
16859                                binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
16860                         binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
16861          assign( flags1,
16862                  binop( Iop_Or32,
16863                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
16864                                binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
16865                         binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
16866          assign( flags2,
16867                  binop( Iop_Or32,
16868                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
16869                                binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
16870                         binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
16871          assign( flags3,
16872                  binop( Iop_Or32,
16873                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
16874                                binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
16875                         binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
16876          putGST_field( PPC_GST_CR,
16877                        binop( Iop_Or32,
16878                               mkexpr( flags0 ),
16879                               binop( Iop_Or32,
16880                                      mkexpr( flags1 ),
16881                                      binop( Iop_Or32,
16882                                             mkexpr( flags2 ),
16883                                             mkexpr( flags3 ) ) ) ),
16884                        crfD );
16885 
16886          break;
16887       }
16888       case 0x174: // xvtdivsp (VSX Vector Test for software Divide Single-Precision)
16889       {
16890          IRTemp flags0 = newTemp(Ity_I32);
16891          IRTemp flags1 = newTemp(Ity_I32);
16892          IRTemp flags2 = newTemp(Ity_I32);
16893          IRTemp flags3 = newTemp(Ity_I32);
16894          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
16895          IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
16896          IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
16897          fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
16898          fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
16899          DIP("xvtdivsp cr%d,v%d,v%d\n", crfD, XA, XB);
16900 
16901          breakV128to4x32( getVSReg( XA ), &a3, &a2, &a1, &a0 );
16902          breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
16903          _do_fp_tdiv(a0, b0, True /* single precision*/, &fe_flag0, &fg_flag0);
16904          _do_fp_tdiv(a1, b1, True /* single precision*/, &fe_flag1, &fg_flag1);
16905          _do_fp_tdiv(a2, b2, True /* single precision*/, &fe_flag2, &fg_flag2);
16906          _do_fp_tdiv(a3, b3, True /* single precision*/, &fe_flag3, &fg_flag3);
16907 
16908          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
16909           * where fl_flag == 1 on ppc64.
16910           */
16911          assign( flags0,
16912                  binop( Iop_Or32,
16913                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
16914                                binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
16915                         binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
16916          assign( flags1,
16917                  binop( Iop_Or32,
16918                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
16919                                binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
16920                         binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
16921          assign( flags2,
16922                  binop( Iop_Or32,
16923                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
16924                                binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
16925                         binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
16926          assign( flags3,
16927                  binop( Iop_Or32,
16928                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
16929                                binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
16930                         binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
16931          putGST_field( PPC_GST_CR,
16932                        binop( Iop_Or32,
16933                               mkexpr( flags0 ),
16934                               binop( Iop_Or32,
16935                                      mkexpr( flags1 ),
16936                                      binop( Iop_Or32,
16937                                             mkexpr( flags2 ),
16938                                             mkexpr( flags3 ) ) ) ),
16939                        crfD );
16940 
16941          break;
16942       }
16943 
16944       default:
16945          vex_printf( "dis_vxv_sp_arith(ppc)(opc2)\n" );
16946          return False;
16947    }
16948    return True;
16949 }
16950 
16951 /*
16952  * Vector Population Count/bit matrix transpose
16953  */
16954 static Bool
dis_av_count_bitTranspose(UInt theInstr,UInt opc2)16955 dis_av_count_bitTranspose ( UInt theInstr, UInt opc2 )
16956 {
16957    UChar vRB_addr = ifieldRegB(theInstr);
16958    UChar vRT_addr = ifieldRegDS(theInstr);
16959    UChar opc1 = ifieldOPC( theInstr );
16960    IRTemp vB = newTemp(Ity_V128);
16961    assign( vB, getVReg(vRB_addr));
16962 
16963    if (opc1 != 0x4) {
16964       vex_printf( "dis_av_count_bitTranspose(ppc)(instr)\n" );
16965       return False;
16966    }
16967 
16968    switch (opc2) {
16969       case 0x702:    // vclzb
16970          DIP("vclzb v%d,v%d\n", vRT_addr, vRB_addr);
16971          putVReg( vRT_addr, unop(Iop_Clz8x16, mkexpr( vB ) ) );
16972          break;
16973 
16974       case 0x742:    // vclzh
16975          DIP("vclzh v%d,v%d\n", vRT_addr, vRB_addr);
16976          putVReg( vRT_addr, unop(Iop_Clz16x8, mkexpr( vB ) ) );
16977          break;
16978 
16979       case 0x782:    // vclzw
16980          DIP("vclzw v%d,v%d\n", vRT_addr, vRB_addr);
16981          putVReg( vRT_addr, unop(Iop_Clz32x4, mkexpr( vB ) ) );
16982          break;
16983 
16984       case 0x7C2:    // vclzd
16985          DIP("vclzd v%d,v%d\n", vRT_addr, vRB_addr);
16986          putVReg( vRT_addr, unop(Iop_Clz64x2, mkexpr( vB ) ) );
16987          break;
16988 
16989       case 0x703:    // vpopcntb
16990       {
16991          /* Break vector into 32-bit words and do the population count
16992           * on byte in the words
16993           */
16994          IRType ty = Ity_I32;
16995          IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
16996          bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
16997          IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
16998          cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
16999 
17000          DIP("vpopcntb v%d,v%d\n", vRT_addr, vRB_addr);
17001          breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
17002          cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   BYTE);
17003          cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  BYTE);
17004          cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  BYTE);
17005          cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, BYTE);
17006 
17007          putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
17008                                          cnt_bits32_63, cnt_bits0_31) );
17009          break;
17010       }
17011 
17012       case 0x743:    // vpopcnth
17013       {
17014          /* Break vector into 32-bit words and do the population count
17015           * for each half word
17016           */
17017          IRType ty = Ity_I32;
17018          IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
17019          bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
17020          IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
17021          cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
17022 
17023          DIP("vpopcnth v%d,v%d\n", vRT_addr, vRB_addr);
17024          breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
17025 
17026          cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   HWORD);
17027          cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  HWORD);
17028          cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  HWORD);
17029          cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, HWORD);
17030 
17031          putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
17032                                          cnt_bits32_63, cnt_bits0_31) );
17033          break;
17034       }
17035 
17036       case 0x783:    // vpopcntw
17037       {
17038          /* Break vector into 32-bit words and do the population count
17039           * on each word.
17040           */
17041          IRType ty = Ity_I32;
17042          IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
17043          bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
17044          IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
17045          cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
17046 
17047          DIP("vpopcntw v%d,v%d\n", vRT_addr, vRB_addr);
17048          breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
17049 
17050          cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   WORD);
17051          cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  WORD);
17052          cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  WORD);
17053          cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, WORD);
17054 
17055          putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
17056                                          cnt_bits32_63, cnt_bits0_31) );
17057          break;
17058       }
17059 
17060       case 0x7C3:    // vpopcntd
17061       {
17062          if (mode64) {
17063             /* Break vector into 64-bit double words and do the population
17064                count on each double word.
17065              */
17066             IRType ty = Ity_I64;
17067             IRTemp bits0_63   = newTemp(Ity_I64);
17068             IRTemp bits64_127 = newTemp(Ity_I64);
17069             IRTemp cnt_bits0_63   = newTemp(Ity_I64);
17070             IRTemp cnt_bits64_127 = newTemp(Ity_I64);
17071 
17072             DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr);
17073 
17074             assign(bits0_63,   unop( Iop_V128to64,   mkexpr( vB ) ) );
17075             assign(bits64_127, unop( Iop_V128HIto64, mkexpr( vB ) ) );
17076             cnt_bits0_63   = gen_POPCOUNT(ty, bits0_63,   DWORD);
17077             cnt_bits64_127 = gen_POPCOUNT(ty, bits64_127, DWORD);
17078 
17079             putVReg( vRT_addr, binop( Iop_64HLtoV128,
17080                                       mkexpr( cnt_bits64_127 ),
17081                                       mkexpr( cnt_bits0_63 ) ) );
17082          } else {
17083             /* Break vector into 32-bit words and do the population count
17084                on each 32-bit word.
17085              */
17086             IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
17087             bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
17088             IRTemp cnt_bits0_63    = newTemp(Ity_I64);
17089             IRTemp cnt_bits64_127  = newTemp(Ity_I64);
17090 
17091             DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr);
17092             breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95,
17093                                          &bits32_63, &bits0_31 );
17094 
17095             cnt_bits0_63   = gen_vpopcntd_mode32(bits0_31, bits32_63);
17096             cnt_bits64_127 = gen_vpopcntd_mode32(bits64_95, bits96_127);
17097 
17098             putVReg( vRT_addr, binop( Iop_64HLtoV128,
17099                                       mkexpr( cnt_bits64_127 ),
17100                                       mkexpr( cnt_bits0_63 ) ) );
17101          }
17102          break;
17103       }
17104 
17105       case 0x50C:  // vgbbd Vector Gather Bits by Bytes by Doubleword
17106          DIP("vgbbd v%d,v%d\n", vRT_addr, vRB_addr);
17107          putVReg( vRT_addr, unop( Iop_PwBitMtxXpose64x2, mkexpr( vB ) ) );
17108          break;
17109 
17110       case 0x5CC:  // vbpermd Vector Bit Permute Doubleword
17111       {
17112          UChar vRA_addr = ifieldRegA( theInstr );
17113          IRTemp vA = newTemp( Ity_V128 );
17114          UInt j;
17115          IRTemp index_dword_hi[8]; // index in double word
17116          IRTemp index_dword_lo[8];
17117          IRTemp index_dword_hi_valid[8];
17118          IRTemp index_dword_lo_valid[8];
17119          IRTemp pb_dword_hi[8];  // permute bit
17120          IRTemp pb_dword_lo[8];
17121          IRTemp tmp_hi[9];
17122          IRTemp tmp_lo[9];
17123 
17124          DIP("vbpermd v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
17125 
17126          tmp_hi[0] = newTemp( Ity_I64 );
17127          tmp_lo[0] = newTemp( Ity_I64 );
17128 
17129          assign( vA, getVReg(vRA_addr) );
17130          assign( tmp_hi[0], mkU64( 0 ) );
17131          assign( tmp_lo[0], mkU64( 0 ) );
17132 
17133          for (j=0; j<8; j++) {
17134             index_dword_hi[j] = newTemp( Ity_I64 );
17135             index_dword_lo[j] = newTemp( Ity_I64 );
17136             index_dword_hi_valid[j] = newTemp( Ity_I64 );
17137             index_dword_lo_valid[j] = newTemp( Ity_I64 );
17138             pb_dword_hi[j] = newTemp( Ity_I64 );
17139             pb_dword_lo[j] = newTemp( Ity_I64 );
17140             tmp_hi[j+1] = newTemp( Ity_I64 );
17141             tmp_lo[j+1] = newTemp( Ity_I64 );
17142 
17143             assign( index_dword_hi[j],
17144                     binop( Iop_And64,
17145                            binop( Iop_Shr64,
17146                                   unop( Iop_V128HIto64,
17147                                         mkexpr( vB ) ),
17148                                   mkU8( ( 7 - j ) * 8 ) ),
17149                            mkU64( 0xFF ) ) );
17150 
17151             assign( index_dword_lo[j],
17152                     binop( Iop_And64,
17153                            binop( Iop_Shr64,
17154                                   unop( Iop_V128to64,
17155                                         mkexpr( vB ) ),
17156                                   mkU8( ( 7 - j ) * 8 ) ),
17157                            mkU64( 0xFF ) ) );
17158 
17159             assign( index_dword_hi_valid[j],
17160                     unop( Iop_1Sto64,
17161                           binop( Iop_CmpLT64U,
17162                                  mkexpr( index_dword_hi[j] ),
17163                                  mkU64( 64 ) ) ) );
17164 
17165             assign( index_dword_lo_valid[j],
17166                     unop( Iop_1Sto64,
17167                           binop( Iop_CmpLT64U,
17168                                  mkexpr( index_dword_lo[j] ),
17169                                  mkU64( 64 ) ) ) );
17170             assign( pb_dword_hi[j],
17171                     binop( Iop_And64,
17172                            binop( Iop_Shr64,
17173                                   unop( Iop_V128HIto64,
17174                                         mkexpr( vA ) ),
17175                                   unop( Iop_64to8,
17176                                         binop( Iop_Sub64,
17177                                                mkU64( 63 ),
17178                                                mkexpr( index_dword_hi[j] )
17179                                                ) ) ),
17180                            mkU64( 0x1 ) ) );
17181 
17182             assign( pb_dword_lo[j],
17183                     binop( Iop_And64,
17184                            binop( Iop_Shr64,
17185                                   unop( Iop_V128to64,
17186                                         mkexpr( vA ) ),
17187                                   unop( Iop_64to8,
17188                                         binop( Iop_Sub64,
17189                                                mkU64( 63 ),
17190                                                mkexpr( index_dword_lo[j] )
17191                                                ) ) ),
17192                            mkU64( 0x1 ) ) );
17193 
17194             assign( tmp_hi[j+1],
17195                     binop( Iop_Or64,
17196                            binop( Iop_And64,
17197                                   mkexpr( index_dword_hi_valid[j] ),
17198                                   binop( Iop_Shl64,
17199                                          mkexpr( pb_dword_hi[j] ),
17200                                          mkU8( 7 - j ) ) ),
17201                            mkexpr( tmp_hi[j] ) ) );
17202 
17203             assign( tmp_lo[j+1],
17204                     binop( Iop_Or64,
17205                            binop( Iop_And64,
17206                                   mkexpr( index_dword_lo_valid[j] ),
17207                                   binop( Iop_Shl64,
17208                                          mkexpr( pb_dword_lo[j] ),
17209                                          mkU8( 7 - j ) ) ),
17210                            mkexpr( tmp_lo[j] ) ) );
17211          }
17212 
17213          putVReg( vRT_addr,
17214                   binop( Iop_64HLtoV128,
17215                          mkexpr( tmp_hi[8] ),
17216                          mkexpr( tmp_lo[8] ) ) );
17217       }
17218       break;
17219 
17220       default:
17221          vex_printf("dis_av_count_bitTranspose(ppc)(opc2)\n");
17222          return False;
17223       break;
17224    }
17225    return True;
17226 }
17227 
17228 typedef enum {
17229    PPC_CMP_EQ = 2,
17230    PPC_CMP_GT = 4,
17231    PPC_CMP_GE = 6,
17232    PPC_CMP_LT = 8
17233 } ppc_cmp_t;
17234 
17235 
17236 /*
17237   This helper function takes as input the IRExpr returned
17238   from a binop( Iop_CmpF64, fpA, fpB), whose result is returned
17239   in IR form.  This helper function converts it to PPC form.
17240 
17241   Map compare result from IR to PPC
17242 
17243   FP cmp result | PPC | IR
17244   --------------------------
17245   UN            | 0x1 | 0x45
17246   EQ            | 0x2 | 0x40
17247   GT            | 0x4 | 0x00
17248   LT            | 0x8 | 0x01
17249 
17250  condcode = Shl(1, (~(ccIR>>5) & 2)
17251                     | ((ccIR ^ (ccIR>>6)) & 1)
17252 */
17253 static IRTemp
get_fp_cmp_CR_val(IRExpr * ccIR_expr)17254 get_fp_cmp_CR_val (IRExpr * ccIR_expr)
17255 {
17256    IRTemp condcode = newTemp( Ity_I32 );
17257    IRTemp ccIR = newTemp( Ity_I32 );
17258 
17259    assign(ccIR, ccIR_expr);
17260    assign( condcode,
17261            binop( Iop_Shl32,
17262                   mkU32( 1 ),
17263                   unop( Iop_32to8,
17264                         binop( Iop_Or32,
17265                                binop( Iop_And32,
17266                                       unop( Iop_Not32,
17267                                             binop( Iop_Shr32,
17268                                                    mkexpr( ccIR ),
17269                                                    mkU8( 5 ) ) ),
17270                                       mkU32( 2 ) ),
17271                                binop( Iop_And32,
17272                                       binop( Iop_Xor32,
17273                                              mkexpr( ccIR ),
17274                                              binop( Iop_Shr32,
17275                                                     mkexpr( ccIR ),
17276                                                     mkU8( 6 ) ) ),
17277                                       mkU32( 1 ) ) ) ) ) );
17278    return condcode;
17279 }
17280 
17281 /*
17282  * Helper function for get_max_min_fp for ascertaining the max or min between two doubles
17283  * following these special rules:
17284  *   - The max/min of a QNaN and any value is that value
17285  *     (When two QNaNs are being compared, the frA QNaN is the return value.)
17286  *   - The max/min of any value and an SNaN is that SNaN converted to a QNaN
17287  *     (When two SNaNs are being compared, the frA SNaN is converted to a QNaN.)
17288  */
_get_maxmin_fp_NaN(IRTemp frA_I64,IRTemp frB_I64)17289 static IRExpr * _get_maxmin_fp_NaN(IRTemp frA_I64, IRTemp frB_I64)
17290 {
17291    IRTemp frA_isNaN = newTemp(Ity_I1);
17292    IRTemp frB_isNaN = newTemp(Ity_I1);
17293    IRTemp frA_isSNaN = newTemp(Ity_I1);
17294    IRTemp frB_isSNaN = newTemp(Ity_I1);
17295    IRTemp frA_isQNaN = newTemp(Ity_I1);
17296    IRTemp frB_isQNaN = newTemp(Ity_I1);
17297 
17298    assign( frA_isNaN, is_NaN( Ity_I64, frA_I64 ) );
17299    assign( frB_isNaN, is_NaN( Ity_I64, frB_I64 ) );
17300    // If operand is a NAN and bit 12 is '0', then it's an SNaN
17301    assign( frA_isSNaN,
17302            mkAND1( mkexpr(frA_isNaN),
17303                    binop( Iop_CmpEQ32,
17304                           binop( Iop_And32,
17305                                  unop( Iop_64HIto32, mkexpr( frA_I64 ) ),
17306                                  mkU32( 0x00080000 ) ),
17307                           mkU32( 0 ) ) ) );
17308    assign( frB_isSNaN,
17309            mkAND1( mkexpr(frB_isNaN),
17310                    binop( Iop_CmpEQ32,
17311                           binop( Iop_And32,
17312                                  unop( Iop_64HIto32, mkexpr( frB_I64 ) ),
17313                                  mkU32( 0x00080000 ) ),
17314                           mkU32( 0 ) ) ) );
17315    assign( frA_isQNaN,
17316            mkAND1( mkexpr( frA_isNaN ), unop( Iop_Not1, mkexpr( frA_isSNaN ) ) ) );
17317    assign( frB_isQNaN,
17318            mkAND1( mkexpr( frB_isNaN ), unop( Iop_Not1, mkexpr( frB_isSNaN ) ) ) );
17319 
17320    /* Based on the rules specified in the function prologue, the algorithm is as follows:
17321     *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
17322     *   if frA is a SNaN
17323     *     result = frA converted to QNaN
17324     *   else if frB is a SNaN
17325     *     result = frB converted to QNaN
17326     *   else if frB is a QNaN
17327     *     result = frA
17328     *   // One of frA or frB was a NaN in order for this function to be called, so
17329     *   // if we get to this point, we KNOW that frA must be a QNaN.
17330     *   else // frA is a QNaN
17331     *     result = frB
17332     *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
17333     */
17334 
17335 #define SNAN_MASK 0x0008000000000000ULL
17336    return
17337    IRExpr_ITE(mkexpr(frA_isSNaN),
17338               /* then: result = frA converted to QNaN */
17339               binop(Iop_Or64, mkexpr(frA_I64), mkU64(SNAN_MASK)),
17340               /* else:  if frB is a SNaN */
17341               IRExpr_ITE(mkexpr(frB_isSNaN),
17342                          /* then: result = frB converted to QNaN */
17343                          binop(Iop_Or64, mkexpr(frB_I64), mkU64(SNAN_MASK)),
17344                          /* else:  if frB is a QNaN */
17345                          IRExpr_ITE(mkexpr(frB_isQNaN),
17346                                     /* then: result = frA */
17347                                     mkexpr(frA_I64),
17348                                     /* else:  frA is a QNaN, so result = frB */
17349                                     mkexpr(frB_I64))));
17350 }
17351 
17352 /*
17353  * Helper function for get_max_min_fp.
17354  */
_get_maxmin_fp_cmp(IRTemp src1,IRTemp src2,Bool isMin)17355 static IRExpr * _get_maxmin_fp_cmp(IRTemp src1, IRTemp src2, Bool isMin)
17356 {
17357    IRTemp src1cmpsrc2 = get_fp_cmp_CR_val( binop( Iop_CmpF64,
17358                                                   unop( Iop_ReinterpI64asF64,
17359                                                         mkexpr( src1 ) ),
17360                                                   unop( Iop_ReinterpI64asF64,
17361                                                         mkexpr( src2 ) ) ) );
17362 
17363    return IRExpr_ITE( binop( Iop_CmpEQ32,
17364                                mkexpr( src1cmpsrc2 ),
17365                                mkU32( isMin ? PPC_CMP_LT : PPC_CMP_GT ) ),
17366                       /* then: use src1 */
17367                       mkexpr( src1 ),
17368                       /* else: use src2 */
17369                       mkexpr( src2 ) );
17370 }
17371 
17372 /*
17373  * Helper function for "Maximum/Minimum Double Precision" operations.
17374  * Arguments: frA and frb are Ity_I64
17375  * Returns Ity_I64 IRExpr that answers the "which is Maxiumum/Minimum" question
17376  */
get_max_min_fp(IRTemp frA_I64,IRTemp frB_I64,Bool isMin)17377 static IRExpr * get_max_min_fp(IRTemp frA_I64, IRTemp frB_I64, Bool isMin)
17378 {
17379    /* There are three special cases where get_fp_cmp_CR_val is not helpful
17380     * for ascertaining the maximum between two doubles:
17381     *   1. The max/min of +0 and -0 is +0.
17382     *   2. The max/min of a QNaN and any value is that value.
17383     *   3. The max/min of any value and an SNaN is that SNaN converted to a QNaN.
17384     * We perform the check for [+/-]0 here in this function and use the
17385     * _get_maxmin_fp_NaN helper for the two NaN cases; otherwise we call _get_maxmin_fp_cmp
17386     * to do the standard comparison function.
17387     */
17388    IRTemp anyNaN = newTemp(Ity_I1);
17389    IRTemp frA_isZero = newTemp(Ity_I1);
17390    IRTemp frB_isZero = newTemp(Ity_I1);
17391    assign( frA_isZero, is_Zero( Ity_I64, frA_I64 ) );
17392    assign( frB_isZero, is_Zero( Ity_I64, frB_I64 ) );
17393    assign( anyNaN, mkOR1( is_NaN( Ity_I64, frA_I64 ),
17394                           is_NaN(Ity_I64, frB_I64 ) ) );
17395 #define MINUS_ZERO 0x8000000000000000ULL
17396 
17397    return IRExpr_ITE( /* If both arguments are zero . . . */
17398                      mkAND1( mkexpr( frA_isZero ), mkexpr( frB_isZero ) ),
17399                      /* then: if frA is -0 and isMin==True, return -0;
17400                       *     else if frA is +0 and isMin==False; return +0;
17401                       *     otherwise, simply return frB. */
17402                      IRExpr_ITE( binop( Iop_CmpEQ32,
17403                                         unop( Iop_64HIto32,
17404                                               mkexpr( frA_I64 ) ),
17405                                         mkU32( isMin ? 0x80000000 : 0 ) ),
17406                                  mkU64( isMin ? MINUS_ZERO : 0ULL ),
17407                                  mkexpr( frB_I64 ) ),
17408                      /* else: check if either input is a NaN*/
17409                      IRExpr_ITE( mkexpr( anyNaN ),
17410                                  /* then: use "NaN helper" */
17411                                  _get_maxmin_fp_NaN( frA_I64, frB_I64 ),
17412                                  /* else: use "comparison helper" */
17413                                  _get_maxmin_fp_cmp( frB_I64, frA_I64, isMin ) ));
17414 }
17415 
_get_vsx_rdpi_suffix(UInt opc2)17416 static const HChar * _get_vsx_rdpi_suffix(UInt opc2)
17417 {
17418    switch (opc2 & 0x7F) {
17419       case 0x72:
17420          return "m";
17421       case 0x52:
17422          return "p";
17423       case 0x56:
17424          return "c";
17425       case 0x32:
17426          return "z";
17427       case 0x12:
17428          return "";
17429 
17430       default: // Impossible to get here
17431          vex_printf("Unrecognized opcode %x\n", opc2);
17432          vpanic("_get_vsx_rdpi_suffix(ppc)(opc2)");
17433    }
17434 }
17435 
17436 /*
17437  * Helper function for vector/scalar double precision fp round to integer instructions.
17438  */
_do_vsx_fp_roundToInt(IRTemp frB_I64,UInt opc2)17439 static IRExpr * _do_vsx_fp_roundToInt(IRTemp frB_I64, UInt opc2)
17440 {
17441 
17442    /* The same rules apply for x{s|v}rdpi{m|p|c|z} as for floating point round operations (fri{m|n|p|z}). */
17443    IRTemp frB = newTemp(Ity_F64);
17444    IRTemp frD = newTemp(Ity_F64);
17445    IRTemp intermediateResult = newTemp(Ity_I64);
17446    IRTemp is_SNAN = newTemp(Ity_I1);
17447    IRExpr * hi32;
17448    IRExpr * rxpi_rm;
17449    switch (opc2 & 0x7F) {
17450       case 0x72:
17451          rxpi_rm = mkU32(Irrm_NegINF);
17452          break;
17453       case 0x52:
17454          rxpi_rm = mkU32(Irrm_PosINF);
17455          break;
17456       case 0x56:
17457          rxpi_rm = get_IR_roundingmode();
17458          break;
17459       case 0x32:
17460          rxpi_rm = mkU32(Irrm_ZERO);
17461          break;
17462       case 0x12:
17463          rxpi_rm = mkU32(Irrm_NEAREST);
17464          break;
17465 
17466       default: // Impossible to get here
17467          vex_printf("Unrecognized opcode %x\n", opc2);
17468          vpanic("_do_vsx_fp_roundToInt(ppc)(opc2)");
17469    }
17470    assign(frB, unop(Iop_ReinterpI64asF64, mkexpr(frB_I64)));
17471    assign( intermediateResult,
17472            binop( Iop_F64toI64S, rxpi_rm,
17473                   mkexpr( frB ) ) );
17474 
17475    /* don't use the rounded integer if frB is outside -9e18..9e18 */
17476    /* F64 has only log10(2**52) significant digits anyway */
17477    /* need to preserve sign of zero */
17478    /*   frD = (fabs(frB) > 9e18) ? frB :
17479             (sign(frB)) ? -fabs((double)intermediateResult) : (double)intermediateResult  */
17480    assign( frD,
17481            IRExpr_ITE(
17482               binop( Iop_CmpNE8,
17483                      unop( Iop_32to8,
17484                            binop( Iop_CmpF64,
17485                                   IRExpr_Const( IRConst_F64( 9e18 ) ),
17486                                   unop( Iop_AbsF64, mkexpr( frB ) ) ) ),
17487                      mkU8(0) ),
17488               mkexpr( frB ),
17489               IRExpr_ITE(
17490                  binop( Iop_CmpNE32,
17491                         binop( Iop_Shr32,
17492                                unop( Iop_64HIto32,
17493                                      mkexpr( frB_I64 ) ),
17494                                mkU8( 31 ) ),
17495                         mkU32(0) ),
17496                  unop( Iop_NegF64,
17497                        unop( Iop_AbsF64,
17498                              binop( Iop_I64StoF64,
17499                                     mkU32( 0 ),
17500                                     mkexpr( intermediateResult ) ) ) ),
17501                  binop( Iop_I64StoF64,
17502                         mkU32( 0 ),
17503                         mkexpr( intermediateResult ) )
17504               )
17505            )
17506    );
17507 
17508    /* See Appendix "Floating-Point Round to Integer Model" in ISA doc.
17509     * If frB is a SNAN, then frD <- frB, with bit 12 set to '1'.
17510     */
17511 #define SNAN_MASK 0x0008000000000000ULL
17512    hi32 = unop( Iop_64HIto32, mkexpr(frB_I64) );
17513    assign( is_SNAN,
17514            mkAND1( is_NaN( Ity_I64, frB_I64 ),
17515                    binop( Iop_CmpEQ32,
17516                           binop( Iop_And32, hi32, mkU32( 0x00080000 ) ),
17517                           mkU32( 0 ) ) ) );
17518 
17519    return IRExpr_ITE( mkexpr( is_SNAN ),
17520                         unop( Iop_ReinterpI64asF64,
17521                               binop( Iop_Xor64,
17522                                      mkU64( SNAN_MASK ),
17523                                      mkexpr( frB_I64 ) ) ),
17524                       mkexpr( frD ));
17525 }
17526 
17527 /*
17528  * Miscellaneous VSX vector instructions
17529  */
17530 static Bool
dis_vxv_misc(UInt theInstr,UInt opc2)17531 dis_vxv_misc ( UInt theInstr, UInt opc2 )
17532 {
17533    /* XX3-Form */
17534    UChar opc1 = ifieldOPC( theInstr );
17535    UChar XT = ifieldRegXT( theInstr );
17536    UChar XB = ifieldRegXB( theInstr );
17537 
17538    if (opc1 != 0x3C) {
17539       vex_printf( "dis_vxv_misc(ppc)(instr)\n" );
17540       return False;
17541    }
17542 
17543    switch (opc2) {
17544       case 0x1B4:  // xvredp (VSX Vector Reciprocal Estimate Double-Precision)
17545       case 0x194:  // xvrsqrtedp (VSX Vector Reciprocal Square Root Estimate
17546                    //             Double-Precision)
17547       {
17548          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
17549          IRExpr* rm  = get_IR_roundingmode();
17550          IRTemp frB = newTemp(Ity_I64);
17551          IRTemp frB2 = newTemp(Ity_I64);
17552          Bool redp = opc2 == 0x1B4;
17553          IRTemp sqrtHi = newTemp(Ity_F64);
17554          IRTemp sqrtLo = newTemp(Ity_F64);
17555          assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
17556          assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
17557 
17558          DIP("%s v%d,v%d\n", redp ? "xvredp" : "xvrsqrtedp", XT, XB);
17559 
17560          if (!redp) {
17561             assign( sqrtHi,
17562                     binop( Iop_SqrtF64,
17563                            rm,
17564                            unop( Iop_ReinterpI64asF64, mkexpr( frB ) ) ) );
17565             assign( sqrtLo,
17566                     binop( Iop_SqrtF64,
17567                            rm,
17568                            unop( Iop_ReinterpI64asF64, mkexpr( frB2 ) ) ) );
17569          }
17570          putVSReg( XT,
17571                    binop( Iop_64HLtoV128,
17572                           unop( Iop_ReinterpF64asI64,
17573                                 triop( Iop_DivF64,
17574                                        rm,
17575                                        ieee_one,
17576                                        redp ? unop( Iop_ReinterpI64asF64,
17577                                                     mkexpr( frB ) )
17578                                             : mkexpr( sqrtHi ) ) ),
17579                           unop( Iop_ReinterpF64asI64,
17580                                 triop( Iop_DivF64,
17581                                        rm,
17582                                        ieee_one,
17583                                        redp ? unop( Iop_ReinterpI64asF64,
17584                                                     mkexpr( frB2 ) )
17585                                             : mkexpr( sqrtLo ) ) ) ) );
17586          break;
17587 
17588       }
17589       case 0x134: // xvresp (VSX Vector Reciprocal Estimate Single-Precision)
17590       case 0x114: // xvrsqrtesp (VSX Vector Reciprocal Square Root Estimate Single-Precision)
17591       {
17592          IRTemp b3, b2, b1, b0;
17593          IRTemp res0 = newTemp(Ity_I32);
17594          IRTemp res1 = newTemp(Ity_I32);
17595          IRTemp res2 = newTemp(Ity_I32);
17596          IRTemp res3 = newTemp(Ity_I32);
17597          IRTemp sqrt3 = newTemp(Ity_F64);
17598          IRTemp sqrt2 = newTemp(Ity_F64);
17599          IRTemp sqrt1 = newTemp(Ity_F64);
17600          IRTemp sqrt0 = newTemp(Ity_F64);
17601          IRExpr* rm  = get_IR_roundingmode();
17602          Bool resp = opc2 == 0x134;
17603 
17604          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
17605 
17606          b3 = b2 = b1 = b0 = IRTemp_INVALID;
17607          DIP("%s v%d,v%d\n", resp ? "xvresp" : "xvrsqrtesp", XT, XB);
17608          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
17609 
17610          if (!resp) {
17611             assign( sqrt3, binop( Iop_SqrtF64, rm, mkexpr( b3 ) ) );
17612             assign( sqrt2, binop( Iop_SqrtF64, rm, mkexpr( b2 ) ) );
17613             assign( sqrt1, binop( Iop_SqrtF64, rm, mkexpr( b1 ) ) );
17614             assign( sqrt0, binop( Iop_SqrtF64, rm, mkexpr( b0 ) ) );
17615          }
17616 
17617          assign( res0,
17618                  unop( Iop_ReinterpF32asI32,
17619                        unop( Iop_TruncF64asF32,
17620                              triop( Iop_DivF64r32,
17621                                     rm,
17622                                     ieee_one,
17623                                     resp ? mkexpr( b0 ) : mkexpr( sqrt0 ) ) ) ) );
17624          assign( res1,
17625                  unop( Iop_ReinterpF32asI32,
17626                        unop( Iop_TruncF64asF32,
17627                              triop( Iop_DivF64r32,
17628                                     rm,
17629                                     ieee_one,
17630                                     resp ? mkexpr( b1 ) : mkexpr( sqrt1 ) ) ) ) );
17631          assign( res2,
17632                  unop( Iop_ReinterpF32asI32,
17633                        unop( Iop_TruncF64asF32,
17634                              triop( Iop_DivF64r32,
17635                                     rm,
17636                                     ieee_one,
17637                                     resp ? mkexpr( b2 ) : mkexpr( sqrt2 ) ) ) ) );
17638          assign( res3,
17639                  unop( Iop_ReinterpF32asI32,
17640                        unop( Iop_TruncF64asF32,
17641                              triop( Iop_DivF64r32,
17642                                     rm,
17643                                     ieee_one,
17644                                     resp ? mkexpr( b3 ) : mkexpr( sqrt3 ) ) ) ) );
17645          putVSReg( XT,
17646                    binop( Iop_64HLtoV128,
17647                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
17648                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
17649          break;
17650       }
17651       case 0x300: // xvmaxsp (VSX Vector Maximum Single-Precision)
17652       case 0x320: // xvminsp (VSX Vector Minimum Single-Precision)
17653       {
17654          UChar XA = ifieldRegXA( theInstr );
17655          IRTemp a3, a2, a1, a0;
17656          IRTemp b3, b2, b1, b0;
17657          IRTemp res0 = newTemp( Ity_I32 );
17658          IRTemp res1 = newTemp( Ity_I32 );
17659          IRTemp res2 = newTemp( Ity_I32 );
17660          IRTemp res3 = newTemp( Ity_I32 );
17661          IRTemp a0_I64 = newTemp( Ity_I64 );
17662          IRTemp a1_I64 = newTemp( Ity_I64 );
17663          IRTemp a2_I64 = newTemp( Ity_I64 );
17664          IRTemp a3_I64 = newTemp( Ity_I64 );
17665          IRTemp b0_I64 = newTemp( Ity_I64 );
17666          IRTemp b1_I64 = newTemp( Ity_I64 );
17667          IRTemp b2_I64 = newTemp( Ity_I64 );
17668          IRTemp b3_I64 = newTemp( Ity_I64 );
17669 
17670          Bool isMin = opc2 == 0x320 ? True : False;
17671 
17672          a3 = a2 = a1 = a0 = IRTemp_INVALID;
17673          b3 = b2 = b1 = b0 = IRTemp_INVALID;
17674          DIP("%s v%d,v%d v%d\n", isMin ? "xvminsp" : "xvmaxsp", XT, XA, XB);
17675          breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
17676          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
17677          assign( a0_I64, unop( Iop_ReinterpF64asI64, mkexpr( a0 ) ) );
17678          assign( b0_I64, unop( Iop_ReinterpF64asI64, mkexpr( b0 ) ) );
17679          assign( a1_I64, unop( Iop_ReinterpF64asI64, mkexpr( a1 ) ) );
17680          assign( b1_I64, unop( Iop_ReinterpF64asI64, mkexpr( b1 ) ) );
17681          assign( a2_I64, unop( Iop_ReinterpF64asI64, mkexpr( a2 ) ) );
17682          assign( b2_I64, unop( Iop_ReinterpF64asI64, mkexpr( b2 ) ) );
17683          assign( a3_I64, unop( Iop_ReinterpF64asI64, mkexpr( a3 ) ) );
17684          assign( b3_I64, unop( Iop_ReinterpF64asI64, mkexpr( b3 ) ) );
17685          assign( res0,
17686                  unop( Iop_ReinterpF32asI32,
17687                        unop( Iop_TruncF64asF32,
17688                              unop( Iop_ReinterpI64asF64,
17689                                    get_max_min_fp( a0_I64, b0_I64, isMin ) ) ) ) );
17690          assign( res1,
17691                  unop( Iop_ReinterpF32asI32,
17692                        unop( Iop_TruncF64asF32,
17693                              unop( Iop_ReinterpI64asF64,
17694                                    get_max_min_fp( a1_I64, b1_I64, isMin ) ) ) ) );
17695          assign( res2,
17696                  unop( Iop_ReinterpF32asI32,
17697                        unop( Iop_TruncF64asF32,
17698                              unop( Iop_ReinterpI64asF64,
17699                                    get_max_min_fp( a2_I64, b2_I64, isMin ) ) ) ) );
17700          assign( res3,
17701                  unop( Iop_ReinterpF32asI32,
17702                        unop( Iop_TruncF64asF32,
17703                              unop( Iop_ReinterpI64asF64,
17704                                    get_max_min_fp( a3_I64, b3_I64, isMin ) ) ) ) );
17705          putVSReg( XT,
17706                    binop( Iop_64HLtoV128,
17707                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
17708                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
17709          break;
17710       }
17711       case 0x380: // xvmaxdp (VSX Vector Maximum Double-Precision)
17712       case 0x3A0: // xvmindp (VSX Vector Minimum Double-Precision)
17713       {
17714          UChar XA = ifieldRegXA( theInstr );
17715          IRTemp frA = newTemp(Ity_I64);
17716          IRTemp frB = newTemp(Ity_I64);
17717          IRTemp frA2 = newTemp(Ity_I64);
17718          IRTemp frB2 = newTemp(Ity_I64);
17719          Bool isMin = opc2 == 0x3A0 ? True : False;
17720 
17721          assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
17722          assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
17723          assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
17724          assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
17725          DIP("%s v%d,v%d v%d\n", isMin ? "xvmindp" : "xvmaxdp", XT, XA, XB);
17726          putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), get_max_min_fp(frA2, frB2, isMin) ) );
17727 
17728          break;
17729       }
17730       case 0x3c0: // xvcpsgndp (VSX Vector Copy Sign Double-Precision)
17731       {
17732          UChar XA = ifieldRegXA( theInstr );
17733          IRTemp frA = newTemp(Ity_I64);
17734          IRTemp frB = newTemp(Ity_I64);
17735          IRTemp frA2 = newTemp(Ity_I64);
17736          IRTemp frB2 = newTemp(Ity_I64);
17737          assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
17738          assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
17739          assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
17740          assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
17741 
17742          DIP("xvcpsgndp v%d,v%d,v%d\n", XT, XA, XB);
17743          putVSReg( XT,
17744                    binop( Iop_64HLtoV128,
17745                           binop( Iop_Or64,
17746                                  binop( Iop_And64,
17747                                         mkexpr( frA ),
17748                                         mkU64( SIGN_BIT ) ),
17749                                  binop( Iop_And64,
17750                                         mkexpr( frB ),
17751                                         mkU64( SIGN_MASK ) ) ),
17752                           binop( Iop_Or64,
17753                                  binop( Iop_And64,
17754                                         mkexpr( frA2 ),
17755                                         mkU64( SIGN_BIT ) ),
17756                                  binop( Iop_And64,
17757                                         mkexpr( frB2 ),
17758                                         mkU64( SIGN_MASK ) ) ) ) );
17759          break;
17760       }
17761       case 0x340: // xvcpsgnsp
17762       {
17763          UChar XA = ifieldRegXA( theInstr );
17764          IRTemp a3_I64, a2_I64, a1_I64, a0_I64;
17765          IRTemp b3_I64, b2_I64, b1_I64, b0_I64;
17766          IRTemp resHi = newTemp(Ity_I64);
17767          IRTemp resLo = newTemp(Ity_I64);
17768 
17769          a3_I64 = a2_I64 = a1_I64 = a0_I64 = IRTemp_INVALID;
17770          b3_I64 = b2_I64 = b1_I64 = b0_I64 = IRTemp_INVALID;
17771          DIP("xvcpsgnsp v%d,v%d v%d\n",XT, XA, XB);
17772          breakV128to4x64U( getVSReg( XA ), &a3_I64, &a2_I64, &a1_I64, &a0_I64 );
17773          breakV128to4x64U( getVSReg( XB ), &b3_I64, &b2_I64, &b1_I64, &b0_I64 );
17774 
17775          assign( resHi,
17776                  binop( Iop_32HLto64,
17777                         binop( Iop_Or32,
17778                                binop( Iop_And32,
17779                                       unop(Iop_64to32, mkexpr( a3_I64 ) ),
17780                                       mkU32( SIGN_BIT32 ) ),
17781                                binop( Iop_And32,
17782                                       unop(Iop_64to32, mkexpr( b3_I64 ) ),
17783                                       mkU32( SIGN_MASK32) ) ),
17784 
17785                         binop( Iop_Or32,
17786                                binop( Iop_And32,
17787                                       unop(Iop_64to32, mkexpr( a2_I64 ) ),
17788                                       mkU32( SIGN_BIT32 ) ),
17789                                binop( Iop_And32,
17790                                       unop(Iop_64to32, mkexpr( b2_I64 ) ),
17791                                       mkU32( SIGN_MASK32 ) ) ) ) );
17792          assign( resLo,
17793                  binop( Iop_32HLto64,
17794                         binop( Iop_Or32,
17795                                binop( Iop_And32,
17796                                       unop(Iop_64to32, mkexpr( a1_I64 ) ),
17797                                       mkU32( SIGN_BIT32 ) ),
17798                                binop( Iop_And32,
17799                                       unop(Iop_64to32, mkexpr( b1_I64 ) ),
17800                                       mkU32( SIGN_MASK32 ) ) ),
17801 
17802                         binop( Iop_Or32,
17803                                binop( Iop_And32,
17804                                       unop(Iop_64to32, mkexpr( a0_I64 ) ),
17805                                       mkU32( SIGN_BIT32 ) ),
17806                                binop( Iop_And32,
17807                                       unop(Iop_64to32, mkexpr( b0_I64 ) ),
17808                                       mkU32( SIGN_MASK32 ) ) ) ) );
17809          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( resHi ), mkexpr( resLo ) ) );
17810          break;
17811       }
17812       case 0x3B2: // xvabsdp (VSX Vector Absolute Value Double-Precision)
17813       case 0x3D2: // xvnabsdp VSX Vector Negative Absolute Value Double-Precision)
17814       {
17815          IRTemp frB = newTemp(Ity_F64);
17816          IRTemp frB2 = newTemp(Ity_F64);
17817          IRTemp abs_resultHi = newTemp(Ity_F64);
17818          IRTemp abs_resultLo = newTemp(Ity_F64);
17819          Bool make_negative = (opc2 == 0x3D2) ? True : False;
17820          assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
17821          assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
17822 
17823          DIP("xv%sabsdp v%d,v%d\n", make_negative ? "n" : "", XT, XB);
17824          if (make_negative) {
17825             assign(abs_resultHi, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB ) ) ) );
17826             assign(abs_resultLo, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB2 ) ) ) );
17827 
17828          } else {
17829             assign(abs_resultHi, unop( Iop_AbsF64, mkexpr( frB ) ) );
17830             assign(abs_resultLo, unop( Iop_AbsF64, mkexpr( frB2 ) ) );
17831          }
17832          putVSReg( XT, binop( Iop_64HLtoV128,
17833                               unop( Iop_ReinterpF64asI64, mkexpr( abs_resultHi ) ),
17834                               unop( Iop_ReinterpF64asI64, mkexpr( abs_resultLo ) ) ) );
17835          break;
17836       }
17837       case 0x332: // xvabssp (VSX Vector Absolute Value Single-Precision)
17838       case 0x352: // xvnabssp (VSX Vector Negative Absolute Value Single-Precision)
17839       {
17840          /*
17841           * The Iop_AbsF32 IRop is not implemented for ppc64 since, up until introduction
17842           * of xvabssp, there has not been an abs(sp) type of instruction.  But since emulation
17843           * of this function is so easy using shifts, I choose to emulate this instruction that
17844           * way versus a native instruction method of implementation.
17845           */
17846          Bool make_negative = (opc2 == 0x352) ? True : False;
17847          IRTemp shiftVector = newTemp(Ity_V128);
17848          IRTemp absVal_vector = newTemp(Ity_V128);
17849          assign( shiftVector,
17850                  binop( Iop_64HLtoV128,
17851                         binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ),
17852                         binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ) ) );
17853          assign( absVal_vector,
17854                    binop( Iop_Shr32x4,
17855                           binop( Iop_Shl32x4,
17856                                  getVSReg( XB ),
17857                                  mkexpr( shiftVector ) ),
17858                           mkexpr( shiftVector ) ) );
17859          if (make_negative) {
17860             IRTemp signBit_vector = newTemp(Ity_V128);
17861             assign( signBit_vector,
17862                     binop( Iop_64HLtoV128,
17863                            binop( Iop_32HLto64,
17864                                   mkU32( 0x80000000 ),
17865                                   mkU32( 0x80000000 ) ),
17866                            binop( Iop_32HLto64,
17867                                   mkU32( 0x80000000 ),
17868                                   mkU32( 0x80000000 ) ) ) );
17869             putVSReg( XT,
17870                       binop( Iop_OrV128,
17871                              mkexpr( absVal_vector ),
17872                              mkexpr( signBit_vector ) ) );
17873          } else {
17874             putVSReg( XT, mkexpr( absVal_vector ) );
17875          }
17876          break;
17877       }
17878       case 0x372: // xvnegsp (VSX Vector Negate Single-Precision)
17879       {
17880          IRTemp B0 = newTemp(Ity_I32);
17881          IRTemp B1 = newTemp(Ity_I32);
17882          IRTemp B2 = newTemp(Ity_I32);
17883          IRTemp B3 = newTemp(Ity_I32);
17884 
17885          DIP("xvnegsp v%d,v%d\n",  XT, XB);
17886 
17887 	 /* Don't support NegF32, so just XOR the sign bit in the int value */
17888          assign(B0, unop( Iop_64HIto32,
17889 			  unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
17890          assign(B1, unop( Iop_64to32,
17891 			  unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
17892          assign(B2, unop( Iop_64HIto32,
17893 			  unop( Iop_V128to64, getVSReg( XB ) ) ) );
17894          assign(B3, unop( Iop_64to32,
17895 			  unop( Iop_V128to64, getVSReg( XB ) ) ) );
17896 
17897          putVSReg( XT,
17898 		   binop( Iop_64HLtoV128,
17899 			  binop( Iop_32HLto64,
17900 				 binop( Iop_Xor32, mkexpr( B0 ), mkU32( 0x80000000 ) ),
17901 				 binop( Iop_Xor32, mkexpr( B1 ), mkU32( 0x80000000 ) ) ),
17902 			  binop( Iop_32HLto64,
17903 				 binop( Iop_Xor32, mkexpr( B2 ), mkU32( 0x80000000 ) ),
17904 				 binop( Iop_Xor32, mkexpr( B3 ), mkU32( 0x80000000 ) ) ) ) );
17905          break;
17906       }
17907       case 0x3F2: // xvnegdp (VSX Vector Negate Double-Precision)
17908       {
17909          IRTemp frB = newTemp(Ity_F64);
17910          IRTemp frB2 = newTemp(Ity_F64);
17911          assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
17912          assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
17913          DIP("xvnegdp v%d,v%d\n",  XT, XB);
17914          putVSReg( XT,
17915                    binop( Iop_64HLtoV128,
17916                           unop( Iop_ReinterpF64asI64,
17917                                 unop( Iop_NegF64, mkexpr( frB ) ) ),
17918                           unop( Iop_ReinterpF64asI64,
17919                                 unop( Iop_NegF64, mkexpr( frB2 ) ) ) ) );
17920          break;
17921       }
17922       case 0x192: // xvrdpi  (VSX Vector Round to Double-Precision Integer using round toward Nearest Away)
17923       case 0x1D6: // xvrdpic (VSX Vector Round to Double-Precision Integer using Current rounding mode)
17924       case 0x1F2: // xvrdpim (VSX Vector Round to Double-Precision Integer using round toward -Infinity)
17925       case 0x1D2: // xvrdpip (VSX Vector Round to Double-Precision Integer using round toward +Infinity)
17926       case 0x1B2: // xvrdpiz (VSX Vector Round to Double-Precision Integer using round toward Zero)
17927       {
17928          IRTemp frBHi_I64 = newTemp(Ity_I64);
17929          IRTemp frBLo_I64 = newTemp(Ity_I64);
17930          IRExpr * frD_fp_roundHi = NULL;
17931          IRExpr * frD_fp_roundLo = NULL;
17932 
17933          assign( frBHi_I64, unop( Iop_V128HIto64, getVSReg( XB ) ) );
17934          frD_fp_roundHi = _do_vsx_fp_roundToInt(frBHi_I64, opc2);
17935          assign( frBLo_I64, unop( Iop_V128to64, getVSReg( XB ) ) );
17936          frD_fp_roundLo = _do_vsx_fp_roundToInt(frBLo_I64, opc2);
17937 
17938          DIP("xvrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), XT, XB);
17939          putVSReg( XT,
17940                    binop( Iop_64HLtoV128,
17941                           unop( Iop_ReinterpF64asI64, frD_fp_roundHi ),
17942                           unop( Iop_ReinterpF64asI64, frD_fp_roundLo ) ) );
17943          break;
17944       }
17945       case 0x112: // xvrspi  (VSX Vector Round to Single-Precision Integer using round toward Nearest Away)
17946       case 0x156: // xvrspic (VSX Vector Round to SinglePrecision Integer using Current rounding mode)
17947       case 0x172: // xvrspim (VSX Vector Round to SinglePrecision Integer using round toward -Infinity)
17948       case 0x152: // xvrspip (VSX Vector Round to SinglePrecision Integer using round toward +Infinity)
17949       case 0x132: // xvrspiz (VSX Vector Round to SinglePrecision Integer using round toward Zero)
17950       {
17951          const HChar * insn_suffix = NULL;
17952          IROp op;
17953          if (opc2 != 0x156) {
17954             // Use pre-defined IRop's for vrfi{m|n|p|z}
17955             switch (opc2) {
17956                case 0x112:
17957                   insn_suffix = "";
17958                   op = Iop_RoundF32x4_RN;
17959                   break;
17960                case 0x172:
17961                   insn_suffix = "m";
17962                   op = Iop_RoundF32x4_RM;
17963                   break;
17964                case 0x152:
17965                   insn_suffix = "p";
17966                   op = Iop_RoundF32x4_RP;
17967                   break;
17968                case 0x132:
17969                   insn_suffix = "z";
17970                   op = Iop_RoundF32x4_RZ;
17971                   break;
17972 
17973                default:
17974                   vex_printf("Unrecognized opcode %x\n", opc2);
17975                   vpanic("dis_vxv_misc(ppc)(vrspi<x>)(opc2)\n");
17976             }
17977             DIP("xvrspi%s v%d,v%d\n", insn_suffix, XT, XB);
17978             putVSReg( XT, unop( op, getVSReg(XB) ) );
17979          } else {
17980             // Handle xvrspic.  Unfortunately there is no corresponding "vfric" instruction.
17981             IRExpr * frD_fp_roundb3, * frD_fp_roundb2, * frD_fp_roundb1, * frD_fp_roundb0;
17982             IRTemp b3_F64, b2_F64, b1_F64, b0_F64;
17983             IRTemp b3_I64 = newTemp(Ity_I64);
17984             IRTemp b2_I64 = newTemp(Ity_I64);
17985             IRTemp b1_I64 = newTemp(Ity_I64);
17986             IRTemp b0_I64 = newTemp(Ity_I64);
17987 
17988             b3_F64 = b2_F64 = b1_F64 = b0_F64 = IRTemp_INVALID;
17989             frD_fp_roundb3 = frD_fp_roundb2 = frD_fp_roundb1 = frD_fp_roundb0 = NULL;
17990             breakV128to4xF64( getVSReg(XB), &b3_F64, &b2_F64, &b1_F64, &b0_F64);
17991             assign(b3_I64, unop(Iop_ReinterpF64asI64, mkexpr(b3_F64)));
17992             assign(b2_I64, unop(Iop_ReinterpF64asI64, mkexpr(b2_F64)));
17993             assign(b1_I64, unop(Iop_ReinterpF64asI64, mkexpr(b1_F64)));
17994             assign(b0_I64, unop(Iop_ReinterpF64asI64, mkexpr(b0_F64)));
17995             frD_fp_roundb3 = unop(Iop_TruncF64asF32,
17996                                   _do_vsx_fp_roundToInt(b3_I64, opc2));
17997             frD_fp_roundb2 = unop(Iop_TruncF64asF32,
17998                                   _do_vsx_fp_roundToInt(b2_I64, opc2));
17999             frD_fp_roundb1 = unop(Iop_TruncF64asF32,
18000                                   _do_vsx_fp_roundToInt(b1_I64, opc2));
18001             frD_fp_roundb0 = unop(Iop_TruncF64asF32,
18002                                   _do_vsx_fp_roundToInt(b0_I64, opc2));
18003             DIP("xvrspic v%d,v%d\n", XT, XB);
18004             putVSReg( XT,
18005                       binop( Iop_64HLtoV128,
18006                              binop( Iop_32HLto64,
18007                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb3 ),
18008                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb2 ) ),
18009                              binop( Iop_32HLto64,
18010                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb1 ),
18011                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb0 ) ) ) );
18012          }
18013          break;
18014       }
18015 
18016       default:
18017          vex_printf( "dis_vxv_misc(ppc)(opc2)\n" );
18018          return False;
18019    }
18020    return True;
18021 }
18022 
18023 
18024 /*
18025  * VSX Scalar Floating Point Arithmetic Instructions
18026  */
18027 static Bool
dis_vxs_arith(UInt theInstr,UInt opc2)18028 dis_vxs_arith ( UInt theInstr, UInt opc2 )
18029 {
18030    /* XX3-Form */
18031    UChar opc1 = ifieldOPC( theInstr );
18032    UChar XT = ifieldRegXT( theInstr );
18033    UChar XA = ifieldRegXA( theInstr );
18034    UChar XB = ifieldRegXB( theInstr );
18035    IRExpr* rm = get_IR_roundingmode();
18036    IRTemp frA = newTemp(Ity_F64);
18037    IRTemp frB = newTemp(Ity_F64);
18038 
18039    if (opc1 != 0x3C) {
18040       vex_printf( "dis_vxs_arith(ppc)(instr)\n" );
18041       return False;
18042    }
18043 
18044    assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
18045    assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
18046 
18047    /* For all the VSX sclar arithmetic instructions, the contents of doubleword element 1
18048     * of VSX[XT] are undefined after the operation; therefore, we can simply set
18049     * element to zero where it makes sense to do so.
18050     */
18051    switch (opc2) {
18052       case 0x000: // xsaddsp  (VSX Scalar Add Single-Precision)
18053          DIP("xsaddsp v%d,v%d,v%d\n", XT, XA, XB);
18054          putVSReg( XT, binop( Iop_64HLtoV128,
18055                               unop( Iop_ReinterpF64asI64,
18056                                     binop( Iop_RoundF64toF32, rm,
18057                                            triop( Iop_AddF64, rm,
18058                                                   mkexpr( frA ),
18059                                                   mkexpr( frB ) ) ) ),
18060                               mkU64( 0 ) ) );
18061          break;
18062       case 0x020: // xssubsp  (VSX Scalar Subtract Single-Precision)
18063          DIP("xssubsp v%d,v%d,v%d\n", XT, XA, XB);
18064          putVSReg( XT, binop( Iop_64HLtoV128,
18065                               unop( Iop_ReinterpF64asI64,
18066                                     binop( Iop_RoundF64toF32, rm,
18067                                            triop( Iop_SubF64, rm,
18068                                                   mkexpr( frA ),
18069                                                   mkexpr( frB ) ) ) ),
18070                               mkU64( 0 ) ) );
18071          break;
18072       case 0x080: // xsadddp (VSX scalar add double-precision)
18073          DIP("xsadddp v%d,v%d,v%d\n", XT, XA, XB);
18074          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
18075                                                     triop( Iop_AddF64, rm,
18076                                                            mkexpr( frA ),
18077                                                            mkexpr( frB ) ) ),
18078                               mkU64( 0 ) ) );
18079          break;
18080       case 0x060: // xsdivsp (VSX scalar divide single-precision)
18081          DIP("xsdivsp v%d,v%d,v%d\n", XT, XA, XB);
18082          putVSReg( XT, binop( Iop_64HLtoV128,
18083                               unop( Iop_ReinterpF64asI64,
18084                                     binop( Iop_RoundF64toF32, rm,
18085                                            triop( Iop_DivF64, rm,
18086                                                   mkexpr( frA ),
18087                                                   mkexpr( frB ) ) ) ),
18088                                mkU64( 0 ) ) );
18089          break;
18090       case 0x0E0: // xsdivdp (VSX scalar divide double-precision)
18091          DIP("xsdivdp v%d,v%d,v%d\n", XT, XA, XB);
18092          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
18093                                                     triop( Iop_DivF64, rm,
18094                                                            mkexpr( frA ),
18095                                                            mkexpr( frB ) ) ),
18096                               mkU64( 0 ) ) );
18097          break;
18098       case 0x004: case 0x024: /* xsmaddasp, xsmaddmsp (VSX scalar multiply-add
18099                                * single-precision)
18100                                */
18101       {
18102          IRTemp frT = newTemp(Ity_F64);
18103          Bool mdp = opc2 == 0x024;
18104          DIP("xsmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
18105          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
18106                                                         getVSReg( XT ) ) ) );
18107          putVSReg( XT,
18108                    binop( Iop_64HLtoV128,
18109                           unop( Iop_ReinterpF64asI64,
18110                                 binop( Iop_RoundF64toF32, rm,
18111                                        qop( Iop_MAddF64, rm,
18112                                             mkexpr( frA ),
18113                                             mkexpr( mdp ? frT : frB ),
18114                                             mkexpr( mdp ? frB : frT ) ) ) ),
18115                           mkU64( 0 ) ) );
18116          break;
18117       }
18118       case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp (VSX scalar multiply-add double-precision)
18119       {
18120          IRTemp frT = newTemp(Ity_F64);
18121          Bool mdp = opc2 == 0x0A4;
18122          DIP("xsmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
18123          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
18124                                                         getVSReg( XT ) ) ) );
18125          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
18126                                                     qop( Iop_MAddF64, rm,
18127                                                          mkexpr( frA ),
18128                                                          mkexpr( mdp ? frT : frB ),
18129                                                          mkexpr( mdp ? frB : frT ) ) ),
18130                               mkU64( 0 ) ) );
18131          break;
18132       }
18133       case 0x044: case 0x064: /* xsmsubasp, xsmsubmsp (VSX scalar
18134                                * multiply-subtract single-precision)
18135 			       */
18136       {
18137          IRTemp frT = newTemp(Ity_F64);
18138          Bool mdp = opc2 == 0x064;
18139          DIP("xsmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
18140          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
18141                                                         getVSReg( XT ) ) ) );
18142          putVSReg( XT,
18143                    binop( Iop_64HLtoV128,
18144                           unop( Iop_ReinterpF64asI64,
18145                                 binop( Iop_RoundF64toF32, rm,
18146                                        qop( Iop_MSubF64, rm,
18147                                             mkexpr( frA ),
18148                                             mkexpr( mdp ? frT : frB ),
18149                                             mkexpr( mdp ? frB : frT ) ) ) ),
18150                           mkU64( 0 ) ) );
18151          break;
18152       }
18153       case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp (VSX scalar multiply-subtract double-precision)
18154       {
18155          IRTemp frT = newTemp(Ity_F64);
18156          Bool mdp = opc2 == 0x0E4;
18157          DIP("xsmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
18158          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
18159                                                         getVSReg( XT ) ) ) );
18160          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
18161                                                     qop( Iop_MSubF64, rm,
18162                                                          mkexpr( frA ),
18163                                                          mkexpr( mdp ? frT : frB ),
18164                                                          mkexpr( mdp ? frB : frT ) ) ),
18165                               mkU64( 0 ) ) );
18166          break;
18167       }
18168       case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp (VSX scalar multiply-add double-precision)
18169       {
18170          /* TODO: mpj -- Naturally, I expected to be able to leverage the implementation
18171           * of fnmadd and use pretty much the same code. However, that code has a bug in the
18172           * way it blindly negates the signbit, even if the floating point result is a NaN.
18173           * So, the TODO is to fix fnmadd (which I'll do in a different patch).
18174           * FIXED 7/1/2012: carll fnmadd and fnmsubs fixed to not negate sign
18175           * bit for NaN result.
18176           */
18177          Bool mdp = opc2 == 0x2A4;
18178          IRTemp frT = newTemp(Ity_F64);
18179          IRTemp maddResult = newTemp(Ity_I64);
18180 
18181          DIP("xsnmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
18182          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
18183                                                         getVSReg( XT ) ) ) );
18184          assign( maddResult, unop( Iop_ReinterpF64asI64, qop( Iop_MAddF64, rm,
18185                                                               mkexpr( frA ),
18186                                                               mkexpr( mdp ? frT : frB ),
18187                                                               mkexpr( mdp ? frB : frT ) ) ) );
18188 
18189          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(maddResult) ),
18190                               mkU64( 0 ) ) );
18191          break;
18192       }
18193       case 0x204: case 0x224: /* xsnmaddasp, xsnmaddmsp (VSX scalar
18194                                * multiply-add single-precision)
18195                                */
18196       {
18197          Bool mdp = opc2 == 0x224;
18198          IRTemp frT = newTemp(Ity_F64);
18199          IRTemp maddResult = newTemp(Ity_I64);
18200 
18201          DIP("xsnmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
18202          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
18203                                                         getVSReg( XT ) ) ) );
18204          assign( maddResult,
18205                  unop( Iop_ReinterpF64asI64,
18206                        binop( Iop_RoundF64toF32, rm,
18207                               qop( Iop_MAddF64, rm,
18208                                    mkexpr( frA ),
18209                                    mkexpr( mdp ? frT : frB ),
18210                                    mkexpr( mdp ? frB : frT ) ) ) ) );
18211 
18212          putVSReg( XT, binop( Iop_64HLtoV128,
18213                               mkexpr( getNegatedResult(maddResult) ),
18214                               mkU64( 0 ) ) );
18215          break;
18216       }
18217       case 0x244: case 0x264: /* xsnmsubasp, xsnmsubmsp (VSX Scalar Negative
18218                                * Multiply-Subtract Single-Precision)
18219                                */
18220       {
18221          IRTemp frT = newTemp(Ity_F64);
18222          Bool mdp = opc2 == 0x264;
18223          IRTemp msubResult = newTemp(Ity_I64);
18224 
18225          DIP("xsnmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
18226          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
18227                                                         getVSReg( XT ) ) ) );
18228          assign( msubResult,
18229                  unop( Iop_ReinterpF64asI64,
18230                        binop( Iop_RoundF64toF32, rm,
18231                               qop( Iop_MSubF64, rm,
18232                                    mkexpr( frA ),
18233                                    mkexpr( mdp ? frT : frB ),
18234                                    mkexpr( mdp ? frB : frT ) ) ) ) );
18235 
18236          putVSReg( XT, binop( Iop_64HLtoV128,
18237                               mkexpr( getNegatedResult(msubResult) ),
18238                               mkU64( 0 ) ) );
18239 
18240          break;
18241       }
18242 
18243       case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp (VSX Scalar Negative Multiply-Subtract Double-Precision)
18244       {
18245          IRTemp frT = newTemp(Ity_F64);
18246          Bool mdp = opc2 == 0x2E4;
18247          IRTemp msubResult = newTemp(Ity_I64);
18248 
18249          DIP("xsnmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
18250          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
18251                                                         getVSReg( XT ) ) ) );
18252          assign(msubResult, unop( Iop_ReinterpF64asI64,
18253                                       qop( Iop_MSubF64,
18254                                            rm,
18255                                            mkexpr( frA ),
18256                                            mkexpr( mdp ? frT : frB ),
18257                                            mkexpr( mdp ? frB : frT ) ) ));
18258 
18259          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(msubResult) ), mkU64( 0 ) ) );
18260 
18261          break;
18262       }
18263 
18264       case 0x040: // xsmulsp (VSX Scalar Multiply Single-Precision)
18265          DIP("xsmulsp v%d,v%d,v%d\n", XT, XA, XB);
18266          putVSReg( XT, binop( Iop_64HLtoV128,
18267                               unop( Iop_ReinterpF64asI64,
18268                                     binop( Iop_RoundF64toF32, rm,
18269                                            triop( Iop_MulF64, rm,
18270                                                    mkexpr( frA ),
18271                                                    mkexpr( frB ) ) ) ),
18272                               mkU64( 0 ) ) );
18273          break;
18274 
18275       case 0x0C0: // xsmuldp (VSX Scalar Multiply Double-Precision)
18276          DIP("xsmuldp v%d,v%d,v%d\n", XT, XA, XB);
18277          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
18278                                                     triop( Iop_MulF64, rm,
18279                                                            mkexpr( frA ),
18280                                                            mkexpr( frB ) ) ),
18281                               mkU64( 0 ) ) );
18282          break;
18283       case 0x0A0: // xssubdp (VSX Scalar Subtract Double-Precision)
18284          DIP("xssubdp v%d,v%d,v%d\n", XT, XA, XB);
18285          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
18286                                                     triop( Iop_SubF64, rm,
18287                                                            mkexpr( frA ),
18288                                                            mkexpr( frB ) ) ),
18289                               mkU64( 0 ) ) );
18290          break;
18291 
18292       case 0x016: // xssqrtsp (VSX Scalar Square Root Single-Precision)
18293          DIP("xssqrtsp v%d,v%d\n", XT, XB);
18294          putVSReg( XT,
18295                    binop( Iop_64HLtoV128,
18296                           unop( Iop_ReinterpF64asI64,
18297                                 binop( Iop_RoundF64toF32, rm,
18298                                        binop( Iop_SqrtF64, rm,
18299                                               mkexpr( frB ) ) ) ),
18300                           mkU64( 0 ) ) );
18301          break;
18302 
18303       case 0x096: // xssqrtdp (VSX Scalar Square Root Double-Precision)
18304          DIP("xssqrtdp v%d,v%d\n", XT, XB);
18305          putVSReg( XT,  binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
18306                                                      binop( Iop_SqrtF64, rm,
18307                                                             mkexpr( frB ) ) ),
18308                                mkU64( 0 ) ) );
18309          break;
18310 
18311       case 0x0F4: // xstdivdp (VSX Scalar Test for software Divide Double-Precision)
18312       {
18313          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
18314          IRTemp frA_I64 = newTemp(Ity_I64);
18315          IRTemp frB_I64 = newTemp(Ity_I64);
18316          DIP("xstdivdp crf%d,v%d,v%d\n", crfD, XA, XB);
18317          assign( frA_I64, unop( Iop_ReinterpF64asI64, mkexpr( frA ) ) );
18318          assign( frB_I64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
18319          putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
18320          break;
18321       }
18322       case 0x0D4: // xstsqrtdp (VSX Vector Test for software Square Root Double-Precision)
18323       {
18324          IRTemp frB_I64 = newTemp(Ity_I64);
18325          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
18326          IRTemp flags = newTemp(Ity_I32);
18327          IRTemp  fe_flag, fg_flag;
18328          fe_flag = fg_flag = IRTemp_INVALID;
18329          DIP("xstsqrtdp v%d,v%d\n", XT, XB);
18330          assign( frB_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
18331          do_fp_tsqrt(frB_I64, False /*not single precision*/, &fe_flag, &fg_flag);
18332          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
18333           * where fl_flag == 1 on ppc64.
18334           */
18335          assign( flags,
18336                  binop( Iop_Or32,
18337                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
18338                                binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
18339                         binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
18340          putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
18341          break;
18342       }
18343 
18344       default:
18345          vex_printf( "dis_vxs_arith(ppc)(opc2)\n" );
18346          return False;
18347    }
18348 
18349    return True;
18350 }
18351 
18352 
18353 /*
18354  * VSX Floating Point Compare Instructions
18355  */
18356 static Bool
dis_vx_cmp(UInt theInstr,UInt opc2)18357 dis_vx_cmp( UInt theInstr, UInt opc2 )
18358 {
18359    /* XX3-Form and XX2-Form */
18360    UChar opc1 = ifieldOPC( theInstr );
18361    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
18362    IRTemp ccPPC32;
18363    UChar XA       = ifieldRegXA ( theInstr );
18364    UChar XB       = ifieldRegXB ( theInstr );
18365    IRTemp frA     = newTemp(Ity_F64);
18366    IRTemp frB     = newTemp(Ity_F64);
18367 
18368    if (opc1 != 0x3C) {
18369       vex_printf( "dis_vx_cmp(ppc)(instr)\n" );
18370       return False;
18371    }
18372 
18373    assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
18374    assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
18375    switch (opc2) {
18376       case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
18377          /* Note: Differences between xscmpudp and xscmpodp are only in
18378           * exception flag settings, which aren't supported anyway. */
18379          DIP("xscmp%sdp crf%d,fr%u,fr%u\n", opc2 == 0x08c ? "u" : "o",
18380                                            crfD, XA, XB);
18381          ccPPC32 = get_fp_cmp_CR_val( binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)));
18382          putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
18383          putFPCC( mkexpr( ccPPC32 ) );
18384          break;
18385 
18386       default:
18387          vex_printf( "dis_vx_cmp(ppc)(opc2)\n" );
18388          return False;
18389    }
18390    return True;
18391 }
18392 
18393 static void
do_vvec_fp_cmp(IRTemp vA,IRTemp vB,UChar XT,UChar flag_rC,ppc_cmp_t cmp_type)18394 do_vvec_fp_cmp ( IRTemp vA, IRTemp vB, UChar XT, UChar flag_rC,
18395                  ppc_cmp_t cmp_type )
18396 {
18397    IRTemp frA_hi     = newTemp(Ity_F64);
18398    IRTemp frB_hi     = newTemp(Ity_F64);
18399    IRTemp frA_lo     = newTemp(Ity_F64);
18400    IRTemp frB_lo     = newTemp(Ity_F64);
18401    IRTemp ccPPC32    = newTemp(Ity_I32);
18402    IRTemp ccIR_hi;
18403    IRTemp ccIR_lo;
18404 
18405    IRTemp hiResult = newTemp(Ity_I64);
18406    IRTemp loResult = newTemp(Ity_I64);
18407    IRTemp hiEQlo = newTemp(Ity_I1);
18408    IRTemp all_elem_true = newTemp(Ity_I32);
18409    IRTemp all_elem_false = newTemp(Ity_I32);
18410 
18411    assign(frA_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vA ))));
18412    assign(frB_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vB ))));
18413    assign(frA_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vA ))));
18414    assign(frB_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vB ))));
18415 
18416    ccIR_hi = get_fp_cmp_CR_val( binop( Iop_CmpF64,
18417                                        mkexpr( frA_hi ),
18418                                        mkexpr( frB_hi ) ) );
18419    ccIR_lo = get_fp_cmp_CR_val( binop( Iop_CmpF64,
18420                                        mkexpr( frA_lo ),
18421                                        mkexpr( frB_lo ) ) );
18422 
18423    if (cmp_type != PPC_CMP_GE) {
18424       assign( hiResult,
18425               unop( Iop_1Sto64,
18426                     binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( cmp_type ) ) ) );
18427       assign( loResult,
18428               unop( Iop_1Sto64,
18429                     binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( cmp_type ) ) ) );
18430    } else {
18431       // For PPC_CMP_GE, one element compare may return "4" (for "greater than") and
18432       // the other element compare may return "2" (for "equal to").
18433       IRTemp lo_GE = newTemp(Ity_I1);
18434       IRTemp hi_GE = newTemp(Ity_I1);
18435 
18436       assign(hi_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 2 ) ),
18437                            binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 4 ) ) ) );
18438       assign( hiResult,unop( Iop_1Sto64, mkexpr( hi_GE ) ) );
18439 
18440       assign(lo_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 2 ) ),
18441                            binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 4 ) ) ) );
18442       assign( loResult, unop( Iop_1Sto64, mkexpr( lo_GE ) ) );
18443    }
18444 
18445    // The [hi/lo]Result will be all 1's or all 0's.  We just look at the lower word.
18446    assign( hiEQlo,
18447            binop( Iop_CmpEQ32,
18448                   unop( Iop_64to32, mkexpr( hiResult ) ),
18449                   unop( Iop_64to32, mkexpr( loResult ) ) ) );
18450    putVSReg( XT,
18451              binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
18452 
18453    assign( all_elem_true,
18454            unop( Iop_1Uto32,
18455                  mkAND1( mkexpr( hiEQlo ),
18456                          binop( Iop_CmpEQ32,
18457                                 mkU32( 0xffffffff ),
18458                                 unop( Iop_64to32,
18459                                 mkexpr( hiResult ) ) ) ) ) );
18460 
18461    assign( all_elem_false,
18462            unop( Iop_1Uto32,
18463                  mkAND1( mkexpr( hiEQlo ),
18464                          binop( Iop_CmpEQ32,
18465                                 mkU32( 0 ),
18466                                 unop( Iop_64to32,
18467                                 mkexpr( hiResult ) ) ) ) ) );
18468    assign( ccPPC32,
18469            binop( Iop_Or32,
18470                   binop( Iop_Shl32, mkexpr( all_elem_false ), mkU8( 1 ) ),
18471                   binop( Iop_Shl32, mkexpr( all_elem_true ), mkU8( 3 ) ) ) );
18472 
18473    if (flag_rC) {
18474       putGST_field( PPC_GST_CR, mkexpr(ccPPC32), 6 );
18475    }
18476 }
18477 
18478 /*
18479  * VSX Vector Compare Instructions
18480  */
18481 static Bool
dis_vvec_cmp(UInt theInstr,UInt opc2)18482 dis_vvec_cmp( UInt theInstr, UInt opc2 )
18483 {
18484    /* XX3-Form */
18485    UChar opc1 = ifieldOPC( theInstr );
18486    UChar XT = ifieldRegXT ( theInstr );
18487    UChar XA = ifieldRegXA ( theInstr );
18488    UChar XB = ifieldRegXB ( theInstr );
18489    UChar flag_rC  = ifieldBIT10(theInstr);
18490    IRTemp vA = newTemp( Ity_V128 );
18491    IRTemp vB = newTemp( Ity_V128 );
18492 
18493    if (opc1 != 0x3C) {
18494       vex_printf( "dis_vvec_cmp(ppc)(instr)\n" );
18495       return False;
18496    }
18497 
18498    assign( vA, getVSReg( XA ) );
18499    assign( vB, getVSReg( XB ) );
18500 
18501    switch (opc2) {
18502       case 0x18C:  // xvcmpeqdp[.] (VSX Vector Compare Equal To Double-Precision [ & Record ])
18503       {
18504          DIP("xvcmpeqdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
18505              XT, XA, XB);
18506          do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_EQ);
18507          break;
18508       }
18509 
18510       case 0x1CC:  // xvcmpgedp[.] (VSX Vector Compare Greater Than or Equal To Double-Precision [ & Record ])
18511       {
18512          DIP("xvcmpgedp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
18513              XT, XA, XB);
18514          do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GE);
18515          break;
18516       }
18517 
18518       case 0x1AC:  // xvcmpgtdp[.] (VSX Vector Compare Greater Than Double-Precision [ & Record ])
18519       {
18520          DIP("xvcmpgtdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
18521              XT, XA, XB);
18522          do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GT);
18523          break;
18524       }
18525 
18526       case 0x10C:  // xvcmpeqsp[.] (VSX Vector Compare Equal To Single-Precision [ & Record ])
18527       {
18528          IRTemp vD = newTemp(Ity_V128);
18529 
18530          DIP("xvcmpeqsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
18531              XT, XA, XB);
18532          assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
18533          putVSReg( XT, mkexpr(vD) );
18534          if (flag_rC) {
18535             set_AV_CR6( mkexpr(vD), True );
18536          }
18537          break;
18538       }
18539 
18540       case 0x14C:  // xvcmpgesp[.] (VSX Vector Compare Greater Than or Equal To Single-Precision [ & Record ])
18541       {
18542          IRTemp vD = newTemp(Ity_V128);
18543 
18544          DIP("xvcmpgesp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
18545              XT, XA, XB);
18546          assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
18547          putVSReg( XT, mkexpr(vD) );
18548          if (flag_rC) {
18549             set_AV_CR6( mkexpr(vD), True );
18550          }
18551          break;
18552       }
18553 
18554       case 0x12C:  //xvcmpgtsp[.] (VSX Vector Compare Greater Than Single-Precision [ & Record ])
18555       {
18556          IRTemp vD = newTemp(Ity_V128);
18557 
18558          DIP("xvcmpgtsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
18559              XT, XA, XB);
18560          assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
18561          putVSReg( XT, mkexpr(vD) );
18562          if (flag_rC) {
18563             set_AV_CR6( mkexpr(vD), True );
18564          }
18565          break;
18566       }
18567 
18568       default:
18569          vex_printf( "dis_vvec_cmp(ppc)(opc2)\n" );
18570          return False;
18571    }
18572    return True;
18573 }
18574 /*
18575  * Miscellaneous VSX Scalar Instructions
18576  */
18577 static Bool
dis_vxs_misc(UInt theInstr,const VexAbiInfo * vbi,UInt opc2,int allow_isa_3_0)18578 dis_vxs_misc( UInt theInstr, const VexAbiInfo* vbi, UInt opc2,
18579               int allow_isa_3_0 )
18580 {
18581 #define VG_PPC_SIGN_MASK 0x7fffffffffffffffULL
18582    /* XX3-Form and XX2-Form */
18583    UChar opc1 = ifieldOPC( theInstr );
18584    UChar XT = ifieldRegXT ( theInstr );
18585    UChar XA = ifieldRegXA ( theInstr );
18586    UChar XB = ifieldRegXB ( theInstr );
18587    IRTemp vA = newTemp( Ity_V128 );
18588    IRTemp vB = newTemp( Ity_V128 );
18589 
18590    if (opc1 != 0x3C) {
18591       vex_printf( "dis_vxs_misc(ppc)(instr)\n" );
18592       return False;
18593    }
18594 
18595    assign( vA, getVSReg( XA ) );
18596    assign( vB, getVSReg( XB ) );
18597 
18598    /* For all the VSX move instructions, the contents of doubleword element 1
18599     * of VSX[XT] are undefined after the operation; therefore, we can simply
18600     * move the entire array element where it makes sense to do so.
18601     */
18602    if (( opc2 == 0x168 ) && ( IFIELD( theInstr, 19, 2 ) == 0 ) )
18603       {
18604          /* Special case of XX1-Form with immediate value
18605           *  xxspltib (VSX Vector Splat Immediate Byte)
18606           */
18607          UInt uim = IFIELD( theInstr, 11, 8 );
18608          UInt word_value = ( uim << 24 ) | ( uim << 16 ) | ( uim << 8 ) | uim;
18609 
18610          DIP("xxspltib v%d,%d\n", (UInt)XT, uim);
18611          putVSReg(XT, binop( Iop_64HLtoV128,
18612                              binop( Iop_32HLto64,
18613                                     mkU32( word_value ),
18614                                     mkU32( word_value ) ),
18615                              binop( Iop_32HLto64,
18616                                     mkU32( word_value ),
18617                                     mkU32( word_value ) ) ) );
18618          return True;
18619       }
18620 
18621    switch ( opc2 ) {
18622       case 0x0ec: // xscmpexpdp (VSX Scalar Compare Exponents Double-Precision)
18623       {
18624          /* Compare 64-bit data, 128-bit layout:
18625             src1[0:63] is double word, src1[64:127] is unused
18626             src2[0:63] is double word, src2[64:127] is unused
18627          */
18628          IRExpr *bit4, *bit5, *bit6, *bit7;
18629          UInt BF = IFIELD( theInstr, 23, 3 );
18630          IRTemp eq_lt_gt = newTemp( Ity_I32 );
18631          IRTemp CC = newTemp( Ity_I32 );
18632          IRTemp vA_hi = newTemp( Ity_I64 );
18633          IRTemp vB_hi = newTemp( Ity_I64 );
18634          IRExpr *mask = mkU64( 0x7FF0000000000000 );
18635 
18636          DIP("xscmpexpdp %d,v%d,v%d\n", BF, XA, XB);
18637 
18638          assign( vA_hi, unop( Iop_V128HIto64, mkexpr( vA ) ) );
18639          assign( vB_hi, unop( Iop_V128HIto64, mkexpr( vB ) ) );
18640 
18641          /* A exp < B exp */
18642          bit4 = binop( Iop_CmpLT64U,
18643                       binop( Iop_And64,
18644                              mkexpr( vA_hi ),
18645                              mask ),
18646                       binop( Iop_And64,
18647                              mkexpr( vB_hi ),
18648                              mask ) );
18649          /*  A exp > B exp */
18650          bit5 = binop( Iop_CmpLT64U,
18651                       binop( Iop_And64,
18652                              mkexpr( vB_hi ),
18653                              mask ),
18654                       binop( Iop_And64,
18655                              mkexpr( vA_hi ),
18656                              mask ) );
18657          /* test equal */
18658          bit6 = binop( Iop_CmpEQ64,
18659                       binop( Iop_And64,
18660                              mkexpr( vA_hi ),
18661                              mask ),
18662                       binop( Iop_And64,
18663                              mkexpr( vB_hi ),
18664                              mask ) );
18665 
18666          /* exp A or exp B is NaN */
18667          bit7 = mkOR1( is_NaN( Ity_I64, vA_hi ),
18668                        is_NaN( Ity_I64, vB_hi ) );
18669 
18670          assign( eq_lt_gt, binop( Iop_Or32,
18671                                   binop( Iop_Shl32,
18672                                          unop( Iop_1Uto32, bit4 ),
18673                                          mkU8( 3) ),
18674                                   binop( Iop_Or32,
18675                                          binop( Iop_Shl32,
18676                                                 unop( Iop_1Uto32, bit5 ),
18677                                                 mkU8( 2) ),
18678                                          binop( Iop_Shl32,
18679                                                 unop( Iop_1Uto32, bit6 ),
18680                                                 mkU8( 1 ) ) ) ) );
18681          assign(CC, binop( Iop_Or32,
18682                            binop( Iop_And32,
18683                                   mkexpr( eq_lt_gt ) ,
18684                                   unop( Iop_Not32, unop( Iop_1Sto32, bit7 ) ) ),
18685                            unop( Iop_1Uto32, bit7 ) ) );
18686 
18687          putGST_field( PPC_GST_CR, mkexpr( CC ), BF );
18688          putFPCC( mkexpr( CC ) );
18689          return True;
18690       }
18691       break;
18692 
18693       case 0x14A: // xxextractuw (VSX Vector Extract Unsigned Word)
18694       {
18695          UInt uim = IFIELD( theInstr, 16, 4 );
18696 
18697          DIP("xxextractuw v%d,v%d,%d\n", (UInt)XT, (UInt)XB, uim);
18698 
18699          putVSReg( XT,
18700                    binop( Iop_ShlV128,
18701                           binop( Iop_AndV128,
18702                                  binop( Iop_ShrV128,
18703                                         mkexpr( vB ),
18704                                         mkU8( ( 12 - uim ) * 8 ) ),
18705                                  binop(Iop_64HLtoV128,
18706                                        mkU64( 0 ),
18707                                        mkU64( 0xFFFFFFFF ) ) ),
18708                           mkU8( ( 32*2 ) ) ) );
18709          break;
18710       }
18711       case 0x16A: // xxinsertw (VSX Vector insert Word)
18712       {
18713          UInt uim = IFIELD( theInstr, 16, 4 );
18714          IRTemp vT = newTemp( Ity_V128 );
18715          IRTemp tmp = newTemp( Ity_V128 );
18716 
18717          DIP("xxinsertw v%d,v%d,%d\n", (UInt)XT, (UInt)XB, uim);
18718 
18719          assign( vT, getVSReg( XT ) );
18720          assign( tmp, binop( Iop_AndV128,
18721                              mkexpr( vT ),
18722                              unop( Iop_NotV128,
18723                                    binop( Iop_ShlV128,
18724                                           binop( Iop_64HLtoV128,
18725                                                  mkU64( 0x0 ),
18726                                                  mkU64( 0xFFFFFFFF) ),
18727                                           mkU8( ( 12 - uim ) * 8 ) ) ) ) );
18728 
18729          putVSReg( XT,
18730                    binop( Iop_OrV128,
18731                           binop( Iop_ShlV128,
18732                                  binop( Iop_AndV128,
18733                                         binop( Iop_ShrV128,
18734                                                mkexpr( vB ),
18735                                                mkU8( 32 * 2 ) ),
18736                                         binop( Iop_64HLtoV128,
18737                                                mkU64( 0 ),
18738                                                mkU64( 0xFFFFFFFF ) ) ),
18739                                  mkU8( ( 12 - uim ) * 8 ) ),
18740                           mkexpr( tmp ) ) );
18741          break;
18742       }
18743 
18744       case 0x2B2: // xsabsdp (VSX scalar absolute value double-precision
18745       {
18746          /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */
18747          IRTemp absVal = newTemp(Ity_V128);
18748          if (host_endness == VexEndnessLE) {
18749             IRTemp hi64 = newTemp(Ity_I64);
18750             IRTemp lo64 = newTemp(Ity_I64);
18751             assign( hi64, unop( Iop_V128HIto64, mkexpr(vB) ) );
18752             assign( lo64, unop( Iop_V128to64, mkexpr(vB) ) );
18753             assign( absVal, binop( Iop_64HLtoV128,
18754                                    binop( Iop_And64, mkexpr(hi64),
18755                                           mkU64(VG_PPC_SIGN_MASK) ),
18756                                    mkexpr(lo64) ) );
18757          } else {
18758             assign(absVal, binop(Iop_ShrV128,
18759                                  binop(Iop_ShlV128, mkexpr(vB),
18760                                        mkU8(1)), mkU8(1)));
18761          }
18762          DIP("xsabsdp v%d,v%d\n", XT, XB);
18763          putVSReg(XT, mkexpr(absVal));
18764          break;
18765       }
18766 
18767       case 0x2b6: // xsxexpdp (VSX Scalar Extract Exponent Double-Precision)
18768                   // xsxsigdp (VSX Scalar Extract Significand Doulbe-Precision)
18769                   // xsvhpdp  (VSX Scalar Convert Half-Precision format
18770                   //           to Double-Precision format)
18771                   // xscvdphp (VSX Scalar round & convert Double-precision
18772                   //           format to Half-precision format)
18773       {
18774          IRTemp rT = newTemp( Ity_I64 );
18775          UInt inst_select = IFIELD( theInstr, 16, 5);
18776 
18777          if (inst_select == 0) {
18778             DIP("xsxexpd %d,v%d\n", (UInt)XT, (UInt)XB);
18779 
18780             assign( rT, binop( Iop_Shr64,
18781                                binop( Iop_And64,
18782                                       unop( Iop_V128HIto64, mkexpr( vB ) ),
18783                                       mkU64( 0x7FF0000000000000 ) ),
18784                                mkU8 ( 52 ) ) );
18785          } else if (inst_select == 1) {
18786             IRExpr *normal;
18787             IRTemp tmp = newTemp(Ity_I64);
18788 
18789             DIP("xsxsigdp v%d,v%d\n",  (UInt)XT, (UInt)XB);
18790 
18791             assign( tmp, unop( Iop_V128HIto64, mkexpr( vB ) ) );
18792 
18793             /* Value is normal if it isn't infinite, zero or denormalized */
18794             normal = mkNOT1( mkOR1(
18795                                    mkOR1( is_NaN( Ity_I64, tmp ),
18796                                           is_Inf( Ity_I64, tmp ) ),
18797                                    mkOR1( is_Zero( Ity_I64, tmp ),
18798                                           is_Denorm( Ity_I64, tmp ) ) ) );
18799 
18800             assign( rT, binop( Iop_Or64,
18801                                binop( Iop_And64,
18802                                       mkexpr( tmp ),
18803                                       mkU64( 0xFFFFFFFFFFFFF ) ),
18804                                binop( Iop_Shl64,
18805                                       unop( Iop_1Uto64, normal),
18806                                       mkU8( 52 ) ) ) );
18807             putIReg( XT, mkexpr( rT ) );
18808 
18809         } else if (inst_select == 16) {
18810             IRTemp result = newTemp( Ity_V128 );
18811             IRTemp value = newTemp( Ity_I64 );
18812             /* Note: PPC only coverts the 16-bit value in the upper 64-bits
18813              * of the source V128 to a 64-bit value stored in the upper
18814              * 64-bits of the V128 result.  The contents of the lower 64-bits
18815              * is undefined.
18816              */
18817 
18818             DIP("xscvhpdp v%d, v%d\n", (UInt)XT, (UInt)XB);
18819             assign( result, unop( Iop_F16toF64x2, mkexpr( vB ) ) );
18820 
18821             putVSReg( XT, mkexpr( result ) );
18822 
18823             assign( value, unop( Iop_V128HIto64, mkexpr( result ) ) );
18824             generate_store_FPRF( Ity_I64, value, vbi );
18825             return True;
18826 
18827          } else if (inst_select == 17) {   // xscvdphp
18828             IRTemp value = newTemp( Ity_I32 );
18829             IRTemp result = newTemp( Ity_V128 );
18830             /* Note: PPC only coverts the 64-bit value in the upper 64-bits of
18831              * the V128 and stores the 16-bit result in the upper word of the
18832              * V128 result.  The contents of the lower 64-bits is undefined.
18833              */
18834             DIP("xscvdphp v%d, v%d\n", (UInt)XT, (UInt)XB);
18835             assign( result,  unop( Iop_F64toF16x2, mkexpr( vB ) ) );
18836             assign( value, unop( Iop_64to32, unop( Iop_V128HIto64,
18837                                                    mkexpr( result ) ) ) );
18838             putVSReg( XT, mkexpr( result ) );
18839             generate_store_FPRF( Ity_I16, value, vbi );
18840             return True;
18841 
18842          } else {
18843             vex_printf( "dis_vxv_scalar_extract_exp_sig invalid inst_select (ppc)(opc2)\n" );
18844             vex_printf("inst_select = %d\n", inst_select);
18845             return False;
18846          }
18847       }
18848       break;
18849 
18850       case 0x254:  // xststdcsp (VSX Scalar Test Data Class Single-Precision)
18851       case 0x2D4:  // xststdcdp (VSX Scalar Test Data Class Double-Precision)
18852       {
18853          /* These instructions only differ in that the single precision
18854             instruction, xststdcsp, has the additional constraint on the
18855             denormal test that the exponent be greater then zero and
18856             less then 0x381. */
18857          IRTemp vB_hi = newTemp( Ity_I64 );
18858          UInt BF = IFIELD( theInstr, 23, 3 );
18859          UInt DCMX_mask = IFIELD( theInstr, 16, 7 );
18860          IRTemp NaN = newTemp( Ity_I64 );
18861          IRTemp inf = newTemp( Ity_I64 );
18862          IRTemp zero = newTemp( Ity_I64 );
18863          IRTemp dnorm = newTemp( Ity_I64 );
18864          IRTemp pos = newTemp( Ity_I64 );
18865          IRTemp not_sp = newTemp( Ity_I64 );
18866          IRTemp DCM = newTemp( Ity_I64 );
18867          IRTemp CC = newTemp( Ity_I64 );
18868          IRTemp exponent = newTemp( Ity_I64 );
18869          IRTemp tmp = newTemp( Ity_I64 );
18870 
18871          assign( vB_hi, unop( Iop_V128HIto64, mkexpr( vB ) ) );
18872 
18873          assign( pos, unop( Iop_1Uto64,
18874                             binop( Iop_CmpEQ64,
18875                                    binop( Iop_Shr64,
18876                                           mkexpr( vB_hi ),
18877                                           mkU8( 63 ) ),
18878                                    mkU64( 0 ) ) ) );
18879 
18880          assign( NaN, unop( Iop_1Uto64, is_NaN( Ity_I64, vB_hi ) ) );
18881          assign( inf, unop( Iop_1Uto64, is_Inf( Ity_I64, vB_hi ) ) );
18882          assign( zero, unop( Iop_1Uto64, is_Zero( Ity_I64, vB_hi ) ) );
18883 
18884          if (opc2 == 0x254) {
18885             DIP("xststdcsp %d,v%d,%d\n", BF, (UInt)XB, DCMX_mask);
18886 
18887             /* The least significant bit of the CC is set to 1 if the double
18888                precision value is not representable as a single precision
18889                value. The spec says the bit is set if:
18890                   src != convert_SPtoDP(convert_DPtoSP(src))
18891             */
18892             assign( tmp,
18893                     unop( Iop_ReinterpF64asI64,
18894                                 unop( Iop_F32toF64,
18895                                       unop( Iop_TruncF64asF32,
18896                                             unop( Iop_ReinterpI64asF64,
18897                                                   mkexpr( vB_hi ) ) ) ) ) );
18898             assign( not_sp, unop( Iop_1Uto64,
18899                                   mkNOT1( binop( Iop_CmpEQ64,
18900                                                  mkexpr( vB_hi ),
18901                                                  mkexpr( tmp ) ) ) ) );
18902             assign( exponent,
18903                     binop( Iop_Shr64,
18904                            binop( Iop_And64,
18905                                   mkexpr( vB_hi ),
18906                                   mkU64( 0x7ff0000000000000 ) ),
18907                            mkU8( 52 ) ) );
18908             assign( dnorm, unop( Iop_1Uto64,
18909                                  mkOR1( is_Denorm( Ity_I64, vB_hi ),
18910                                         mkAND1( binop( Iop_CmpLT64U,
18911                                                        mkexpr( exponent ),
18912                                                        mkU64( 0x381 ) ),
18913                                                 binop( Iop_CmpNE64,
18914                                                        mkexpr( exponent ),
18915                                                        mkU64( 0x0 ) ) ) ) ) );
18916 
18917          } else {
18918             DIP("xststdcdp %d,v%d,%d\n", BF, (UInt)XB, DCMX_mask);
18919             assign( not_sp,  mkU64( 0 ) );
18920             assign( dnorm, unop( Iop_1Uto64, is_Denorm( Ity_I64, vB_hi ) ) );
18921          }
18922 
18923          assign( DCM, create_DCM( Ity_I64, NaN, inf, zero, dnorm, pos ) );
18924          assign( CC,
18925                  binop( Iop_Or64,
18926                         binop( Iop_And64,    /* vB sign bit */
18927                                binop( Iop_Shr64,
18928                                       mkexpr( vB_hi ),
18929                                       mkU8( 60 ) ),
18930                                mkU64( 0x8 ) ),
18931                         binop( Iop_Or64,
18932                                binop( Iop_Shl64,
18933                                       unop( Iop_1Uto64,
18934                                             binop( Iop_CmpNE64,
18935                                                    binop( Iop_And64,
18936                                                           mkexpr( DCM ),
18937                                                           mkU64( DCMX_mask ) ),
18938                                                    mkU64( 0 ) ) ),
18939                                       mkU8( 1 ) ),
18940                                mkexpr( not_sp ) ) ) );
18941          putGST_field( PPC_GST_CR, unop( Iop_64to32, mkexpr( CC ) ), BF );
18942          putFPCC( unop( Iop_64to32, mkexpr( CC ) ) );
18943       }
18944       return True;
18945 
18946       case 0x2C0: // xscpsgndp
18947       {
18948          /* Scalar copy sign double-precision */
18949          IRTemp vecA_signed = newTemp(Ity_I64);
18950          IRTemp vecB_unsigned = newTemp(Ity_I64);
18951          IRTemp vec_result = newTemp(Ity_V128);
18952          DIP("xscpsgndp v%d,v%d v%d\n", XT, XA, XB);
18953          assign( vecA_signed, binop( Iop_And64,
18954                                      unop( Iop_V128HIto64,
18955                                            mkexpr(vA)),
18956                                            mkU64(~VG_PPC_SIGN_MASK) ) );
18957          assign( vecB_unsigned, binop( Iop_And64,
18958                                        unop( Iop_V128HIto64,
18959                                              mkexpr(vB) ),
18960                                              mkU64(VG_PPC_SIGN_MASK) ) );
18961          assign( vec_result, binop( Iop_64HLtoV128,
18962                                     binop( Iop_Or64,
18963                                            mkexpr(vecA_signed),
18964                                            mkexpr(vecB_unsigned) ),
18965                                     mkU64(0x0ULL)));
18966          putVSReg(XT, mkexpr(vec_result));
18967          break;
18968       }
18969       case 0x2D2: // xsnabsdp
18970       {
18971          /* Scalar negative absolute value double-precision */
18972          IRTemp BHi_signed = newTemp(Ity_I64);
18973          DIP("xsnabsdp v%d,v%d\n", XT, XB);
18974          assign( BHi_signed, binop( Iop_Or64,
18975                                     unop( Iop_V128HIto64,
18976                                           mkexpr(vB) ),
18977                                           mkU64(~VG_PPC_SIGN_MASK) ) );
18978          putVSReg(XT, binop( Iop_64HLtoV128,
18979                              mkexpr(BHi_signed), mkU64(0x0ULL) ) );
18980          break;
18981       }
18982       case 0x2F2: // xsnegdp
18983       {
18984          /* Scalar negate double-precision */
18985          IRTemp BHi_signed = newTemp(Ity_I64);
18986          IRTemp BHi_unsigned = newTemp(Ity_I64);
18987          IRTemp BHi_negated = newTemp(Ity_I64);
18988          IRTemp BHi_negated_signbit = newTemp(Ity_I1);
18989          IRTemp vec_result = newTemp(Ity_V128);
18990          DIP("xsnabsdp v%d,v%d\n", XT, XB);
18991          assign( BHi_signed, unop( Iop_V128HIto64, mkexpr(vB) ) );
18992          assign( BHi_unsigned, binop( Iop_And64, mkexpr(BHi_signed),
18993                                       mkU64(VG_PPC_SIGN_MASK) ) );
18994          assign( BHi_negated_signbit,
18995                  unop( Iop_Not1,
18996                        unop( Iop_32to1,
18997                              binop( Iop_Shr32,
18998                                     unop( Iop_64HIto32,
18999                                           binop( Iop_And64,
19000                                                  mkexpr(BHi_signed),
19001                                                  mkU64(~VG_PPC_SIGN_MASK) )
19002                                           ),
19003                                     mkU8(31) ) ) ) );
19004          assign( BHi_negated,
19005                  binop( Iop_Or64,
19006                         binop( Iop_32HLto64,
19007                                binop( Iop_Shl32,
19008                                       unop( Iop_1Uto32,
19009                                             mkexpr(BHi_negated_signbit) ),
19010                                       mkU8(31) ),
19011                                mkU32(0) ),
19012                         mkexpr(BHi_unsigned) ) );
19013          assign( vec_result, binop( Iop_64HLtoV128, mkexpr(BHi_negated),
19014                                     mkU64(0x0ULL)));
19015          putVSReg( XT, mkexpr(vec_result));
19016          break;
19017       }
19018       case 0x280: // xsmaxdp (VSX Scalar Maximum Double-Precision)
19019       case 0x2A0: // xsmindp (VSX Scalar Minimum Double-Precision)
19020       {
19021          IRTemp frA     = newTemp(Ity_I64);
19022          IRTemp frB     = newTemp(Ity_I64);
19023          Bool isMin = opc2 == 0x2A0 ? True : False;
19024          DIP("%s v%d,v%d v%d\n", isMin ? "xsmaxdp" : "xsmindp", XT, XA, XB);
19025 
19026          assign(frA, unop(Iop_V128HIto64, mkexpr( vA )));
19027          assign(frB, unop(Iop_V128HIto64, mkexpr( vB )));
19028          putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), mkU64( 0 ) ) );
19029 
19030          break;
19031       }
19032       case 0x0F2: // xsrdpim (VSX Scalar Round to Double-Precision Integer using round toward -Infinity)
19033       case 0x0D2: // xsrdpip (VSX Scalar Round to Double-Precision Integer using round toward +Infinity)
19034       case 0x0D6: // xsrdpic (VSX Scalar Round to Double-Precision Integer using Current rounding mode)
19035       case 0x0B2: // xsrdpiz (VSX Scalar Round to Double-Precision Integer using round toward Zero)
19036       case 0x092: // xsrdpi  (VSX Scalar Round to Double-Precision Integer using round toward Nearest Away)
19037       {
19038          IRTemp frB_I64 = newTemp(Ity_I64);
19039          IRExpr * frD_fp_round = NULL;
19040 
19041          assign(frB_I64, unop(Iop_V128HIto64, mkexpr( vB )));
19042          frD_fp_round = _do_vsx_fp_roundToInt(frB_I64, opc2);
19043 
19044          DIP("xsrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), XT, XB);
19045          putVSReg( XT,
19046                    binop( Iop_64HLtoV128,
19047                           unop( Iop_ReinterpF64asI64, frD_fp_round),
19048                           mkU64( 0 ) ) );
19049          break;
19050       }
19051       case 0x034: // xsresp (VSX Scalar Reciprocal Estimate single-Precision)
19052       case 0x014: /* xsrsqrtesp (VSX Scalar Reciprocal Square Root Estimate
19053                    * single-Precision)
19054                    */
19055       {
19056          IRTemp frB = newTemp(Ity_F64);
19057          IRTemp sqrt = newTemp(Ity_F64);
19058          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
19059          IRExpr* rm  = get_IR_roundingmode();
19060          Bool redp = opc2 == 0x034;
19061          DIP("%s v%d,v%d\n", redp ? "xsresp" : "xsrsqrtesp", XT,
19062              XB);
19063 
19064          assign( frB,
19065                  unop( Iop_ReinterpI64asF64,
19066                        unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
19067 
19068          if (!redp)
19069             assign( sqrt,
19070                     binop( Iop_SqrtF64,
19071                            rm,
19072                            mkexpr(frB) ) );
19073          putVSReg( XT,
19074                       binop( Iop_64HLtoV128,
19075                              unop( Iop_ReinterpF64asI64,
19076                                    binop( Iop_RoundF64toF32, rm,
19077                                           triop( Iop_DivF64,
19078                                                  rm,
19079                                                  ieee_one,
19080                                                  redp ? mkexpr( frB ) :
19081                                                         mkexpr( sqrt ) ) ) ),
19082                              mkU64( 0 ) ) );
19083          break;
19084       }
19085 
19086       case 0x0B4: // xsredp (VSX Scalar Reciprocal Estimate Double-Precision)
19087       case 0x094: // xsrsqrtedp (VSX Scalar Reciprocal Square Root Estimate Double-Precision)
19088 
19089       {
19090          IRTemp frB = newTemp(Ity_F64);
19091          IRTemp sqrt = newTemp(Ity_F64);
19092          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
19093          IRExpr* rm  = get_IR_roundingmode();
19094          Bool redp = opc2 == 0x0B4;
19095          DIP("%s v%d,v%d\n", redp ? "xsredp" : "xsrsqrtedp", XT, XB);
19096          assign( frB,
19097                  unop( Iop_ReinterpI64asF64,
19098                        unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
19099 
19100          if (!redp)
19101             assign( sqrt,
19102                     binop( Iop_SqrtF64,
19103                            rm,
19104                            mkexpr(frB) ) );
19105          putVSReg( XT,
19106                       binop( Iop_64HLtoV128,
19107                              unop( Iop_ReinterpF64asI64,
19108                                    triop( Iop_DivF64,
19109                                           rm,
19110                                           ieee_one,
19111                                           redp ? mkexpr( frB ) : mkexpr( sqrt ) ) ),
19112                              mkU64( 0 ) ) );
19113          break;
19114       }
19115 
19116       case 0x232: // xsrsp (VSX Scalar Round to Single-Precision)
19117       {
19118          IRTemp frB = newTemp(Ity_F64);
19119          IRExpr* rm  = get_IR_roundingmode();
19120          DIP("xsrsp v%d, v%d\n", XT, XB);
19121          assign( frB,
19122                  unop( Iop_ReinterpI64asF64,
19123                        unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
19124 
19125          putVSReg( XT, binop( Iop_64HLtoV128,
19126                               unop( Iop_ReinterpF64asI64,
19127                                     binop( Iop_RoundF64toF32,
19128                                            rm,
19129                                            mkexpr( frB ) ) ),
19130                               mkU64( 0 ) ) );
19131          break;
19132       }
19133 
19134       case 0x354: // xvtstdcsp (VSX Test Data Class Single-Precision)
19135       {
19136          UInt DX_mask = IFIELD( theInstr, 16, 5 );
19137          UInt DC_mask = IFIELD( theInstr, 6, 1 );
19138          UInt DM_mask = IFIELD( theInstr, 2, 1 );
19139          UInt DCMX_mask = (DC_mask << 6) | (DM_mask << 5) | DX_mask;
19140 
19141          IRTemp match_value[4];
19142          IRTemp value[4];
19143          IRTemp NaN[4];
19144          IRTemp inf[4];
19145          IRTemp pos[4];
19146          IRTemp DCM[4];
19147          IRTemp zero[4];
19148          IRTemp dnorm[4];
19149          Int i;
19150 
19151          DIP("xvtstdcsp v%d,v%d,%d\n", (UInt)XT, (UInt)XB, DCMX_mask);
19152 
19153          for (i = 0; i < 4; i++) {
19154             NaN[i]   = newTemp(Ity_I32);
19155             inf[i]   = newTemp(Ity_I32);
19156             pos[i]   = newTemp(Ity_I32);
19157             DCM[i]   = newTemp(Ity_I32);
19158             zero[i]  = newTemp(Ity_I32);
19159             dnorm[i] = newTemp(Ity_I32);
19160 
19161             value[i] = newTemp(Ity_I32);
19162             match_value[i] = newTemp(Ity_I32);
19163 
19164             assign( value[i],
19165                     unop( Iop_64to32,
19166                           unop( Iop_V128to64,
19167                                 binop( Iop_AndV128,
19168                                        binop( Iop_ShrV128,
19169                                               mkexpr( vB ),
19170                                               mkU8( (3-i)*32 ) ),
19171                                        binop( Iop_64HLtoV128,
19172                                               mkU64( 0x0 ),
19173                                               mkU64( 0xFFFFFFFF ) ) ) ) ) );
19174 
19175             assign( pos[i], unop( Iop_1Uto32,
19176                                   binop( Iop_CmpEQ32,
19177                                          binop( Iop_Shr32,
19178                                                 mkexpr( value[i] ),
19179                                                 mkU8( 31 ) ),
19180                                          mkU32( 0 ) ) ) );
19181 
19182             assign( NaN[i], unop( Iop_1Uto32, is_NaN( Ity_I32, value[i] ) ));
19183             assign( inf[i], unop( Iop_1Uto32, is_Inf( Ity_I32, value[i] ) ) );
19184             assign( zero[i], unop( Iop_1Uto32, is_Zero( Ity_I32, value[i] ) ) );
19185 
19186             assign( dnorm[i], unop( Iop_1Uto32, is_Denorm( Ity_I32,
19187                                                            value[i] ) ) );
19188             assign( DCM[i], create_DCM( Ity_I32, NaN[i], inf[i], zero[i],
19189                                         dnorm[i], pos[i] ) );
19190 
19191             assign( match_value[i],
19192                     unop( Iop_1Sto32,
19193                           binop( Iop_CmpNE32,
19194                                  binop( Iop_And32,
19195                                         mkU32( DCMX_mask ),
19196                                         mkexpr( DCM[i] ) ),
19197                                  mkU32( 0 ) ) ) );
19198          }
19199 
19200          putVSReg( XT, binop( Iop_64HLtoV128,
19201                               binop( Iop_32HLto64,
19202                                      mkexpr( match_value[0] ),
19203                                      mkexpr( match_value[1] ) ),
19204                               binop( Iop_32HLto64,
19205                                      mkexpr( match_value[2] ),
19206                                      mkexpr( match_value[3] ) ) ) );
19207       }
19208       break;
19209 
19210       case 0x360:  // xviexpsp  (VSX Vector Insert Exponent Single-Precision)
19211       {
19212             Int i;
19213             IRTemp new_XT[5];
19214             IRTemp A_value[4];
19215             IRTemp B_value[4];
19216             IRExpr *sign[4], *expr[4], *fract[4];
19217 
19218             DIP("xviexpsp v%d,v%d\n", XT, XB);
19219             new_XT[0] = newTemp(Ity_V128);
19220             assign( new_XT[0], binop( Iop_64HLtoV128,
19221                                       mkU64( 0x0 ),
19222                                       mkU64( 0x0 ) ) );
19223 
19224             for (i = 0; i < 4; i++) {
19225                A_value[i] = newTemp(Ity_I32);
19226                B_value[i] = newTemp(Ity_I32);
19227 
19228                assign( A_value[i],
19229                        unop( Iop_64to32,
19230                              unop( Iop_V128to64,
19231                                    binop( Iop_AndV128,
19232                                           binop( Iop_ShrV128,
19233                                                  mkexpr( vA ),
19234                                                  mkU8( (3-i)*32 ) ),
19235                                           binop( Iop_64HLtoV128,
19236                                                  mkU64( 0x0 ),
19237                                                  mkU64( 0xFFFFFFFF ) ) ) ) ) );
19238                assign( B_value[i],
19239                        unop( Iop_64to32,
19240                              unop( Iop_V128to64,
19241                                    binop( Iop_AndV128,
19242                                           binop( Iop_ShrV128,
19243                                                  mkexpr( vB ),
19244                                                  mkU8( (3-i)*32 ) ),
19245                                           binop( Iop_64HLtoV128,
19246                                                  mkU64( 0x0 ),
19247                                                  mkU64( 0xFFFFFFFF ) ) ) ) ) );
19248 
19249                sign[i] = binop( Iop_And32, mkexpr( A_value[i] ),
19250                                 mkU32( 0x80000000 ) );
19251                expr[i] = binop( Iop_Shl32,
19252                                 binop( Iop_And32, mkexpr( B_value[i] ),
19253                                        mkU32( 0xFF ) ),
19254                                 mkU8( 23 ) );
19255                fract[i] = binop( Iop_And32, mkexpr( A_value[i] ),
19256                                  mkU32( 0x007FFFFF ) );
19257 
19258                new_XT[i+1] = newTemp(Ity_V128);
19259                assign( new_XT[i+1],
19260                        binop( Iop_OrV128,
19261                               binop( Iop_ShlV128,
19262                                      binop( Iop_64HLtoV128,
19263                                             mkU64( 0 ),
19264                                             binop( Iop_32HLto64,
19265                                                    mkU32( 0 ),
19266                                                    binop( Iop_Or32,
19267                                                          binop( Iop_Or32,
19268                                                                  sign[i],
19269                                                                  expr[i] ),
19270                                                           fract[i] ) ) ),
19271                                      mkU8( (3-i)*32 ) ),
19272                               mkexpr( new_XT[i] ) ) );
19273             }
19274             putVSReg( XT, mkexpr( new_XT[4] ) );
19275       }
19276       break;
19277 
19278       case 0x396:  // xsiexpdp (VSX Scalar Insert Exponent Double-Precision)
19279       {
19280          IRExpr *sign, *expr, *fract;
19281          UChar rA_addr = ifieldRegA(theInstr);
19282          UChar rB_addr = ifieldRegB(theInstr);
19283          IRTemp rA = newTemp( Ity_I64 );
19284          IRTemp rB = newTemp( Ity_I64 );
19285 
19286          DIP("xsiexpdp v%d,%d,%d\n", (UInt)XT, (UInt)rA_addr, (UInt)rB_addr);
19287          assign( rA, getIReg(rA_addr));
19288          assign( rB, getIReg(rB_addr));
19289 
19290          sign = binop( Iop_And64, mkexpr( rA ), mkU64( 0x8000000000000000 ) );
19291          expr = binop( Iop_Shl64,
19292                        binop( Iop_And64, mkexpr( rB ), mkU64( 0x7FF ) ),
19293                        mkU8( 52 ) );
19294          fract = binop( Iop_And64, mkexpr( rA ), mkU64( 0x000FFFFFFFFFFFFF ) );
19295 
19296          putVSReg( XT, binop( Iop_64HLtoV128,
19297                               binop( Iop_Or64,
19298                                      binop( Iop_Or64, sign, expr ),
19299                                      fract ),
19300                               mkU64( 0 ) ) );
19301       }
19302       break;
19303 
19304       case 0x3B6: // xvxexpdp (VSX Vector Extract Exponent Double-Precision)
19305                   // xvxsigdp (VSX Vector Extract Significand Double-Precision)
19306                   // xxbrh
19307                   // xvxexpsp (VSX Vector Extract Exponent Single-Precision)
19308                   // xvxsigsp (VSX Vector Extract Significand Single-Precision)
19309                   // xxbrw
19310                   // xxbrd
19311                   // xxbrq
19312                   // xvcvhpsp (VSX Vector Convert Half-Precision format to Single-Precision format)
19313                   // xvcvsphp (VSX Vector round and convert Single-Precision format to Half-Precision format)
19314       {
19315          UInt inst_select = IFIELD( theInstr, 16, 5);
19316 
19317          if (inst_select == 0) {
19318             DIP("xvxexpdp v%d,v%d\n", XT, XB);
19319 
19320             putVSReg( XT, binop( Iop_ShrV128,
19321                                  binop( Iop_AndV128,
19322                                         mkexpr( vB ),
19323                                         binop( Iop_64HLtoV128,
19324                                                mkU64( 0x7FF0000000000000 ),
19325                                                mkU64( 0x7FF0000000000000 ) ) ),
19326                                  mkU8( 52 ) ) );
19327 
19328          } else if (inst_select == 1) {
19329             Int i;
19330             IRExpr *normal[2];
19331             IRTemp value[2];
19332             IRTemp new_XT[3];
19333 
19334             DIP("xvxsigdp v%d,v%d\n", XT, XB);
19335             new_XT[0] = newTemp(Ity_V128);
19336             assign( new_XT[0], binop( Iop_64HLtoV128,
19337                                       mkU64( 0x0 ),
19338                                       mkU64( 0x0 ) ) );
19339 
19340             for (i = 0; i < 2; i++) {
19341                value[i] = newTemp(Ity_I64);
19342                assign( value[i],
19343                        unop( Iop_V128to64,
19344                             binop( Iop_AndV128,
19345                                     binop( Iop_ShrV128,
19346                                            mkexpr( vB ),
19347                                            mkU8( (1-i)*64 ) ),
19348                                     binop( Iop_64HLtoV128,
19349                                            mkU64( 0x0 ),
19350                                            mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ) );
19351 
19352                /* Value is normal if it isn't infinite, zero or denormalized */
19353                normal[i] = mkNOT1( mkOR1(
19354                                          mkOR1( is_NaN( Ity_I64, value[i] ),
19355                                                 is_Inf( Ity_I64, value[i] ) ),
19356                                          mkOR1( is_Zero( Ity_I64, value[i] ),
19357                                                 is_Denorm( Ity_I64,
19358                                                            value[i] ) ) ) );
19359                new_XT[i+1] = newTemp(Ity_V128);
19360 
19361                assign( new_XT[i+1],
19362                        binop( Iop_OrV128,
19363                               binop( Iop_ShlV128,
19364                                      binop( Iop_64HLtoV128,
19365                                             mkU64( 0x0 ),
19366                                             binop( Iop_Or64,
19367                                                    binop( Iop_And64,
19368                                                           mkexpr( value[i] ),
19369                                                           mkU64( 0xFFFFFFFFFFFFF ) ),
19370                                                    binop( Iop_Shl64,
19371                                                           unop( Iop_1Uto64,
19372                                                                 normal[i]),
19373                                                           mkU8( 52 ) ) ) ),
19374                                      mkU8( (1-i)*64 ) ),
19375                               mkexpr( new_XT[i] ) ) );
19376             }
19377             putVSReg( XT, mkexpr( new_XT[2] ) );
19378 
19379          } else if (inst_select == 7) {
19380             IRTemp sub_element0 = newTemp( Ity_V128 );
19381             IRTemp sub_element1 = newTemp( Ity_V128 );
19382 
19383             DIP("xxbrh v%d, v%d\n", (UInt)XT, (UInt)XB);
19384 
19385             assign( sub_element0,
19386                     binop( Iop_ShrV128,
19387                            binop( Iop_AndV128,
19388                                   binop(Iop_64HLtoV128,
19389                                         mkU64( 0xFF00FF00FF00FF00 ),
19390                                         mkU64( 0xFF00FF00FF00FF00 ) ),
19391                                   mkexpr( vB ) ),
19392                            mkU8( 8 ) ) );
19393             assign( sub_element1,
19394                     binop( Iop_ShlV128,
19395                            binop( Iop_AndV128,
19396                                   binop(Iop_64HLtoV128,
19397                                         mkU64( 0x00FF00FF00FF00FF ),
19398                                         mkU64( 0x00FF00FF00FF00FF ) ),
19399                                   mkexpr( vB ) ),
19400                            mkU8( 8 ) ) );
19401 
19402             putVSReg(XT, binop( Iop_OrV128,
19403                                 mkexpr( sub_element1 ),
19404                                 mkexpr( sub_element0 ) ) );
19405 
19406          } else if (inst_select == 8) {
19407             DIP("xvxexpsp v%d,v%d\n", XT, XB);
19408 
19409             putVSReg( XT, binop( Iop_ShrV128,
19410                                  binop( Iop_AndV128,
19411                                         mkexpr( vB ),
19412                                         binop( Iop_64HLtoV128,
19413                                                mkU64( 0x7F8000007F800000 ),
19414                                                mkU64( 0x7F8000007F800000 ) ) ),
19415                                  mkU8( 23 ) ) );
19416          } else if (inst_select == 9) {
19417             Int i;
19418             IRExpr *normal[4];
19419             IRTemp value[4];
19420             IRTemp new_value[4];
19421             IRTemp new_XT[5];
19422 
19423             DIP("xvxsigsp v%d,v%d\n", XT, XB);
19424             new_XT[0] = newTemp(Ity_V128);
19425             assign( new_XT[0], binop( Iop_64HLtoV128,
19426                                       mkU64( 0x0 ),
19427                                       mkU64( 0x0 ) ) );
19428 
19429             for (i = 0; i < 4; i++) {
19430                value[i] = newTemp(Ity_I32);
19431                assign( value[i],
19432                        unop( Iop_64to32,
19433                              unop( Iop_V128to64,
19434                                    binop( Iop_AndV128,
19435                                           binop( Iop_ShrV128,
19436                                                  mkexpr( vB ),
19437                                                  mkU8( (3-i)*32 ) ),
19438                                           binop( Iop_64HLtoV128,
19439                                                  mkU64( 0x0 ),
19440                                                  mkU64( 0xFFFFFFFF ) ) ) ) ) );
19441 
19442                new_XT[i+1] = newTemp(Ity_V128);
19443 
19444                /* Value is normal if it isn't infinite, zero or denormalized */
19445                normal[i] = mkNOT1( mkOR1(
19446                                          mkOR1( is_NaN( Ity_I32, value[i] ),
19447                                                 is_Inf( Ity_I32, value[i] ) ),
19448                                          mkOR1( is_Zero( Ity_I32, value[i] ),
19449                                                 is_Denorm( Ity_I32,
19450                                                            value[i] ) ) ) );
19451                new_value[i] = newTemp(Ity_I32);
19452                assign( new_value[i],
19453                        binop( Iop_Or32,
19454                               binop( Iop_And32,
19455                                      mkexpr( value[i] ),
19456                                      mkU32( 0x7FFFFF ) ),
19457                               binop( Iop_Shl32,
19458                                      unop( Iop_1Uto32,
19459                                            normal[i]),
19460                                      mkU8( 23 ) ) ) );
19461 
19462                assign( new_XT[i+1],
19463                        binop( Iop_OrV128,
19464                               binop( Iop_ShlV128,
19465                                      binop( Iop_64HLtoV128,
19466                                             mkU64( 0x0 ),
19467                                             binop( Iop_32HLto64,
19468                                                    mkU32( 0x0 ),
19469                                                    mkexpr( new_value[i] ) ) ),
19470                                      mkU8( (3-i)*32 ) ),
19471                               mkexpr( new_XT[i] ) ) );
19472             }
19473             putVSReg( XT, mkexpr( new_XT[4] ) );
19474 
19475          } else if (inst_select == 15) {
19476             IRTemp sub_element0 = newTemp( Ity_V128 );
19477             IRTemp sub_element1 = newTemp( Ity_V128 );
19478             IRTemp sub_element2 = newTemp( Ity_V128 );
19479             IRTemp sub_element3 = newTemp( Ity_V128 );
19480 
19481             DIP("xxbrw v%d, v%d\n", (UInt)XT, (UInt)XB);
19482 
19483             assign( sub_element0,
19484                     binop( Iop_ShrV128,
19485                            binop( Iop_AndV128,
19486                                   binop(Iop_64HLtoV128,
19487                                         mkU64( 0xFF000000FF000000 ),
19488                                         mkU64( 0xFF000000FF000000 ) ),
19489                                   mkexpr( vB ) ),
19490                            mkU8( 24 ) ) );
19491             assign( sub_element1,
19492                     binop( Iop_ShrV128,
19493                            binop( Iop_AndV128,
19494                                   binop(Iop_64HLtoV128,
19495                                         mkU64( 0x00FF000000FF0000 ),
19496                                         mkU64( 0x00FF000000FF0000 ) ),
19497                                   mkexpr( vB ) ),
19498                            mkU8( 8 ) ) );
19499             assign( sub_element2,
19500                     binop( Iop_ShlV128,
19501                            binop( Iop_AndV128,
19502                                   binop(Iop_64HLtoV128,
19503                                         mkU64( 0x0000FF000000FF00 ),
19504                                         mkU64( 0x0000FF000000FF00 ) ),
19505                                   mkexpr( vB ) ),
19506                            mkU8( 8 ) ) );
19507             assign( sub_element3,
19508                     binop( Iop_ShlV128,
19509                            binop( Iop_AndV128,
19510                                   binop(Iop_64HLtoV128,
19511                                         mkU64( 0x00000000FF000000FF ),
19512                                         mkU64( 0x00000000FF000000FF ) ),
19513                                   mkexpr( vB ) ),
19514                            mkU8( 24 ) ) );
19515 
19516             putVSReg( XT,
19517                       binop( Iop_OrV128,
19518                              binop( Iop_OrV128,
19519                                     mkexpr( sub_element3 ),
19520                                     mkexpr( sub_element2 ) ),
19521                              binop( Iop_OrV128,
19522                                     mkexpr( sub_element1 ),
19523                                     mkexpr( sub_element0 ) ) ) );
19524 
19525          } else if (inst_select == 23) {
19526             DIP("xxbrd v%d, v%d\n", (UInt)XT, (UInt)XB);
19527 
19528             int i;
19529             int shift = 56;
19530             IRTemp sub_element[16];
19531             IRTemp new_xT[17];
19532 
19533             new_xT[0] = newTemp( Ity_V128 );
19534             assign( new_xT[0], binop( Iop_64HLtoV128,
19535                                       mkU64( 0 ),
19536                                       mkU64( 0 ) ) );
19537 
19538             for ( i = 0; i < 4; i++ ) {
19539                new_xT[i+1] = newTemp( Ity_V128 );
19540                sub_element[i]   = newTemp( Ity_V128 );
19541                sub_element[i+4] = newTemp( Ity_V128 );
19542 
19543                assign( sub_element[i],
19544                        binop( Iop_ShrV128,
19545                               binop( Iop_AndV128,
19546                                      binop( Iop_64HLtoV128,
19547                                             mkU64( (0xFFULL << (7 - i) * 8) ),
19548                                             mkU64( (0xFFULL << (7 - i) * 8) ) ),
19549                                      mkexpr( vB ) ),
19550                               mkU8( shift ) ) );
19551 
19552                assign( sub_element[i+4],
19553                        binop( Iop_ShlV128,
19554                               binop( Iop_AndV128,
19555                                      binop( Iop_64HLtoV128,
19556                                             mkU64( (0xFFULL << i*8) ),
19557                                             mkU64( (0xFFULL << i*8) ) ),
19558                                      mkexpr( vB ) ),
19559                               mkU8( shift ) ) );
19560                shift = shift - 16;
19561 
19562                assign( new_xT[i+1],
19563                        binop( Iop_OrV128,
19564                               mkexpr( new_xT[i] ),
19565                               binop( Iop_OrV128,
19566                                      mkexpr ( sub_element[i] ),
19567                                      mkexpr ( sub_element[i+4] ) ) ) );
19568                }
19569 
19570             putVSReg( XT, mkexpr( new_xT[4] ) );
19571 
19572          } else if (inst_select == 24) {
19573             // xvcvhpsp, (VSX Vector Convert half-precision format to
19574             //           Single-precision format)
19575             /* only supported on ISA 3.0 and newer */
19576             IRTemp result = newTemp( Ity_V128 );
19577             IRTemp src  = newTemp( Ity_I64 );
19578 
19579             if (!allow_isa_3_0) return False;
19580 
19581             DIP("xvcvhpsp v%d,v%d\n", XT,XB);
19582             /* The instruction does not set the C or FPCC fields.  The
19583              * instruction takes four 16-bit values stored in a 128-bit value
19584              * as follows:   x V | x V | x V | x V  where V is a 16-bit
19585              * value and x is an unused 16-bit value. To use Iop_F16toF32x4
19586              * the four 16-bit values will be gathered into a single 64 bit
19587              * value.  The backend will scatter the four 16-bit values back
19588              * into a 128-bit operand before issuing the instruction.
19589              */
19590             /* Gather 16-bit float values from V128 source into new 64-bit
19591              * source value for the Iop.
19592              */
19593             assign( src,
19594                     unop( Iop_V128to64,
19595                           binop( Iop_Perm8x16,
19596                                  mkexpr( vB ),
19597                                  binop ( Iop_64HLtoV128,
19598                                          mkU64( 0 ),
19599                                          mkU64( 0x020306070A0B0E0F) ) ) ) );
19600 
19601             assign( result, unop( Iop_F16toF32x4, mkexpr( src ) ) );
19602 
19603             putVSReg( XT, mkexpr( result ) );
19604 
19605          } else if (inst_select == 25) {
19606             // xvcvsphp, (VSX Vector round and Convert single-precision
19607             // format to half-precision format)
19608             /* only supported on ISA 3.0 and newer */
19609             IRTemp result = newTemp( Ity_V128 );
19610             IRTemp tmp64  = newTemp( Ity_I64 );
19611 
19612             if (!allow_isa_3_0) return False;
19613             DIP("xvcvsphp v%d,v%d\n", XT,XB);
19614 
19615             /* Iop_F32toF16x4 is V128 -> I64, scatter the 16-bit floats in the
19616              * I64 result to the V128 register to store.
19617              */
19618             assign( tmp64, unop( Iop_F32toF16x4, mkexpr( vB ) ) );
19619 
19620             /* Scatter 16-bit float values from returned 64-bit value
19621              * of V128 result.
19622              */
19623             if (host_endness == VexEndnessLE)
19624                /* Note location 0 may have a valid number in it.  Location
19625                 * 15 should always be zero.  Use 0xF to put zeros in the
19626                 * desired bytes.
19627                 */
19628                assign( result,
19629                        binop( Iop_Perm8x16,
19630                               binop( Iop_64HLtoV128,
19631                                      mkexpr( tmp64 ),
19632                                      mkU64( 0 ) ),
19633                               binop ( Iop_64HLtoV128,
19634                                       mkU64( 0x0F0F00010F0F0203 ),
19635                                       mkU64( 0x0F0F04050F0F0607 ) ) ) );
19636             else
19637                assign( result,
19638                        binop( Iop_Perm8x16,
19639                               binop( Iop_64HLtoV128,
19640                                      mkexpr( tmp64 ),
19641                                      mkU64( 0 ) ),
19642                               binop ( Iop_64HLtoV128,
19643                                       mkU64( 0x0F0F06070F0F0405 ),
19644                                       mkU64( 0x0F0F02030F0F0001 ) ) ) );
19645             putVSReg( XT, mkexpr( result ) );
19646 
19647          } else if ( inst_select == 31 ) {
19648             int i;
19649             int shift_left = 8;
19650             int shift_right = 120;
19651             IRTemp sub_element[16];
19652             IRTemp new_xT[9];
19653 
19654             DIP("xxbrq v%d, v%d\n", (UInt) XT, (UInt) XB);
19655 
19656             new_xT[0] = newTemp( Ity_V128 );
19657             assign( new_xT[0], binop( Iop_64HLtoV128,
19658                                       mkU64( 0 ),
19659                                       mkU64( 0 ) ) );
19660 
19661             for ( i = 0; i < 8; i++ ) {
19662                new_xT[i+1] = newTemp( Ity_V128 );
19663                sub_element[i]   = newTemp( Ity_V128 );
19664                sub_element[i+8] = newTemp( Ity_V128 );
19665 
19666                assign( sub_element[i],
19667                        binop( Iop_ShrV128,
19668                               binop( Iop_AndV128,
19669                                      binop( Iop_64HLtoV128,
19670                                             mkU64( ( 0xFFULL << (7 - i) * 8 ) ),
19671                                             mkU64( 0x0ULL ) ),
19672                                      mkexpr( vB ) ),
19673                               mkU8( shift_right ) ) );
19674                shift_right = shift_right - 16;
19675 
19676                assign( sub_element[i+8],
19677                        binop( Iop_ShlV128,
19678                               binop( Iop_AndV128,
19679                                      binop( Iop_64HLtoV128,
19680                                             mkU64( 0x0ULL ),
19681                                             mkU64( ( 0xFFULL << (7 - i) * 8 ) ) ),
19682                                      mkexpr( vB ) ),
19683                               mkU8( shift_left ) ) );
19684                shift_left = shift_left + 16;
19685 
19686                assign( new_xT[i+1],
19687                        binop( Iop_OrV128,
19688                               mkexpr( new_xT[i] ),
19689                               binop( Iop_OrV128,
19690                                      mkexpr ( sub_element[i] ),
19691                                      mkexpr ( sub_element[i+8] ) ) ) );
19692                }
19693 
19694             putVSReg( XT, mkexpr( new_xT[8] ) );
19695 
19696          } else {
19697             vex_printf("dis_vxs_misc(ppc) Invalid instruction selection\n");
19698             return False;
19699          }
19700          break;
19701       }
19702 
19703       case 0x3D4: // xvtstdcdp (VSX Test Data Class Double-Precision)
19704       {
19705          UInt DX_mask = IFIELD( theInstr, 16, 5 );
19706          UInt DC_mask = IFIELD( theInstr, 6, 1 );
19707          UInt DM_mask = IFIELD( theInstr, 2, 1 );
19708          UInt DCMX_mask = (DC_mask << 6) | (DM_mask << 5) | DX_mask;
19709 
19710          IRTemp NaN[2], inf[2], zero[2], dnorm[2], pos[2], DCM[2];
19711          IRTemp match_value[2];
19712          IRTemp value[2];
19713          Int i;
19714 
19715          DIP("xvtstdcdp v%d,v%d,%d\n", (UInt)XT, (UInt)XB, DCMX_mask);
19716 
19717          for (i = 0; i < 2; i++) {
19718             NaN[i] = newTemp(Ity_I64);
19719             inf[i] = newTemp(Ity_I64);
19720             pos[i] = newTemp(Ity_I64);
19721             DCM[i] = newTemp(Ity_I64);
19722             zero[i] = newTemp(Ity_I64);
19723             dnorm[i] = newTemp(Ity_I64);
19724 
19725             value[i] = newTemp(Ity_I64);
19726             match_value[i] = newTemp(Ity_I64);
19727 
19728             assign( value[i],
19729                     unop( Iop_V128to64,
19730                           binop( Iop_AndV128,
19731                                  binop( Iop_ShrV128,
19732                                         mkexpr( vB ),
19733                                         mkU8( (1-i)*64 ) ),
19734                                  binop( Iop_64HLtoV128,
19735                                         mkU64( 0x0 ),
19736                                         mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ) );
19737 
19738             assign( pos[i], unop( Iop_1Uto64,
19739                                  binop( Iop_CmpEQ64,
19740                                         binop( Iop_Shr64,
19741                                                mkexpr( value[i] ),
19742                                                mkU8( 63 ) ),
19743                                         mkU64( 0 ) ) ) );
19744 
19745             assign( NaN[i], unop( Iop_1Uto64, is_NaN( Ity_I64, value[i] ) ) );
19746             assign( inf[i], unop( Iop_1Uto64, is_Inf( Ity_I64, value[i] ) ) );
19747             assign( zero[i], unop( Iop_1Uto64, is_Zero( Ity_I64, value[i] ) ) );
19748             assign( dnorm[i], unop( Iop_1Uto64, is_Denorm( Ity_I64,
19749                                                            value[i] ) ) );
19750 
19751             assign( DCM[i], create_DCM( Ity_I64, NaN[i], inf[i], zero[i],
19752                                         dnorm[i], pos[i] ) );
19753 
19754             assign( match_value[i],
19755                     unop( Iop_1Sto64,
19756                           binop( Iop_CmpNE64,
19757                                  binop( Iop_And64,
19758                                         mkU64( DCMX_mask ),
19759                                         mkexpr( DCM[i] ) ),
19760                                  mkU64( 0 ) ) ) );
19761          }
19762          putVSReg( XT, binop( Iop_64HLtoV128,
19763                               mkexpr( match_value[0] ),
19764                               mkexpr( match_value[1] ) ) );
19765       }
19766       break;
19767 
19768       case 0x3E0:  // xviexpdp (VSX Vector Insert Exponent Double-Precision)
19769       {
19770             Int i;
19771             IRTemp new_XT[3];
19772             IRTemp A_value[2];
19773             IRTemp B_value[2];
19774             IRExpr *sign[2], *expr[2], *fract[2];
19775 
19776             DIP("xviexpdp v%d,v%d\n", XT, XB);
19777             new_XT[0] = newTemp(Ity_V128);
19778             assign( new_XT[0], binop( Iop_64HLtoV128,
19779                                       mkU64( 0x0 ),
19780                                       mkU64( 0x0 ) ) );
19781 
19782             for (i = 0; i < 2; i++) {
19783                A_value[i] = newTemp(Ity_I64);
19784                B_value[i] = newTemp(Ity_I64);
19785 
19786                assign( A_value[i],
19787                        unop( Iop_V128to64,
19788                              binop( Iop_AndV128,
19789                                     binop( Iop_ShrV128,
19790                                            mkexpr( vA ),
19791                                            mkU8( (1-i)*64 ) ),
19792                                     binop( Iop_64HLtoV128,
19793                                            mkU64( 0x0 ),
19794                                            mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ) );
19795                assign( B_value[i],
19796                        unop( Iop_V128to64,
19797                              binop( Iop_AndV128,
19798                                     binop( Iop_ShrV128,
19799                                            mkexpr( vB ),
19800                                            mkU8( (1-i)*64 ) ),
19801                                     binop( Iop_64HLtoV128,
19802                                            mkU64( 0x0 ),
19803                                            mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) ) );
19804 
19805                sign[i] = binop( Iop_And64, mkexpr( A_value[i] ),
19806                                 mkU64( 0x8000000000000000 ) );
19807                expr[i] = binop( Iop_Shl64,
19808                                 binop( Iop_And64, mkexpr( B_value[i] ),
19809                                        mkU64( 0x7FF ) ),
19810                                 mkU8( 52 ) );
19811                fract[i] = binop( Iop_And64, mkexpr( A_value[i] ),
19812                                  mkU64( 0x000FFFFFFFFFFFFF ) );
19813 
19814                new_XT[i+1] = newTemp(Ity_V128);
19815                assign( new_XT[i+1],
19816                        binop( Iop_OrV128,
19817                               binop( Iop_ShlV128,
19818                                      binop( Iop_64HLtoV128,
19819                                             mkU64( 0 ),
19820                                             binop( Iop_Or64,
19821                                                    binop( Iop_Or64,
19822                                                           sign[i],
19823                                                           expr[i] ),
19824                                                    fract[i] ) ),
19825                                      mkU8( (1-i)*64 ) ),
19826                               mkexpr( new_XT[i] ) ) );
19827             }
19828             putVSReg( XT, mkexpr( new_XT[2] ) );
19829       }
19830       break;
19831 
19832       default:
19833          vex_printf( "dis_vxs_misc(ppc)(opc2)\n" );
19834          return False;
19835    }
19836    return True;
19837 }
19838 
19839 /*
19840  * VSX vector miscellaneous instructions
19841  */
19842 
19843 static Bool
dis_vx_misc(UInt theInstr,UInt opc2)19844 dis_vx_misc ( UInt theInstr, UInt opc2 )
19845 {
19846    /* XX3-Form */
19847    UChar XT = ifieldRegXT ( theInstr );
19848    UChar XA = ifieldRegXA ( theInstr );
19849    UChar XB = ifieldRegXB ( theInstr );
19850    IRTemp vA = newTemp( Ity_V128 );
19851    IRTemp vB = newTemp( Ity_V128 );
19852    IRTemp src1 = newTemp(Ity_I64);
19853    IRTemp src2 = newTemp(Ity_I64);
19854    IRTemp result_mask = newTemp(Ity_I64);
19855    IRTemp cmp_mask = newTemp(Ity_I64);
19856    IRTemp nan_mask = newTemp(Ity_I64);
19857    IRTemp snan_mask = newTemp(Ity_I64);
19858    IRTemp word_result = newTemp(Ity_I64);
19859    IRTemp check_result = newTemp(Ity_I64);
19860    IRTemp xT = newTemp( Ity_V128 );
19861    IRTemp nan_cmp_value = newTemp(Ity_I64);
19862    UInt trap_enabled = 0;  /* 0 - trap enabled is False */
19863 
19864    assign( vA, getVSReg( XA ) );
19865    assign( vB, getVSReg( XB ) );
19866    assign( xT, getVSReg( XT ) );
19867 
19868    assign(src1, unop( Iop_V128HIto64, mkexpr( vA ) ) );
19869    assign(src2, unop( Iop_V128HIto64, mkexpr( vB ) ) );
19870 
19871    assign( nan_mask,
19872            binop( Iop_Or64,
19873                   unop( Iop_1Sto64, is_NaN( Ity_I64, src1 ) ),
19874                   unop( Iop_1Sto64, is_NaN( Ity_I64, src2 ) ) ) );
19875 
19876    if ( trap_enabled == 0 )
19877       /* Traps on invalid operation are assumed not enabled, assign
19878          result of comparison to xT.
19879       */
19880       assign( snan_mask, mkU64( 0 ) );
19881 
19882    else
19883       assign( snan_mask,
19884               binop( Iop_Or64,
19885                      unop( Iop_1Sto64, is_sNaN( Ity_I64, src1 ) ),
19886                      unop( Iop_1Sto64, is_sNaN( Ity_I64, src2 ) ) ) );
19887 
19888    assign (result_mask, binop( Iop_Or64,
19889                                mkexpr( snan_mask ),
19890                                mkexpr( nan_mask ) ) );
19891 
19892    switch (opc2) {
19893    case 0xC: //xscmpeqdp
19894       {
19895          DIP("xscmpeqdp v%d,v%d,v%d\n", XT, XA, XB);
19896          /* extract double-precision floating point source values from
19897             double word 0 */
19898 
19899          /* result of Iop_CmpF64 is 0x40 if operands are equal,
19900             mask is all 1's if equal. */
19901 
19902          assign( cmp_mask,
19903                  unop( Iop_1Sto64,
19904                        unop(Iop_32to1,
19905                             binop(Iop_Shr32,
19906                                   binop( Iop_CmpF64,
19907                                          unop( Iop_ReinterpI64asF64,
19908                                                mkexpr( src1 ) ),
19909                                          unop( Iop_ReinterpI64asF64,
19910                                                mkexpr( src2 ) ) ),
19911                                   mkU8( 6 ) ) ) ) );
19912 
19913          assign( word_result,
19914                  binop( Iop_Or64,
19915                         binop( Iop_And64, mkexpr( cmp_mask ),
19916                                mkU64( 0xFFFFFFFFFFFFFFFF ) ),
19917                         binop( Iop_And64,
19918                                unop( Iop_Not64, mkexpr( cmp_mask ) ),
19919                                mkU64( 0x0 ) ) ) );
19920          assign( nan_cmp_value, mkU64( 0 ) );
19921          break;
19922       }
19923 
19924    case 0x2C: //xscmpgtdp
19925       {
19926          DIP("xscmpgtdp v%d,v%d,v%d\n", XT, XA, XB);
19927          /* Test for src1 > src2 */
19928 
19929          /* Result of Iop_CmpF64 is 0x1 if op1 < op2, set mask to all 1's. */
19930          assign( cmp_mask,
19931                  unop( Iop_1Sto64,
19932                        unop(Iop_32to1,
19933                             binop(Iop_CmpF64,
19934                                   unop( Iop_ReinterpI64asF64,
19935                                         mkexpr( src2 ) ),
19936                                   unop( Iop_ReinterpI64asF64,
19937                                        mkexpr( src1 ) ) ) ) ) );
19938          assign( word_result,
19939                  binop( Iop_Or64,
19940                         binop( Iop_And64, mkexpr( cmp_mask ),
19941                                mkU64( 0xFFFFFFFFFFFFFFFF ) ),
19942                         binop( Iop_And64,
19943                                unop( Iop_Not64, mkexpr( cmp_mask ) ),
19944                                mkU64( 0x0 ) ) ) );
19945          assign( nan_cmp_value, mkU64( 0 ) );
19946          break;
19947       }
19948 
19949    case 0x4C: //xscmpgedp
19950       {
19951          DIP("xscmpeqdp v%d,v%d,v%d\n", XT, XA, XB);
19952          /* compare src 1 >= src 2 */
19953          /* result of Iop_CmpF64 is 0x40 if operands are equal,
19954             mask is all 1's if equal. */
19955          assign( cmp_mask,
19956                  unop( Iop_1Sto64,
19957                        unop(Iop_32to1,
19958                             binop( Iop_Or32,
19959                                    binop( Iop_Shr32,
19960                                           binop(Iop_CmpF64,   /* EQ test */
19961                                                 unop( Iop_ReinterpI64asF64,
19962                                                       mkexpr( src1 ) ),
19963                                                 unop( Iop_ReinterpI64asF64,
19964                                                       mkexpr( src2 ) ) ),
19965                                           mkU8( 6 ) ),
19966                                    binop(Iop_CmpF64,  /* src2 < src 1 test */
19967                                          unop( Iop_ReinterpI64asF64,
19968                                                mkexpr( src2 ) ),
19969                                          unop( Iop_ReinterpI64asF64,
19970                                                mkexpr( src1 ) ) ) ) ) ) );
19971          assign( word_result,
19972                  binop( Iop_Or64,
19973                         binop( Iop_And64, mkexpr( cmp_mask ),
19974                                mkU64( 0xFFFFFFFFFFFFFFFF ) ),
19975                         binop( Iop_And64,
19976                                unop( Iop_Not64, mkexpr( cmp_mask ) ),
19977                                mkU64( 0x0 ) ) ) );
19978          assign( nan_cmp_value, mkU64( 0 ) );
19979          break;
19980       }
19981 
19982    case 0x200: //xsmaxcdp
19983       {
19984          DIP("xsmaxcdp v%d,v%d,v%d\n", XT, XA, XB);
19985          /* extract double-precision floating point source values from
19986             double word 0 */
19987 
19988          /* result of Iop_CmpF64 is 0x1 if arg1 LT then arg2, */
19989          assign( cmp_mask,
19990                  unop( Iop_1Sto64,
19991                        unop( Iop_32to1,
19992                              binop(Iop_CmpF64,
19993                                    unop( Iop_ReinterpI64asF64,
19994                                          mkexpr( src2 ) ),
19995                                    unop( Iop_ReinterpI64asF64,
19996                                          mkexpr( src1 ) ) ) ) ) );
19997          assign( word_result,
19998                  binop( Iop_Or64,
19999                         binop( Iop_And64, mkexpr( cmp_mask ), mkexpr( src1 ) ),
20000                         binop( Iop_And64,
20001                                unop( Iop_Not64, mkexpr( cmp_mask ) ),
20002                                mkexpr( src2 ) ) ) );
20003          assign( nan_cmp_value, mkexpr( src2 ) );
20004          break;
20005       }
20006 
20007    case 0x220: //xsmincdp
20008       {
20009          DIP("xsmincdp v%d,v%d,v%d\n", XT, XA, XB);
20010          /* extract double-precision floating point source values from
20011             double word 0 */
20012 
20013          /* result of Iop_CmpF64 is 0x1 if arg1 less then arg2, */
20014          assign( cmp_mask,
20015                  unop( Iop_1Sto64,
20016                        unop( Iop_32to1,
20017                              binop(Iop_CmpF64,
20018                                    unop( Iop_ReinterpI64asF64,
20019                                          mkexpr( src1 ) ),
20020                                    unop( Iop_ReinterpI64asF64,
20021                                          mkexpr( src2 ) ) ) ) ) );
20022          assign( word_result,
20023                  binop( Iop_Or64,
20024                         binop( Iop_And64, mkexpr( cmp_mask ), mkexpr( src1 ) ),
20025                         binop( Iop_And64,
20026                                unop( Iop_Not64, mkexpr( cmp_mask ) ),
20027                                mkexpr( src2 ) ) ) );
20028          assign( nan_cmp_value, mkexpr( src2 ) );
20029          break;
20030       }
20031 
20032    default:
20033       vex_printf( "dis_vx_misc(ppc)(opc2)\n" );
20034       return False;
20035    }
20036 
20037    /* If either argument is NaN, result is src2.  If either argument is
20038       SNaN, we are supposed to generate invalid operation exception.
20039       Currently don't support generating exceptions.  In case of an
20040       trap enabled invalid operation (SNaN) XT is not changed. The
20041       snan_mask is setup appropriately for trap enabled or not.
20042    */
20043    assign( check_result,
20044            binop( Iop_Or64,
20045                   binop( Iop_And64, mkexpr( snan_mask ),
20046                          unop( Iop_V128HIto64, mkexpr( xT ) ) ),
20047                   binop( Iop_And64, unop( Iop_Not64,
20048                                           mkexpr( snan_mask ) ),
20049                          binop( Iop_Or64,
20050                                 binop( Iop_And64, mkexpr( nan_mask ),
20051                                        mkexpr( nan_cmp_value ) ),
20052                                 binop( Iop_And64,
20053                                        unop( Iop_Not64,
20054                                              mkexpr( nan_mask ) ),
20055                                        mkU64( 0 ) ) ) ) ) );
20056 
20057    /* If SNaN is true, then the result is unchanged if a trap-enabled
20058       Invalid Operation occurs.  Result mask already setup for trap-enabled
20059       case.
20060    */
20061    putVSReg( XT,
20062              binop( Iop_64HLtoV128,
20063                     binop( Iop_Or64,
20064                            binop( Iop_And64,
20065                                   unop( Iop_Not64, mkexpr( result_mask ) ),
20066                                   mkexpr( word_result ) ),
20067                            binop( Iop_And64,
20068                                   mkexpr( result_mask ),
20069                                   mkexpr( check_result ) ) ),
20070                     mkU64( 0 ) ) );
20071    return True;
20072 }
20073 
20074 /*
20075  * VSX Logical Instructions
20076  */
20077 static Bool
dis_vx_logic(UInt theInstr,UInt opc2)20078 dis_vx_logic ( UInt theInstr, UInt opc2 )
20079 {
20080    /* XX3-Form */
20081    UChar opc1 = ifieldOPC( theInstr );
20082    UChar XT = ifieldRegXT ( theInstr );
20083    UChar XA = ifieldRegXA ( theInstr );
20084    UChar XB = ifieldRegXB ( theInstr );
20085    IRTemp vA = newTemp( Ity_V128 );
20086    IRTemp vB = newTemp( Ity_V128 );
20087 
20088    if (opc1 != 0x3C) {
20089       vex_printf( "dis_vx_logic(ppc)(instr)\n" );
20090       return False;
20091    }
20092 
20093    assign( vA, getVSReg( XA ) );
20094    assign( vB, getVSReg( XB ) );
20095 
20096    switch (opc2) {
20097       case 0x268: // xxlxor
20098          DIP("xxlxor v%d,v%d,v%d\n", XT, XA, XB);
20099          putVSReg( XT, binop( Iop_XorV128, mkexpr( vA ), mkexpr( vB ) ) );
20100          break;
20101       case 0x248: // xxlor
20102          DIP("xxlor v%d,v%d,v%d\n", XT, XA, XB);
20103          putVSReg( XT, binop( Iop_OrV128, mkexpr( vA ), mkexpr( vB ) ) );
20104          break;
20105       case 0x288: // xxlnor
20106          DIP("xxlnor v%d,v%d,v%d\n", XT, XA, XB);
20107          putVSReg( XT, unop( Iop_NotV128, binop( Iop_OrV128, mkexpr( vA ),
20108                                                  mkexpr( vB ) ) ) );
20109          break;
20110       case 0x208: // xxland
20111          DIP("xxland v%d,v%d,v%d\n", XT, XA, XB);
20112          putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), mkexpr( vB ) ) );
20113          break;
20114       case 0x228: //xxlandc
20115          DIP("xxlandc v%d,v%d,v%d\n", XT, XA, XB);
20116          putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), unop( Iop_NotV128,
20117                                                                mkexpr( vB ) ) ) );
20118          break;
20119       case 0x2A8: // xxlorc (VSX Logical OR with complement)
20120          DIP("xxlorc v%d,v%d,v%d\n", XT, XA, XB);
20121          putVSReg( XT, binop( Iop_OrV128,
20122                               mkexpr( vA ),
20123                               unop( Iop_NotV128, mkexpr( vB ) ) ) );
20124          break;
20125       case 0x2C8: // xxlnand (VSX Logical NAND)
20126          DIP("xxlnand v%d,v%d,v%d\n", XT, XA, XB);
20127          putVSReg( XT, unop( Iop_NotV128,
20128                              binop( Iop_AndV128, mkexpr( vA ),
20129                                     mkexpr( vB ) ) ) );
20130          break;
20131       case 0x2E8: // xxleqv (VSX Logical Equivalence)
20132          DIP("xxleqv v%d,v%d,v%d\n", XT, XA, XB);
20133          putVSReg( XT, unop( Iop_NotV128,
20134                              binop( Iop_XorV128,
20135                              mkexpr( vA ), mkexpr( vB ) ) ) );
20136          break;
20137       default:
20138          vex_printf( "dis_vx_logic(ppc)(opc2)\n" );
20139          return False;
20140    }
20141    return True;
20142 }
20143 
20144 /*
20145  * VSX Load Instructions
20146  * NOTE: VSX supports word-aligned storage access.
20147  */
20148 static Bool
dis_vx_load(UInt theInstr)20149 dis_vx_load ( UInt theInstr )
20150 {
20151    /* XX1-Form */
20152    UChar opc1 = ifieldOPC( theInstr );
20153    UChar XT = ifieldRegXT ( theInstr );
20154    UChar rA_addr = ifieldRegA( theInstr );
20155    UChar rB_addr = ifieldRegB( theInstr );
20156    UInt opc2 = ifieldOPClo10( theInstr );
20157 
20158    IRType ty = mode64 ? Ity_I64 : Ity_I32;
20159    IRTemp EA = newTemp( ty );
20160 
20161    if (opc1 != 0x1F) {
20162       vex_printf( "dis_vx_load(ppc)(instr)\n" );
20163       return False;
20164    }
20165 
20166    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
20167 
20168    switch (opc2) {
20169    case 0x00C: // lxsiwzx (Load VSX Scalar as Integer Word and Zero Indexed)
20170    {
20171       IRExpr * exp;
20172       DIP("lxsiwzx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
20173 
20174       if (host_endness == VexEndnessLE)
20175          exp = unop( Iop_64to32, load( Ity_I64, mkexpr( EA ) ) );
20176       else
20177          exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) );
20178 
20179       putVSReg( XT, binop( Iop_64HLtoV128,
20180                            unop( Iop_32Uto64, exp),
20181                            mkU64(0) ) );
20182       break;
20183    }
20184    case 0x04C: // lxsiwax (Load VSX Scalar as Integer Word Algebraic Indexed)
20185    {
20186       IRExpr * exp;
20187       DIP("lxsiwax %d,r%u,r%u\n", XT, rA_addr, rB_addr);
20188 
20189       if (host_endness == VexEndnessLE)
20190          exp = unop( Iop_64to32, load( Ity_I64, mkexpr( EA ) ) );
20191       else
20192          exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) );
20193 
20194       putVSReg( XT, binop( Iop_64HLtoV128,
20195                            unop( Iop_32Sto64, exp),
20196                            mkU64(0) ) );
20197       break;
20198    }
20199    case 0x10C: // lxvx
20200    {
20201       UInt ea_off = 0;
20202       IRExpr* irx_addr;
20203       IRTemp word[4];
20204       int i;
20205 
20206       DIP("lxvx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
20207 
20208       if ( host_endness == VexEndnessBE ) {
20209          for ( i = 3; i>= 0; i-- ) {
20210             word[i] = newTemp( Ity_I64 );
20211 
20212             irx_addr =
20213                binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
20214                       ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20215 
20216             assign( word[i], unop( Iop_32Uto64,
20217                                    load( Ity_I32, irx_addr ) ) );
20218             ea_off += 4;
20219          }
20220 
20221          putVSReg( XT, binop( Iop_64HLtoV128,
20222                               binop( Iop_Or64,
20223                                      mkexpr( word[2] ),
20224                                      binop( Iop_Shl64,
20225                                             mkexpr( word[3] ),
20226                                             mkU8( 32 ) ) ),
20227                               binop( Iop_Or64,
20228                                      mkexpr( word[0] ),
20229                                      binop( Iop_Shl64,
20230                                             mkexpr( word[1] ),
20231                                             mkU8( 32 ) ) ) ) );
20232       } else {
20233          for ( i = 0; i< 4; i++ ) {
20234             word[i] = newTemp( Ity_I64 );
20235 
20236             irx_addr =
20237                binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
20238                       ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20239 
20240             assign( word[i], unop( Iop_32Uto64,
20241                                    load( Ity_I32, irx_addr ) ) );
20242             ea_off += 4;
20243          }
20244 
20245          putVSReg( XT, binop( Iop_64HLtoV128,
20246                               binop( Iop_Or64,
20247                                      mkexpr( word[2] ),
20248                                      binop( Iop_Shl64,
20249                                             mkexpr( word[3] ),
20250                                             mkU8( 32 ) ) ),
20251                               binop( Iop_Or64,
20252                                      mkexpr( word[0] ),
20253                                      binop( Iop_Shl64,
20254                                             mkexpr( word[1] ),
20255                                             mkU8( 32 ) ) ) ) );
20256       }
20257       break;
20258    }
20259 
20260    case 0x10D: // lxvl
20261    {
20262       DIP("lxvl %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
20263 
20264       IRTemp byte[16];
20265       UInt i;
20266       UInt ea_off = 0;
20267       IRExpr* irx_addr;
20268       IRTemp tmp_low[9];
20269       IRTemp tmp_hi[9];
20270       IRTemp shift = newTemp( Ity_I8 );
20271       IRTemp nb_gt16 = newTemp( Ity_I8 );
20272       IRTemp ld_result = newTemp( Ity_V128 );
20273       IRTemp nb_not_zero = newTemp( Ity_I64 );
20274 
20275       IRTemp base_addr = newTemp( ty );
20276 
20277       tmp_low[0] = newTemp( Ity_I64 );
20278       tmp_hi[0] = newTemp( Ity_I64 );
20279 
20280       assign( base_addr, ea_rAor0( rA_addr ) );
20281       assign( tmp_low[0], mkU64( 0 ) );
20282       assign( tmp_hi[0], mkU64( 0 ) );
20283 
20284       /* shift is 15 - nb, where nb = rB[0:7], used to zero out upper bytes */
20285       assign( nb_not_zero, unop( Iop_1Sto64,
20286                                   binop( Iop_CmpNE64,
20287                                          mkU64( 0 ),
20288                                          binop( Iop_Shr64,
20289                                                 getIReg( rB_addr ),
20290                                                 mkU8( 56 ) ) ) ) );
20291 
20292       assign( nb_gt16, unop( Iop_1Sto8,
20293                              binop( Iop_CmpLT64U,
20294                                     binop( Iop_Shr64,
20295                                            getIReg( rB_addr ),
20296                                            mkU8( 60 ) ),
20297                                     mkU64( 1 ) ) ) );
20298 
20299       /* Set the shift to 0, by ANDing with nb_gt16.  nb_gt16 will be all
20300        * zeros if nb > 16.  This will result in quad word load being stored.
20301        */
20302       assign( shift,
20303               binop( Iop_And8,
20304                      unop( Iop_64to8,
20305                            binop( Iop_Mul64,
20306                                   binop( Iop_Sub64,
20307                                          mkU64 ( 16 ),
20308                                          binop( Iop_Shr64,
20309                                                 getIReg( rB_addr ),
20310                                                 mkU8( 56 ) ) ),
20311                                   mkU64( 8 ) ) ),
20312                      mkexpr( nb_gt16 ) ) );
20313 
20314       /* fetch all 16 bytes, we will remove what we don't want later */
20315       if ( host_endness == VexEndnessBE ) {
20316          for ( i = 0; i < 8; i++ ) {
20317             byte[i] = newTemp( Ity_I64 );
20318             tmp_hi[i+1] = newTemp( Ity_I64 );
20319 
20320             irx_addr =
20321                binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
20322                       ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20323             ea_off += 1;
20324 
20325             assign( byte[i], binop( Iop_Shl64,
20326                                       unop( Iop_8Uto64,
20327                                             load( Ity_I8, irx_addr ) ),
20328                                       mkU8( 8 * ( 7 - i ) ) ) );
20329 
20330             assign( tmp_hi[i+1], binop( Iop_Or64,
20331                                         mkexpr( byte[i] ),
20332                                         mkexpr( tmp_hi[i] ) ) );
20333          }
20334 
20335          for ( i = 0; i < 8; i++ ) {
20336             byte[i+8] = newTemp( Ity_I64 );
20337             tmp_low[i+1] = newTemp( Ity_I64 );
20338 
20339             irx_addr =
20340                binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
20341                       ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20342             ea_off += 1;
20343 
20344             assign( byte[i+8], binop( Iop_Shl64,
20345                                     unop( Iop_8Uto64,
20346                                           load( Ity_I8, irx_addr ) ),
20347                                     mkU8( 8 * ( 7 - i ) ) ) );
20348 
20349             assign( tmp_low[i+1], binop( Iop_Or64,
20350                                          mkexpr( byte[i+8] ),
20351                                          mkexpr( tmp_low[i] ) ) );
20352          }
20353          assign( ld_result, binop( Iop_ShlV128,
20354                                    binop( Iop_ShrV128,
20355                                           binop( Iop_64HLtoV128,
20356                                                  mkexpr( tmp_hi[8] ),
20357                                                  mkexpr( tmp_low[8] ) ),
20358                                           mkexpr( shift ) ),
20359                                    mkexpr( shift ) ) );
20360       } else {
20361          for ( i = 0; i < 8; i++ ) {
20362             byte[i] = newTemp( Ity_I64 );
20363             tmp_low[i+1] = newTemp( Ity_I64 );
20364 
20365             irx_addr =
20366                binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
20367                       ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20368             ea_off += 1;
20369 
20370             assign( byte[i], binop( Iop_Shl64,
20371                                     unop( Iop_8Uto64,
20372                                           load( Ity_I8, irx_addr ) ),
20373                                     mkU8( 8 * i ) ) );
20374 
20375             assign( tmp_low[i+1],
20376                     binop( Iop_Or64,
20377                            mkexpr( byte[i] ), mkexpr( tmp_low[i] ) ) );
20378          }
20379 
20380          for ( i = 0; i < 8; i++ ) {
20381             byte[i + 8] = newTemp( Ity_I64 );
20382             tmp_hi[i+1] = newTemp( Ity_I64 );
20383 
20384             irx_addr =
20385                binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
20386                       ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20387             ea_off += 1;
20388 
20389             assign( byte[i+8], binop( Iop_Shl64,
20390                                       unop( Iop_8Uto64,
20391                                             load( Ity_I8, irx_addr ) ),
20392                                       mkU8( 8 * i ) ) );
20393 
20394             assign( tmp_hi[i+1], binop( Iop_Or64,
20395                                         mkexpr( byte[i+8] ),
20396                                         mkexpr( tmp_hi[i] ) ) );
20397          }
20398          assign( ld_result, binop( Iop_ShrV128,
20399                                    binop( Iop_ShlV128,
20400                                           binop( Iop_64HLtoV128,
20401                                                  mkexpr( tmp_hi[8] ),
20402                                                  mkexpr( tmp_low[8] ) ),
20403                                           mkexpr( shift ) ),
20404                                    mkexpr( shift ) ) );
20405       }
20406 
20407 
20408       /* If nb = 0, mask out the calculated load result so the stored
20409        * value is zero.
20410        */
20411 
20412       putVSReg( XT, binop( Iop_AndV128,
20413                            mkexpr( ld_result ),
20414                            binop( Iop_64HLtoV128,
20415                                   mkexpr( nb_not_zero ),
20416                                   mkexpr( nb_not_zero ) ) ) );
20417       break;
20418    }
20419 
20420    case 0x12D: // lxvll (Load VSX Vector Left-Justified with Length XX1 form)
20421    {
20422       IRTemp byte[16];
20423       IRTemp tmp_low[9];
20424       IRTemp tmp_hi[9];
20425       IRTemp mask = newTemp(Ity_V128);
20426       IRTemp rB = newTemp( Ity_I64 );
20427       IRTemp nb = newTemp( Ity_I64 );
20428       IRTemp nb_zero = newTemp(Ity_V128);
20429       IRTemp mask_shift = newTemp(Ity_I64);
20430       Int i;
20431       UInt ea_off = 0;
20432       IRExpr* irx_addr;
20433       IRTemp base_addr = newTemp( ty );
20434       IRTemp nb_compare_zero = newTemp( Ity_I64 );
20435 
20436       DIP("lxvll %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
20437 
20438       tmp_low[0] = newTemp(Ity_I64);
20439       tmp_hi[0] = newTemp(Ity_I64);
20440 
20441       assign( rB, getIReg(rB_addr));
20442       assign( base_addr, ea_rAor0( rA_addr ) );
20443       assign( tmp_low[0], mkU64( 0 ) );
20444       assign( tmp_hi[0], mkU64( 0 ) );
20445 
20446       /* mask_shift is number of 16 bytes minus (nb times 8-bits per byte) */
20447       assign( nb, binop( Iop_Shr64, mkexpr( rB ), mkU8( 56 )  ) );
20448 
20449       assign( nb_compare_zero, unop( Iop_1Sto64,
20450                                      binop( Iop_CmpEQ64,
20451                                             mkexpr( nb ),
20452                                             mkU64( 0 ) ) ) );
20453 
20454       /* nb_zero is 0xFF..FF if the nb_field = 0 */
20455       assign( nb_zero, binop( Iop_64HLtoV128,
20456                               mkexpr( nb_compare_zero ),
20457                               mkexpr( nb_compare_zero ) ) );
20458 
20459       assign( mask_shift, binop( Iop_Sub64,
20460                                  mkU64( 16*8 ),
20461                                  binop( Iop_Mul64,
20462                                         mkexpr( nb ),
20463                                         mkU64( 8 ) ) ) );
20464 
20465       /* fetch all 16 bytes, we will remove what we don't want later */
20466       for (i = 0; i < 8; i++) {
20467          byte[i] = newTemp(Ity_I64);
20468          tmp_hi[i+1] = newTemp(Ity_I64);
20469 
20470          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
20471                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20472          ea_off += 1;
20473 
20474          /* Instruction always loads in Big Endian format */
20475          assign( byte[i], binop( Iop_Shl64,
20476                                  unop( Iop_8Uto64,
20477                                        load( Ity_I8, irx_addr ) ),
20478                                  mkU8( 8 * (7 - i) ) ) );
20479          assign( tmp_hi[i+1],
20480                  binop( Iop_Or64,
20481                         mkexpr( byte[i] ), mkexpr( tmp_hi[i] ) ) );
20482       }
20483 
20484       for (i = 0; i < 8; i++) {
20485          byte[i + 8]  = newTemp(Ity_I64);
20486          tmp_low[i+1] = newTemp(Ity_I64);
20487 
20488          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
20489                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20490          ea_off += 1;
20491 
20492          /* Instruction always loads in Big Endian format */
20493         assign( byte[i+8], binop( Iop_Shl64,
20494                                    unop( Iop_8Uto64,
20495                                          load( Ity_I8, irx_addr ) ),
20496                                    mkU8( 8 * (7 - i) ) ) );
20497          assign( tmp_low[i+1], binop( Iop_Or64,
20498                                       mkexpr( byte[i+8] ),
20499                                       mkexpr( tmp_low[i] ) ) );
20500       }
20501 
20502       /* Create mask to clear the right most 16 - nb bytes, set to zero
20503        * if nb= 0.
20504        */
20505       assign( mask, binop( Iop_AndV128,
20506                           binop( Iop_ShlV128,
20507                                   binop( Iop_ShrV128,
20508                                          mkV128( 0xFFFF ),
20509                                          unop( Iop_64to8, mkexpr( mask_shift ) ) ),
20510                                   unop( Iop_64to8, mkexpr( mask_shift ) ) ),
20511                            unop( Iop_NotV128, mkexpr( nb_zero ) ) ) );
20512 
20513       putVSReg( XT, binop( Iop_AndV128,
20514                            mkexpr( mask ),
20515                            binop( Iop_64HLtoV128,
20516                                   mkexpr( tmp_hi[8] ),
20517                                   mkexpr( tmp_low[8] ) ) ) );
20518       break;
20519    }
20520 
20521    case 0x16C: // lxvwsx
20522    {
20523       IRTemp data = newTemp( Ity_I64 );
20524 
20525       DIP("lxvwsx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
20526 
20527       /* The load is a 64-bit fetch that is Endian aware, just want
20528        * the lower 32 bits. */
20529       if ( host_endness == VexEndnessBE ) {
20530          UInt ea_off = 4;
20531          IRExpr* irx_addr;
20532 
20533          irx_addr =
20534             binop( mkSzOp( ty, Iop_Sub8 ), mkexpr( EA ),
20535                    ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20536 
20537          assign( data, binop( Iop_And64,
20538                               load( Ity_I64, irx_addr ),
20539                               mkU64( 0xFFFFFFFF ) ) );
20540 
20541       } else {
20542          assign( data, binop( Iop_And64,
20543                               load( Ity_I64, mkexpr( EA ) ),
20544                               mkU64( 0xFFFFFFFF ) ) );
20545       }
20546 
20547       /* Take lower 32-bits and spat across the four word positions */
20548       putVSReg( XT,
20549                 binop( Iop_64HLtoV128,
20550                        binop( Iop_Or64,
20551                               mkexpr( data ),
20552                               binop( Iop_Shl64,
20553                                      mkexpr( data ),
20554                                      mkU8( 32 ) ) ),
20555                        binop( Iop_Or64,
20556                               mkexpr( data ),
20557                               binop( Iop_Shl64,
20558                                      mkexpr( data ),
20559                                      mkU8( 32 ) ) ) ) );
20560       break;
20561    }
20562 
20563    case 0x20C: // lxsspx (Load VSX Scalar Single-Precision Indexed)
20564    {
20565       IRExpr * exp;
20566       DIP("lxsspx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
20567       /* Take 32-bit floating point value in the upper half of the fetched
20568        * 64-bit value, convert to 64-bit floating point value and load into
20569        * top word of V128.
20570        */
20571       exp = unop( Iop_ReinterpF64asI64,
20572                   unop( Iop_F32toF64,
20573                         unop( Iop_ReinterpI32asF32,
20574                               load( Ity_I32, mkexpr( EA ) ) ) ) );
20575 
20576       putVSReg( XT, binop( Iop_64HLtoV128, exp, mkU64( 0 ) ) );
20577       break;
20578    }
20579    case 0x24C: // lxsdx
20580    {
20581       IRExpr * exp;
20582       DIP("lxsdx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
20583       exp = load( Ity_I64, mkexpr( EA ) );
20584       // We need to pass an expression of type Ity_V128 with putVSReg, but the load
20585       // we just performed is only a DW.  But since the contents of VSR[XT] element 1
20586       // are undefined after this operation, we can just do a splat op.
20587       putVSReg( XT, binop( Iop_64HLtoV128, exp, exp ) );
20588       break;
20589    }
20590 
20591    case 0x30D: // lxsibzx
20592    {
20593       IRExpr *byte;
20594       IRExpr* irx_addr;
20595 
20596       DIP("lxsibzx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
20597 
20598       if ( host_endness == VexEndnessBE )
20599          irx_addr = binop( Iop_Sub64, mkexpr( EA ), mkU64( 7 ) );
20600 
20601       else
20602          irx_addr = mkexpr( EA );
20603 
20604       byte = load( Ity_I64, irx_addr );
20605       putVSReg( XT, binop( Iop_64HLtoV128,
20606                             binop( Iop_And64,
20607                                    byte,
20608                                    mkU64( 0xFF ) ),
20609                            mkU64( 0 ) ) );
20610       break;
20611    }
20612 
20613    case 0x32D: // lxsihzx
20614    {
20615       IRExpr *byte;
20616       IRExpr* irx_addr;
20617 
20618       DIP("lxsihzx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
20619 
20620       if ( host_endness == VexEndnessBE )
20621          irx_addr = binop( Iop_Sub64, mkexpr( EA ), mkU64( 6 ) );
20622 
20623       else
20624          irx_addr = mkexpr( EA );
20625 
20626       byte = load( Ity_I64, irx_addr );
20627       putVSReg( XT, binop( Iop_64HLtoV128,
20628                             binop( Iop_And64,
20629                                    byte,
20630                                    mkU64( 0xFFFF ) ),
20631                            mkU64( 0 ) ) );
20632       break;
20633    }
20634    case 0x34C: // lxvd2x
20635    {
20636       IRExpr *t128;
20637       DIP("lxvd2x %d,r%u,r%u\n", XT, rA_addr, rB_addr);
20638       t128 = load( Ity_V128, mkexpr( EA ) );
20639 
20640       /* The data in the vec register should be in big endian order.
20641          So if we just did a little endian load then swap around the
20642          high and low double words. */
20643       if (host_endness == VexEndnessLE) {
20644          IRTemp high = newTemp(Ity_I64);
20645          IRTemp low = newTemp(Ity_I64);
20646          assign( high, unop(Iop_V128HIto64, t128) );
20647          assign( low, unop(Iop_V128to64, t128) );
20648          t128 = binop( Iop_64HLtoV128, mkexpr (low), mkexpr (high) );
20649       }
20650 
20651       putVSReg( XT, t128 );
20652       break;
20653    }
20654    case 0x14C: // lxvdsx
20655    {
20656       IRTemp data = newTemp(Ity_I64);
20657       DIP("lxvdsx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
20658       assign( data, load( Ity_I64, mkexpr( EA ) ) );
20659       putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( data ), mkexpr( data ) ) );
20660       break;
20661    }
20662    case 0x30C:
20663    {
20664       IRExpr *t0;
20665 
20666       DIP("lxvw4x %d,r%u,r%u\n", XT, rA_addr, rB_addr);
20667 
20668       /* The load will result in the data being in BE order. */
20669       if (host_endness == VexEndnessLE) {
20670          IRExpr *t0_BE;
20671          IRTemp perm_LE = newTemp(Ity_V128);
20672 
20673          t0_BE = load( Ity_V128, mkexpr( EA ) );
20674 
20675          /*  Permute the data to LE format */
20676          assign( perm_LE, binop( Iop_64HLtoV128, mkU64(0x0c0d0e0f08090a0bULL),
20677                                  mkU64(0x0405060700010203ULL)));
20678 
20679          t0 = binop( Iop_Perm8x16, t0_BE, mkexpr(perm_LE) );
20680       } else {
20681          t0 = load( Ity_V128, mkexpr( EA ) );
20682       }
20683 
20684       putVSReg( XT, t0 );
20685       break;
20686    }
20687 
20688    case 0x32C: // lxvh8x
20689    {
20690       DIP("lxvh8x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
20691 
20692       IRTemp h_word[8];
20693       int i;
20694       UInt ea_off = 0;
20695       IRExpr* irx_addr;
20696       IRTemp tmp_low[5];
20697       IRTemp tmp_hi[5];
20698 
20699       tmp_low[0] = newTemp( Ity_I64 );
20700       tmp_hi[0] = newTemp( Ity_I64 );
20701       assign( tmp_low[0], mkU64( 0 ) );
20702       assign( tmp_hi[0], mkU64( 0 ) );
20703 
20704       for ( i = 0; i < 4; i++ ) {
20705          h_word[i]    = newTemp(Ity_I64);
20706          tmp_low[i+1] = newTemp(Ity_I64);
20707 
20708          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
20709                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20710          ea_off += 2;
20711 
20712          assign( h_word[i], binop( Iop_Shl64,
20713                                    unop( Iop_16Uto64,
20714                                          load( Ity_I16, irx_addr ) ),
20715                                    mkU8( 16 * ( 3 - i ) ) ) );
20716 
20717          assign( tmp_low[i+1],
20718                  binop( Iop_Or64,
20719                         mkexpr( h_word[i] ), mkexpr( tmp_low[i] ) ) );
20720       }
20721 
20722       for ( i = 0; i < 4; i++ ) {
20723          h_word[i+4]   = newTemp( Ity_I64 );
20724          tmp_hi[i+1] = newTemp( Ity_I64 );
20725 
20726          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
20727                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20728          ea_off += 2;
20729 
20730          assign( h_word[i+4], binop( Iop_Shl64,
20731                                      unop( Iop_16Uto64,
20732                                            load( Ity_I16, irx_addr ) ),
20733                                      mkU8( 16 * ( 3 - i ) ) ) );
20734 
20735          assign( tmp_hi[i+1], binop( Iop_Or64,
20736                                      mkexpr( h_word[i+4] ),
20737                                      mkexpr( tmp_hi[i] ) ) );
20738       }
20739       putVSReg( XT, binop( Iop_64HLtoV128,
20740                            mkexpr( tmp_low[4] ), mkexpr( tmp_hi[4] ) ) );
20741       break;
20742    }
20743 
20744    case 0x36C: // lxvb16x
20745    {
20746       DIP("lxvb16x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
20747 
20748       /* The result of lxvb16x should be the same on big and little
20749          endian systems. We do a host load, then reverse the bytes in
20750          the double words. If the host load was little endian we swap
20751          them around again. */
20752 
20753       IRTemp high = newTemp(Ity_I64);
20754       IRTemp high_rev = newTemp(Ity_I64);
20755       IRTemp low = newTemp(Ity_I64);
20756       IRTemp low_rev = newTemp(Ity_I64);
20757 
20758       IRExpr *t128 = load( Ity_V128, mkexpr( EA ) );
20759 
20760       assign( high, unop(Iop_V128HIto64, t128) );
20761       assign( high_rev, unop(Iop_Reverse8sIn64_x1, mkexpr(high)) );
20762       assign( low, unop(Iop_V128to64, t128) );
20763       assign( low_rev, unop(Iop_Reverse8sIn64_x1, mkexpr(low)) );
20764 
20765       if (host_endness == VexEndnessLE)
20766          t128 = binop( Iop_64HLtoV128, mkexpr (low_rev), mkexpr (high_rev) );
20767       else
20768          t128 = binop( Iop_64HLtoV128, mkexpr (high_rev), mkexpr (low_rev) );
20769 
20770       putVSReg( XT, t128 );
20771       break;
20772    }
20773 
20774    default:
20775       vex_printf( "dis_vx_load(ppc)(opc2)\n" );
20776       return False;
20777    }
20778    return True;
20779 }
20780 
20781 /*
20782  * VSX Move Instructions
20783  */
20784 static Bool
dis_vx_move(UInt theInstr)20785 dis_vx_move ( UInt theInstr )
20786 {
20787    /* XX1-Form */
20788    UChar opc1 = ifieldOPC( theInstr );
20789    UChar XS = ifieldRegXS( theInstr );
20790    UChar rA_addr = ifieldRegA( theInstr );
20791    UChar rB_addr = ifieldRegB( theInstr );
20792    IRTemp vS = newTemp( Ity_V128 );
20793    UInt opc2 = ifieldOPClo10( theInstr );
20794    IRType ty = Ity_I64;
20795 
20796    if ( opc1 != 0x1F ) {
20797       vex_printf( "dis_vx_move(ppc)(instr)\n" );
20798       return False;
20799    }
20800 
20801    switch (opc2) {
20802    case 0x133: // mfvsrld RA,XS   Move From VSR Lower Doubleword
20803       DIP("mfvsrld %d,r%u\n", (UInt)XS, rA_addr);
20804 
20805       assign( vS, getVSReg( XS ) );
20806       putIReg( rA_addr, unop(Iop_V128to64, mkexpr( vS) ) );
20807 
20808       break;
20809 
20810    case 0x193: // mfvsrdd  XT,RA,RB  Move to VSR Double Doubleword
20811    {
20812       IRTemp tmp = newTemp( Ity_I32 );
20813 
20814       DIP("mfvsrdd %d,r%u\n", (UInt)XS, rA_addr);
20815 
20816       assign( tmp, unop( Iop_64to32, getIReg(rA_addr) ) );
20817       assign( vS, binop( Iop_64HLtoV128,
20818                          binop( Iop_32HLto64,
20819                                 mkexpr( tmp ),
20820                                 mkexpr( tmp ) ),
20821                          binop( Iop_32HLto64,
20822                                 mkexpr( tmp ),
20823                                 mkexpr( tmp ) ) ) );
20824       putVSReg( XS, mkexpr( vS ) );
20825    }
20826    break;
20827 
20828    case 0x1B3: // mtvsrws  XT,RA  Move to VSR word & Splat
20829    {
20830       IRTemp rA = newTemp( ty );
20831       IRTemp rB = newTemp( ty );
20832 
20833       DIP("mfvsrws %d,r%u\n", (UInt)XS, rA_addr);
20834 
20835       if ( rA_addr == 0 )
20836          assign( rA, mkU64 ( 0 ) );
20837       else
20838          assign( rA, getIReg(rA_addr) );
20839 
20840       assign( rB, getIReg(rB_addr) );
20841       assign( vS, binop( Iop_64HLtoV128, mkexpr( rA ), mkexpr( rB ) ) );
20842       putVSReg( XS, mkexpr( vS ) );
20843    }
20844    break;
20845 
20846    default:
20847       vex_printf( "dis_vx_move(ppc)(opc2)\n" );
20848       return False;
20849    }
20850    return True;
20851 }
20852 
20853 /*
20854  * VSX Store Instructions
20855  * NOTE: VSX supports word-aligned storage access.
20856  */
20857 static Bool
dis_vx_store(UInt theInstr)20858 dis_vx_store ( UInt theInstr )
20859 {
20860    /* XX1-Form */
20861    UChar opc1 = ifieldOPC( theInstr );
20862    UChar XS = ifieldRegXS( theInstr );
20863    UChar rA_addr = ifieldRegA( theInstr );
20864    UChar rB_addr = ifieldRegB( theInstr );
20865    IRTemp vS = newTemp( Ity_V128 );
20866    UInt opc2 = ifieldOPClo10( theInstr );
20867 
20868    IRType ty = mode64 ? Ity_I64 : Ity_I32;
20869    IRTemp EA = newTemp( ty );
20870 
20871    if (opc1 != 0x1F) {
20872       vex_printf( "dis_vx_store(ppc)(instr)\n" );
20873       return False;
20874    }
20875 
20876    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
20877    assign( vS, getVSReg( XS ) );
20878 
20879    switch (opc2) {
20880    case 0x08C:
20881    {
20882      /* Need the next to the most significant 32-bit word from
20883       * the 128-bit vector.
20884       */
20885       IRExpr * high64, * low32;
20886       DIP("stxsiwx %d,r%u,r%u\n", XS, rA_addr, rB_addr);
20887       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
20888       low32  = unop( Iop_64to32, high64 );
20889       store( mkexpr( EA ), low32 );
20890       break;
20891    }
20892 
20893    case 0x18C: // stxvx Store VSX Vector Indexed
20894    {
20895       UInt ea_off = 0;
20896       IRExpr* irx_addr;
20897       IRTemp word0 = newTemp( Ity_I64 );
20898       IRTemp word1 = newTemp( Ity_I64 );
20899       IRTemp word2 = newTemp( Ity_I64 );
20900       IRTemp word3 = newTemp( Ity_I64 );
20901       DIP("stxvx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
20902 
20903       assign( word0,  binop( Iop_Shr64,
20904                              unop( Iop_V128HIto64, mkexpr( vS ) ),
20905                              mkU8( 32 ) ) );
20906 
20907       assign( word1, binop( Iop_And64,
20908                             unop( Iop_V128HIto64, mkexpr( vS ) ),
20909                             mkU64( 0xFFFFFFFF ) ) );
20910 
20911       assign( word2, binop( Iop_Shr64,
20912                             unop( Iop_V128to64, mkexpr( vS ) ),
20913                             mkU8( 32 ) ) );
20914 
20915       assign( word3, binop( Iop_And64,
20916                             unop( Iop_V128to64, mkexpr( vS ) ),
20917                             mkU64( 0xFFFFFFFF ) ) );
20918 
20919       if (host_endness == VexEndnessBE) {
20920          store( mkexpr( EA ), unop( Iop_64to32, mkexpr( word0 ) ) );
20921 
20922          ea_off += 4;
20923          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
20924                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20925 
20926          store( irx_addr, unop( Iop_64to32, mkexpr( word1 ) ) );
20927 
20928          ea_off += 4;
20929          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
20930                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20931 
20932          store( irx_addr, unop( Iop_64to32, mkexpr( word2 ) ) );
20933          ea_off += 4;
20934          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
20935                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20936 
20937          store( irx_addr, unop( Iop_64to32, mkexpr( word3 ) ) );
20938       } else {
20939          store( mkexpr( EA ), unop( Iop_64to32, mkexpr( word3 ) ) );
20940 
20941          ea_off += 4;
20942          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
20943                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20944 
20945          store( irx_addr, unop( Iop_64to32, mkexpr( word2 ) ) );
20946 
20947          ea_off += 4;
20948          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
20949                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20950 
20951          store( irx_addr, unop( Iop_64to32, mkexpr( word1 ) ) );
20952          ea_off += 4;
20953          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
20954                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
20955 
20956          store( irx_addr, unop( Iop_64to32, mkexpr( word0 ) ) );
20957       }
20958       break;
20959    }
20960 
20961    case 0x18D: // stxvl Store VSX Vector Indexed
20962    {
20963       UInt ea_off = 0;
20964       IRExpr* irx_addr;
20965       IRTemp word0 = newTemp( Ity_I64 );
20966       IRTemp word1 = newTemp( Ity_I64 );
20967       IRTemp word2 = newTemp( Ity_I64 );
20968       IRTemp word3 = newTemp( Ity_I64 );
20969       IRTemp shift = newTemp( Ity_I8 );
20970       IRTemp nb_gt16 = newTemp( Ity_I8 );
20971       IRTemp nb_zero = newTemp( Ity_V128 );
20972       IRTemp nb = newTemp( Ity_I8 );
20973       IRTemp nb_field = newTemp( Ity_I64 );
20974       IRTemp n_bytes = newTemp( Ity_I8 );
20975       IRTemp base_addr = newTemp( ty );
20976       IRTemp current_mem = newTemp( Ity_V128 );
20977       IRTemp store_val = newTemp( Ity_V128 );
20978       IRTemp nb_mask = newTemp( Ity_V128 );
20979 
20980       DIP("stxvl %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
20981 
20982       assign( nb_field, binop( Iop_Shr64,
20983                                getIReg(rB_addr),
20984                                mkU8( 56 ) ) );
20985 
20986       assign( nb, unop( Iop_64to8, mkexpr( nb_field ) ) );
20987 
20988       /* nb_gt16 will be all zeros if nb > 16 */
20989       assign( nb_gt16, unop( Iop_1Sto8,
20990                              binop( Iop_CmpLT64U,
20991                                     binop( Iop_Shr64,
20992                                            mkexpr( nb_field ),
20993                                            mkU8( 4 ) ),
20994                                     mkU64( 1 ) ) ) );
20995 
20996       /* nb_zero is 0xFF..FF if the nb_field = 0 */
20997       assign( nb_zero, binop( Iop_64HLtoV128,
20998                               unop( Iop_1Sto64,
20999                                     binop( Iop_CmpEQ64,
21000                                            mkexpr( nb_field ),
21001                                            mkU64( 0 ) ) ),
21002                               unop( Iop_1Sto64,
21003                                     binop( Iop_CmpEQ64,
21004                                            mkexpr( nb_field ),
21005                                            mkU64( 0 ) ) ) ) );
21006 
21007       /* set n_bytes to 0 if nb >= 16.  Otherwise, set to nb. */
21008       assign( n_bytes, binop( Iop_And8, mkexpr( nb ), mkexpr( nb_gt16 ) ) );
21009       assign( shift, unop( Iop_64to8,
21010                            binop( Iop_Mul64,
21011                                   binop( Iop_Sub64,
21012                                          mkU64( 16 ),
21013                                          unop( Iop_8Uto64,
21014                                                mkexpr( n_bytes ) ) ),
21015                                   mkU64( 8 ) ) ) );
21016 
21017       /* We only have a 32-bit store function. So, need to fetch the
21018        * contents of memory merge with the store value and do two
21019        * 32-byte stores so we preserve the contents of memory not
21020        * addressed by nb.
21021        */
21022       assign( base_addr, ea_rAor0( rA_addr ) );
21023 
21024       assign( current_mem,
21025               binop( Iop_64HLtoV128,
21026                      load( Ity_I64,
21027                            binop( mkSzOp( ty, Iop_Add8 ),
21028                                   mkexpr( base_addr ),
21029                                   ty == Ity_I64 ? mkU64( 8 ) : mkU32( 8 )
21030                                   ) ),
21031 		     load( Ity_I64, mkexpr( base_addr ) ) ) );
21032 
21033       /* Set the nb_mask to all zeros if nb = 0 so the current contents
21034        * of memory get written back without modifications.
21035        *
21036        * The store_val is a combination of the current memory value
21037        * and the bytes you want to store.  The nb_mask selects the
21038        * bytes you want stored from Vs.
21039        */
21040        assign( nb_mask,
21041                binop( Iop_OrV128,
21042                       binop( Iop_AndV128,
21043                              mkexpr( nb_zero ),
21044                              mkV128( 0 ) ),
21045                       binop( Iop_AndV128,
21046 			     binop( Iop_ShrV128,
21047 				    mkV128( 0xFFFF ),
21048 				    mkexpr( shift ) ),
21049                              unop( Iop_NotV128, mkexpr( nb_zero ) ) ) ) );
21050 
21051        assign( store_val,
21052                binop( Iop_OrV128,
21053                       binop( Iop_AndV128,
21054 			     mkexpr( vS ),
21055                              mkexpr( nb_mask ) ),
21056                       binop( Iop_AndV128,
21057                              unop( Iop_NotV128, mkexpr( nb_mask ) ),
21058                              mkexpr( current_mem) ) ) );
21059 
21060       /* Store the value in 32-byte chunks */
21061       assign( word0,  binop( Iop_Shr64,
21062                              unop( Iop_V128HIto64, mkexpr( store_val ) ),
21063                              mkU8( 32 ) ) );
21064 
21065       assign( word1, binop( Iop_And64,
21066                             unop( Iop_V128HIto64, mkexpr( store_val ) ),
21067                             mkU64( 0xFFFFFFFF ) ) );
21068 
21069       assign( word2, binop( Iop_Shr64,
21070                             unop( Iop_V128to64, mkexpr( store_val ) ),
21071                             mkU8( 32 ) ) );
21072 
21073       assign( word3, binop( Iop_And64,
21074                             unop( Iop_V128to64, mkexpr( store_val ) ),
21075                             mkU64( 0xFFFFFFFF ) ) );
21076 
21077       ea_off = 0;
21078       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
21079                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21080 
21081       store( irx_addr, unop( Iop_64to32, mkexpr( word3 ) ) );
21082 
21083       ea_off += 4;
21084       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
21085                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21086 
21087       store( irx_addr, unop( Iop_64to32, mkexpr( word2 ) ) );
21088 
21089       ea_off += 4;
21090       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
21091                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21092 
21093       store( irx_addr, unop( Iop_64to32, mkexpr( word1 ) ) );
21094 
21095       ea_off += 4;
21096       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
21097                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21098 
21099       store( irx_addr, unop( Iop_64to32, mkexpr( word0 ) ) );
21100       break;
21101    }
21102 
21103    case 0x1AD: // stxvll (Store VSX Vector Left-justified with length XX1-form)
21104    {
21105       UInt ea_off = 0;
21106       IRExpr* irx_addr;
21107       IRTemp word0[5];
21108       IRTemp word1[5];
21109       IRTemp word2[5];
21110       IRTemp word3[5];
21111       IRTemp shift = newTemp(Ity_I8);
21112       IRTemp nb_gt16 = newTemp(Ity_I8);
21113       IRTemp nb_zero = newTemp(Ity_V128);
21114       IRTemp nb = newTemp(Ity_I8);
21115       IRTemp nb_field = newTemp(Ity_I64);
21116       IRTemp n_bytes = newTemp(Ity_I8);
21117       IRTemp base_addr = newTemp( ty );
21118       IRTemp current_mem = newTemp(Ity_V128);
21119       IRTemp store_val = newTemp(Ity_V128);
21120       IRTemp nb_mask = newTemp(Ity_V128);
21121       IRTemp mask = newTemp( Ity_I64 );
21122       IRTemp byte[16];
21123       IRTemp tmp_low[9];
21124       IRTemp tmp_hi[9];
21125       IRTemp nb_field_compare_zero = newTemp( Ity_I64 );
21126       Int i;
21127 
21128       DIP("stxvll %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
21129 
21130       assign( nb_field, binop( Iop_Shr64,
21131                                getIReg(rB_addr),
21132                                mkU8( 56 ) ) );
21133       assign( nb, unop( Iop_64to8, mkexpr( nb_field ) ) );
21134       assign( mask, mkU64( 0xFFFFFFFFFFFFFFFFULL ) );
21135 
21136       /* nb_gt16 will be all zeros if nb > 16 */
21137       assign( nb_gt16, unop( Iop_1Sto8,
21138                              binop( Iop_CmpLT64U,
21139                                     binop( Iop_Shr64,
21140                                            mkexpr( nb_field ),
21141                                            mkU8( 4 ) ),
21142                                     mkU64( 1 ) ) ) );
21143 
21144       assign( nb_field_compare_zero, unop( Iop_1Sto64,
21145                                            binop( Iop_CmpEQ64,
21146                                                   mkexpr( nb_field ),
21147                                                   mkU64( 0 ) ) ) );
21148 
21149       /* nb_zero is 0xFF..FF if the nb_field = 0 */
21150       assign( nb_zero, binop( Iop_64HLtoV128,
21151                               mkexpr( nb_field_compare_zero ),
21152                               mkexpr( nb_field_compare_zero ) ) );
21153 
21154 
21155       /* set n_bytes to 0 if nb >= 16.  Otherwise, set to nb. */
21156       assign( n_bytes, binop( Iop_And8, mkexpr( nb ), mkexpr( nb_gt16 ) ) );
21157       assign( shift,
21158               unop( Iop_64to8,
21159                     binop( Iop_Mul64,
21160                            binop( Iop_Sub64,
21161                                   mkU64( 16 ),
21162                                   unop( Iop_8Uto64, mkexpr( n_bytes ) )),
21163                            mkU64( 8 ) ) ) );
21164 
21165       /* We only have a 32-bit store function. So, need to fetch the
21166        * contents of memory merge with the store value and do two
21167        * 32-byte stores so we preserve the contents of memory not
21168        * addressed by nb.
21169        */
21170       assign( base_addr, ea_rAor0( rA_addr ) );
21171       /* fetch all 16 bytes and store in Big Endian format */
21172       word0[0] = newTemp(Ity_I64);
21173       assign( word0[0], mkU64( 0 ) );
21174 
21175       word1[0] = newTemp(Ity_I64);
21176       assign( word1[0], mkU64( 0 ) );
21177 
21178       word2[0] = newTemp(Ity_I64);
21179       assign( word2[0], mkU64( 0 ) );
21180 
21181       word3[0] = newTemp(Ity_I64);
21182       assign( word3[0], mkU64( 0 ) );
21183 
21184       for (i = 0; i < 4; i++) {
21185          word0[i+1] = newTemp(Ity_I64);
21186 
21187          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
21188                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21189          ea_off += 1;
21190 
21191          /* Instruction always loads in Big Endian format */
21192          assign( word0[i+1],
21193                  binop( Iop_Or64,
21194                         binop( Iop_Shl64,
21195                                unop( Iop_8Uto64,
21196                                      load( Ity_I8,
21197                                            irx_addr ) ),
21198                                mkU8( (3-i)*8 ) ),
21199                         mkexpr( word0[i] ) ) );
21200       }
21201 
21202       for (i = 0; i < 4; i++) {
21203          word1[i+1] = newTemp(Ity_I64);
21204 
21205          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
21206                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21207          ea_off += 1;
21208 
21209          /* Instruction always loads in Big Endian format */
21210          assign( word1[i+1],
21211                  binop( Iop_Or64,
21212                         binop( Iop_Shl64,
21213                                unop( Iop_8Uto64,
21214                                      load( Ity_I8,
21215                                            irx_addr ) ),
21216                                mkU8( (3-i)*8 ) ),
21217                         mkexpr( word1[i] ) ) );
21218       }
21219       for (i = 0; i < 4; i++) {
21220          word2[i+1] = newTemp(Ity_I64);
21221 
21222          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
21223                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21224          ea_off += 1;
21225 
21226          /* Instruction always loads in Big Endian format */
21227          assign( word2[i+1],
21228                  binop( Iop_Or64,
21229                         binop( Iop_Shl64,
21230                                unop( Iop_8Uto64,
21231                                      load( Ity_I8,
21232                                            irx_addr ) ),
21233                                mkU8( (3-i)*8 ) ),
21234                         mkexpr( word2[i] ) ) );
21235       }
21236       for (i = 0; i < 4; i++) {
21237          word3[i+1] = newTemp(Ity_I64);
21238 
21239          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
21240                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21241          ea_off += 1;
21242 
21243          /* Instruction always loads in Big Endian format */
21244          assign( word3[i+1],
21245                  binop( Iop_Or64,
21246                         binop( Iop_Shl64,
21247                                unop( Iop_8Uto64,
21248                                      load( Ity_I8,
21249                                            irx_addr ) ),
21250                                mkU8( (3-i)*8 ) ),
21251                         mkexpr( word3[i] ) ) );
21252       }
21253 
21254 
21255       assign( current_mem,
21256               binop( Iop_64HLtoV128,
21257                      binop( Iop_Or64,
21258                             binop( Iop_Shl64,
21259                                    mkexpr( word0[4] ),
21260                                    mkU8( 32 ) ),
21261                             mkexpr( word1[4] ) ),
21262                      binop( Iop_Or64,
21263                             binop( Iop_Shl64,
21264                                    mkexpr( word2[4] ),
21265                                    mkU8( 32 ) ),
21266                             mkexpr( word3[4] ) ) ) );
21267 
21268       /* Set the nb_mask to all zeros if nb = 0 so the current contents
21269        * of memory get written back without modifications.
21270        *
21271        * The store_val is a combination of the current memory value
21272        * and the bytes you want to store.  The nb_mask selects the
21273        * bytes you want stored from Vs.
21274        */
21275       /* The instruction always uses Big Endian order */
21276       assign( nb_mask,
21277               binop( Iop_OrV128,
21278                      binop( Iop_AndV128,
21279                             binop( Iop_ShlV128,
21280                                    binop( Iop_ShrV128,
21281                                           binop( Iop_64HLtoV128,
21282                                                  mkexpr( mask ),
21283                                                  mkexpr( mask ) ),
21284                                           mkexpr( shift ) ),
21285                                    mkexpr( shift ) ),
21286                             unop( Iop_NotV128, mkexpr( nb_zero ) ) ),
21287                      binop( Iop_AndV128,
21288                             mkexpr( nb_zero ),
21289                             binop( Iop_64HLtoV128,
21290                                    mkU64( 0x0 ),
21291                                    mkU64( 0x0 ) ) ) ) );
21292 
21293       assign( store_val,
21294               binop( Iop_OrV128,
21295                      binop( Iop_AndV128,
21296                             mkexpr( vS ),
21297                             mkexpr( nb_mask ) ),
21298                      binop( Iop_AndV128,
21299                             unop( Iop_NotV128, mkexpr( nb_mask ) ),
21300                             mkexpr( current_mem) ) ) );
21301 
21302       /* store the merged value in Big Endian format */
21303       tmp_low[0] = newTemp(Ity_I64);
21304       tmp_hi[0] = newTemp(Ity_I64);
21305       assign( tmp_low[0], mkU64( 0 ) );
21306       assign( tmp_hi[0], mkU64( 0 ) );
21307 
21308       for (i = 0; i < 8; i++) {
21309          byte[i] = newTemp(Ity_I64);
21310          byte[i+8] = newTemp(Ity_I64);
21311          tmp_low[i+1] = newTemp(Ity_I64);
21312          tmp_hi[i+1]  = newTemp(Ity_I64);
21313 
21314          assign( byte[i], binop( Iop_And64,
21315                                  binop( Iop_Shr64,
21316                                         unop( Iop_V128HIto64,
21317                                               mkexpr( store_val ) ),
21318                                         mkU8( (7-i)*8 ) ),
21319                                  mkU64( 0xFF ) ) );
21320          assign( byte[i+8], binop( Iop_And64,
21321                                    binop( Iop_Shr64,
21322                                           unop( Iop_V128to64,
21323                                                 mkexpr( store_val ) ),
21324                                           mkU8( (7-i)*8 ) ),
21325                                    mkU64( 0xFF ) ) );
21326 
21327          assign( tmp_low[i+1],
21328                  binop( Iop_Or64,
21329                         mkexpr( tmp_low[i] ),
21330                         binop( Iop_Shl64, mkexpr( byte[i] ), mkU8( i*8 ) ) ) );
21331          assign( tmp_hi[i+1],
21332                  binop( Iop_Or64,
21333                         mkexpr( tmp_hi[i] ),
21334                         binop( Iop_Shl64, mkexpr( byte[i+8] ),
21335                                mkU8( i*8 ) ) ) );
21336       }
21337 
21338       /* Store the value in 32-byte chunks */
21339       ea_off = 0;
21340       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
21341                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21342 
21343       store( irx_addr, unop( Iop_64to32, mkexpr( tmp_low[8] ) ) );
21344 
21345       ea_off += 4;
21346       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
21347                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21348 
21349       store( irx_addr, unop( Iop_64HIto32, mkexpr( tmp_low[8] ) ) );
21350 
21351       ea_off += 4;
21352       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
21353                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21354 
21355       store( irx_addr, unop( Iop_64to32, mkexpr( tmp_hi[8] ) ) );
21356 
21357       ea_off += 4;
21358       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( base_addr ),
21359                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21360 
21361       store( irx_addr, unop( Iop_64HIto32, mkexpr( tmp_hi[8] ) ) );
21362 
21363       break;
21364       }
21365 
21366    case 0x28C:
21367    {
21368       IRTemp high64 = newTemp(Ity_F64);
21369       IRTemp val32  = newTemp(Ity_I32);
21370       DIP("stxsspx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
21371       assign(high64, unop( Iop_ReinterpI64asF64,
21372                            unop( Iop_V128HIto64, mkexpr( vS ) ) ) );
21373       assign(val32, unop( Iop_ReinterpF32asI32,
21374                           unop( Iop_TruncF64asF32,
21375                                 mkexpr(high64) ) ) );
21376       store( mkexpr( EA ), mkexpr( val32 ) );
21377       break;
21378    }
21379    case 0x2CC:
21380    {
21381       IRExpr * high64;
21382       DIP("stxsdx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
21383       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
21384       store( mkexpr( EA ), high64 );
21385       break;
21386    }
21387 
21388    case 0x38D: // stxsibx
21389    {
21390       IRExpr *stored_word;
21391       IRTemp byte_to_store = newTemp( Ity_I64 );
21392 
21393       DIP("stxsibx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
21394 
21395       /* Can't store just a byte, need to fetch the word at EA merge data
21396        * and store.
21397        */
21398       stored_word = load( Ity_I64, mkexpr( EA ) );
21399       assign( byte_to_store, binop( Iop_And64,
21400                                     unop( Iop_V128HIto64,
21401                                           mkexpr( vS ) ),
21402                                     mkU64( 0xFF ) ) );
21403 
21404       store( mkexpr( EA ), binop( Iop_Or64,
21405                                   binop( Iop_And64,
21406                                          stored_word,
21407                                          mkU64( 0xFFFFFFFFFFFFFF00 ) ),
21408                                   mkexpr( byte_to_store ) ) );
21409       break;
21410    }
21411 
21412    case 0x3AD: // stxsihx
21413    {
21414       IRExpr *stored_word;
21415       IRTemp byte_to_store = newTemp( Ity_I64 );
21416 
21417       DIP("stxsihx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
21418 
21419       /* Can't store just a halfword, need to fetch the word at EA merge data
21420        * and store.
21421        */
21422       stored_word = load( Ity_I64, mkexpr( EA ) );
21423       assign( byte_to_store, binop( Iop_And64,
21424                                     unop( Iop_V128HIto64,
21425                                           mkexpr( vS ) ),
21426                                     mkU64( 0xFFFF ) ) );
21427 
21428       store( mkexpr( EA ), binop( Iop_Or64,
21429                                   binop( Iop_And64,
21430                                          stored_word,
21431                                          mkU64( 0xFFFFFFFFFFFF0000 ) ),
21432                                   mkexpr( byte_to_store ) ) );
21433       break;
21434    }
21435 
21436    case 0x3CC:
21437    {
21438       IRExpr * high64, *low64;
21439       DIP("stxvd2x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
21440       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
21441       low64 = unop( Iop_V128to64, mkexpr( vS ) );
21442       store( mkexpr( EA ), high64 );
21443       store( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
21444                     ty == Ity_I64 ? mkU64( 8 ) : mkU32( 8 ) ), low64 );
21445       break;
21446    }
21447    case 0x38C:
21448    {
21449       UInt ea_off = 0;
21450       IRExpr* irx_addr;
21451       IRTemp hi64 = newTemp( Ity_I64 );
21452       IRTemp lo64 = newTemp( Ity_I64 );
21453 
21454       DIP("stxvw4x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
21455 
21456       // This instruction supports word-aligned stores, so EA may not be
21457       // quad-word aligned.  Therefore, do 4 individual word-size stores.
21458       assign( hi64, unop( Iop_V128HIto64, mkexpr( vS ) ) );
21459       assign( lo64, unop( Iop_V128to64, mkexpr( vS ) ) );
21460       store( mkexpr( EA ), unop( Iop_64HIto32, mkexpr( hi64 ) ) );
21461       ea_off += 4;
21462       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
21463                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21464       store( irx_addr, unop( Iop_64to32, mkexpr( hi64 ) ) );
21465       ea_off += 4;
21466       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
21467                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21468       store( irx_addr, unop( Iop_64HIto32, mkexpr( lo64 ) ) );
21469       ea_off += 4;
21470       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
21471                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21472       store( irx_addr, unop( Iop_64to32, mkexpr( lo64 ) ) );
21473 
21474       break;
21475    }
21476    case 0x3AC: // stxvh8x Store VSX Vector Halfword*8 Indexed
21477    {
21478       UInt ea_off = 0;
21479       IRExpr* irx_addr;
21480       IRTemp half_word0 = newTemp( Ity_I64 );
21481       IRTemp half_word1 = newTemp( Ity_I64 );
21482       IRTemp half_word2 = newTemp( Ity_I64 );
21483       IRTemp half_word3 = newTemp( Ity_I64 );
21484       IRTemp half_word4 = newTemp( Ity_I64 );
21485       IRTemp half_word5 = newTemp( Ity_I64 );
21486       IRTemp half_word6 = newTemp( Ity_I64 );
21487       IRTemp half_word7 = newTemp( Ity_I64 );
21488 
21489       DIP("stxvb8x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
21490 
21491       assign( half_word0, binop( Iop_Shr64,
21492                                  unop( Iop_V128HIto64, mkexpr( vS ) ),
21493                                  mkU8( 48 ) ) );
21494 
21495       assign( half_word1, binop( Iop_And64,
21496                                  binop( Iop_Shr64,
21497                                         unop( Iop_V128HIto64, mkexpr( vS ) ),
21498                                         mkU8( 32 ) ),
21499                                  mkU64( 0xFFFF ) ) );
21500 
21501       assign( half_word2, binop( Iop_And64,
21502                                  binop( Iop_Shr64,
21503                                         unop( Iop_V128HIto64, mkexpr( vS ) ),
21504                                         mkU8( 16 ) ),
21505                                  mkU64( 0xFFFF ) ) );
21506 
21507       assign( half_word3, binop( Iop_And64,
21508                                  unop( Iop_V128HIto64, mkexpr( vS ) ),
21509                                  mkU64( 0xFFFF ) ) );
21510 
21511       assign( half_word4, binop( Iop_Shr64,
21512                                  unop( Iop_V128to64, mkexpr( vS ) ),
21513                                  mkU8( 48 ) ) );
21514 
21515       assign( half_word5, binop( Iop_And64,
21516                                  binop( Iop_Shr64,
21517                                         unop( Iop_V128to64, mkexpr( vS ) ),
21518                                         mkU8( 32 ) ),
21519                                  mkU64( 0xFFFF ) ) );
21520 
21521       assign( half_word6, binop( Iop_And64,
21522                                  binop( Iop_Shr64,
21523                                         unop( Iop_V128to64, mkexpr( vS ) ),
21524                                         mkU8( 16 ) ),
21525                                  mkU64( 0xFFFF ) ) );
21526 
21527       assign( half_word7, binop( Iop_And64,
21528                                  unop( Iop_V128to64, mkexpr( vS ) ),
21529                                  mkU64( 0xFFFF ) ) );
21530 
21531       /* Do the 32-bit stores.  The store() does an Endian aware store. */
21532       if ( host_endness == VexEndnessBE ) {
21533          store( mkexpr( EA ), unop( Iop_64to32,
21534                                     binop( Iop_Or64,
21535                                            mkexpr( half_word1 ),
21536                                            binop( Iop_Shl64,
21537                                                   mkexpr( half_word0 ),
21538                                                   mkU8( 16 ) ) ) ) );
21539 
21540          ea_off += 4;
21541          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
21542                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21543 
21544 
21545          store( irx_addr, unop( Iop_64to32,
21546                                 binop( Iop_Or64,
21547                                        mkexpr( half_word3 ),
21548                                        binop( Iop_Shl64,
21549                                               mkexpr( half_word2 ),
21550                                               mkU8( 16 ) ) ) ) );
21551 
21552          ea_off += 4;
21553          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
21554                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21555 
21556          store( irx_addr, unop( Iop_64to32,
21557                                 binop( Iop_Or64,
21558                                        mkexpr( half_word5 ),
21559                                        binop( Iop_Shl64,
21560                                               mkexpr( half_word4 ),
21561                                               mkU8( 16 ) ) ) ) );
21562          ea_off += 4;
21563          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
21564                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21565 
21566          store( irx_addr, unop( Iop_64to32,
21567                                 binop( Iop_Or64,
21568                                        mkexpr( half_word7 ),
21569                                        binop( Iop_Shl64,
21570                                               mkexpr( half_word6 ),
21571                                               mkU8( 16 ) ) ) ) );
21572 
21573       } else {
21574          store( mkexpr( EA ), unop( Iop_64to32,
21575                                     binop( Iop_Or64,
21576                                            mkexpr( half_word0 ),
21577                                            binop( Iop_Shl64,
21578                                                   mkexpr( half_word1 ),
21579                                                   mkU8( 16 ) ) ) ) );
21580 
21581          ea_off += 4;
21582          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
21583                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21584 
21585          store( irx_addr, unop( Iop_64to32,
21586                                 binop( Iop_Or64,
21587                                        mkexpr( half_word2 ),
21588                                        binop( Iop_Shl64,
21589                                               mkexpr( half_word3 ),
21590                                               mkU8( 16 ) ) ) ) );
21591          ea_off += 4;
21592          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
21593                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21594 
21595          store( irx_addr, unop( Iop_64to32,
21596                                 binop( Iop_Or64,
21597                                        mkexpr( half_word4 ),
21598                                        binop( Iop_Shl64,
21599                                               mkexpr( half_word5 ),
21600                                               mkU8( 16 ) ) ) ) );
21601          ea_off += 4;
21602          irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
21603                            ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21604 
21605          store( irx_addr, unop( Iop_64to32,
21606                                 binop( Iop_Or64,
21607                                        mkexpr( half_word6 ),
21608                                        binop( Iop_Shl64,
21609                                               mkexpr( half_word7 ),
21610                                               mkU8( 16 ) ) ) ) );
21611       }
21612       break;
21613    }
21614 
21615    case 0x3EC: // stxvb16x Store VSX Vector Byte*16 Indexed
21616    {
21617       UInt ea_off = 0;
21618       int i;
21619       IRExpr* irx_addr;
21620       IRTemp byte[16];
21621 
21622       DIP("stxvb16x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
21623 
21624       for ( i = 0; i < 8; i++ ) {
21625          byte[i] = newTemp( Ity_I64 );
21626          byte[i+8] = newTemp( Ity_I64 );
21627 
21628          assign( byte[i], binop( Iop_And64,
21629                                binop( Iop_Shr64,
21630                                       unop( Iop_V128HIto64, mkexpr( vS ) ),
21631                                       mkU8( 56 - i*8 ) ),
21632                                mkU64( 0xFF ) ) );
21633 
21634          assign( byte[i+8], binop( Iop_And64,
21635                                binop( Iop_Shr64,
21636                                       unop( Iop_V128to64, mkexpr( vS ) ),
21637                                       mkU8( 56 - i*8) ),
21638                                mkU64( 0xFF ) ) );
21639       }
21640 
21641       if ( host_endness == VexEndnessBE ) {
21642          for ( i = 0; i < 16; i = i + 4)  {
21643             irx_addr =
21644                binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
21645                       ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21646 
21647             store( irx_addr,
21648                    unop( Iop_64to32,
21649                          binop( Iop_Or64,
21650                                 binop( Iop_Or64,
21651                                        mkexpr( byte[i+3] ),
21652                                        binop( Iop_Shl64,
21653                                               mkexpr( byte[i+2] ),
21654                                               mkU8( 8 ) ) ),
21655                                 binop( Iop_Or64,
21656                                        binop( Iop_Shl64,
21657                                               mkexpr( byte[i+1] ),
21658                                               mkU8( 16 ) ),
21659                                        binop( Iop_Shl64,
21660                                               mkexpr( byte[i] ),
21661                                               mkU8( 24 ) ) ) ) ) );
21662             ea_off += 4;
21663          }
21664 
21665       } else {
21666          for ( i = 0; i < 16; i = i + 4)  {
21667             irx_addr =
21668                binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
21669                       ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
21670 
21671             store( irx_addr,
21672                    unop( Iop_64to32,
21673                          binop( Iop_Or64,
21674                                 binop( Iop_Or64,
21675                                        mkexpr( byte[i] ),
21676                                        binop( Iop_Shl64,
21677                                               mkexpr( byte[i+1] ),
21678                                               mkU8( 8 ) ) ),
21679                                 binop( Iop_Or64,
21680                                        binop( Iop_Shl64,
21681                                               mkexpr( byte[i+2] ),
21682                                               mkU8( 16 ) ),
21683                                        binop( Iop_Shl64,
21684                                               mkexpr( byte[i+3] ),
21685                                               mkU8( 24 ) ) ) ) ) );
21686 
21687             ea_off += 4;
21688          }
21689       }
21690       break;
21691    }
21692 
21693    default:
21694       vex_printf( "dis_vx_store(ppc)(opc2)\n" );
21695       return False;
21696    }
21697    return True;
21698 }
21699 
21700 static Bool
dis_vx_Scalar_Round_to_quad_integer(UInt theInstr,const VexAbiInfo * vbi)21701 dis_vx_Scalar_Round_to_quad_integer( UInt theInstr, const VexAbiInfo* vbi )
21702 {
21703    /* The ISA 3.0 instructions supported in this function require
21704     * the underlying hardware platform that supports the ISA3.0
21705     * instruction set.
21706     */
21707    /* XX1-Form */
21708    UChar opc1 = ifieldOPC( theInstr );
21709    UInt opc2 = IFIELD( theInstr, 1, 8 );
21710    UChar vT_addr = ifieldRegDS( theInstr );
21711    UChar vB_addr = ifieldRegB( theInstr );
21712    IRTemp vB = newTemp( Ity_F128 );
21713    IRTemp vT = newTemp( Ity_F128 );
21714    UChar EX = IFIELD( theInstr, 0, 1 );
21715 
21716    assign( vB, getF128Reg( vB_addr ) );
21717    if (opc1 != 0x3F) {
21718       vex_printf( "dis_vx_Scalar_Round_to_quad_integer(ppc)(instr)\n" );
21719       return False;
21720    }
21721    switch (opc2) {
21722    case 0x005:     // VSX Scalar Round to Quad-Precision Integer [with Inexact]
21723       {
21724          UChar R   = IFIELD( theInstr, 16, 1 );
21725          UChar RMC = IFIELD( theInstr, 9, 2 );
21726 
21727          /* Store the rm specification bits.  Will extract them later when
21728           * the isntruction is issued.
21729           */
21730          IRExpr* rm = mkU32( R << 3 | RMC << 1 | EX);
21731 
21732          if ( EX == 0 ) {  // xsrqpi
21733             DIP("xsrqpi %d,v%d,v%d,%d\n",  R, vT_addr, vB_addr, RMC);
21734             assign( vT, binop( Iop_F128toI128S, rm, mkexpr( vB ) ) );
21735 
21736          } else {     // xsrqpix
21737             DIP("xsrqpix %d,v%d,v%d,%d\n", R, vT_addr, vB_addr, RMC);
21738             assign( vT, binop( Iop_F128toI128S, rm, mkexpr( vB ) ) );
21739          }
21740          generate_store_FPRF( Ity_F128, vT, vbi );
21741       }   /* case 0x005 */
21742       break;
21743    case 0x025:     // xsrqpxp  VSX Scalar Round Quad-Precision to
21744                    // Double-Extended Precision
21745       {
21746          UChar R   = IFIELD( theInstr, 16, 1 );
21747          UChar RMC = IFIELD( theInstr, 9, 2 );
21748 
21749          /* Store the rm specification bits.  Will extract them later when
21750           * the isntruction is issued.
21751           */
21752          IRExpr* rm = mkU32( R << 3 | RMC << 1 );
21753 
21754         DIP("xsrqpxp %d,v%d,v%d,%d\n",  R, vT_addr, vB_addr, RMC);
21755          assign( vT, binop( Iop_RndF128, rm, mkexpr( vB ) ) );
21756          generate_store_FPRF( Ity_F128, vT, vbi );
21757       }   /* case 0x025 */
21758      break;
21759    default:
21760       vex_printf( "dis_vx_Scalar_Round_to_quad_integer(ppc)(opc2)\n" );
21761       return False;
21762    }     /* switch opc2 */
21763    putF128Reg( vT_addr, mkexpr( vT ) );
21764    return True;
21765 }
21766 
21767 static Bool
dis_vx_Floating_Point_Arithmetic_quad_precision(UInt theInstr,const VexAbiInfo * vbi)21768 dis_vx_Floating_Point_Arithmetic_quad_precision( UInt theInstr,
21769                                                  const VexAbiInfo* vbi )
21770 {
21771    /* The ISA 3.0 instructions supported in this function require
21772     * the underlying hardware platform that supports the ISA 3.0
21773     * instruction set.
21774     */
21775    /* XX1-Form */
21776    UChar opc1 = ifieldOPC( theInstr );
21777    UInt opc2 = ifieldOPClo10( theInstr );
21778    UChar vT_addr = ifieldRegDS( theInstr );
21779    UChar vA_addr = ifieldRegA( theInstr );
21780    UChar vB_addr = ifieldRegB( theInstr );
21781    IRTemp vA = newTemp( Ity_F128 );
21782    IRTemp vB = newTemp( Ity_F128 );
21783    IRTemp vT = newTemp( Ity_F128 );
21784    IRExpr* rm = get_IR_roundingmode();
21785    UChar R0 = IFIELD( theInstr, 0, 1 );
21786 
21787    assign( vB, getF128Reg( vB_addr ) );
21788 
21789    if ( opc1 != 0x3F ) {
21790       vex_printf( "Erorr, dis_vx_Floating_Point_Arithmetic_quad_precision(ppc)(instr)\n" );
21791       return False;
21792    }
21793    switch ( opc2 ) {
21794    case 0x004:     // xsaddqp (VSX Scalar Add Quad-Precision[using round to Odd])
21795       {
21796          assign( vA, getF128Reg( vA_addr ) );
21797 
21798          if ( R0 == 0 ) {
21799             /* rounding mode specified by RN. Issue inst with R0 = 0 */
21800             DIP("xsaddqp v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21801             assign( vT, triop( Iop_AddF128, rm, mkexpr( vA ), mkexpr( vB ) ) );
21802 
21803          } else {
21804            /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
21805             DIP("xsaddqpo v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21806             assign( vT, triop( Iop_AddF128, set_round_to_Oddmode(),
21807                                mkexpr( vA ), mkexpr( vB ) ) );
21808          }
21809          generate_store_FPRF( Ity_F128, vT, vbi );
21810          break;
21811       }
21812    case 0x024:     // xsmulqp (VSX Scalar Multiply Quad-Precision[using round to Odd])
21813       {
21814          assign( vA, getF128Reg( vA_addr ) );
21815 
21816          if ( R0 == 0 ) {
21817             /* rounding mode specified by RN. Issue inst with R0 = 0 */
21818             DIP("xsmulqp v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21819             assign( vT, triop( Iop_MulF128, rm, mkexpr( vA ), mkexpr( vB ) ) );
21820 
21821          } else {
21822             /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
21823             DIP("xsmulqpo v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21824             assign( vT, triop( Iop_MulF128, set_round_to_Oddmode(), mkexpr( vA ),
21825                                mkexpr( vB ) ) );
21826          }
21827          generate_store_FPRF( Ity_F128, vT, vbi );
21828          break;
21829       }
21830    case 0x184:   // xsmaddqp (VSX Scalar Multiply add Quad-Precision[using round to Odd])
21831       {
21832          /* instruction computes (vA * vB) + vC */
21833          IRTemp vC = newTemp( Ity_F128 );
21834 
21835          assign( vA, getF128Reg( vA_addr ) );
21836          assign( vC, getF128Reg( vT_addr ) );
21837 
21838          if ( R0 == 0 ) {
21839             /* rounding mode specified by RN. Issue inst with R0 = 0 */
21840             DIP("xsmaddqp v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21841             assign( vT,
21842                qop( Iop_MAddF128, rm, mkexpr( vA ),
21843                     mkexpr( vC ), mkexpr( vB ) ) );
21844 
21845          } else {
21846             /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
21847             DIP("xsmaddqpo v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21848             assign( vT,
21849                qop( Iop_MAddF128, set_round_to_Oddmode(), mkexpr( vA ),
21850                     mkexpr( vC ), mkexpr( vB ) ) );
21851          }
21852          generate_store_FPRF( Ity_F128, vT, vbi );
21853          break;
21854       }
21855    case 0x1A4:   // xsmsubqp (VSX Scalar Multiply Subtract Quad-Precision[using round to Odd])
21856       {
21857          IRTemp vC = newTemp( Ity_F128 );
21858 
21859          assign( vA, getF128Reg( vA_addr ) );
21860          assign( vC, getF128Reg( vT_addr ) );
21861 
21862          if ( R0 == 0 ) {
21863             /* rounding mode specified by RN. Issue inst with R0 = 0 */
21864             DIP("xsmsubqp v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21865             assign( vT,
21866                qop( Iop_MSubF128, rm, mkexpr( vA ),
21867                     mkexpr( vC ), mkexpr( vB ) ) );
21868 
21869          } else {
21870             /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
21871             DIP("xsmsubqpo v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21872             assign( vT,
21873                     qop( Iop_MSubF128, set_round_to_Oddmode(),
21874                          mkexpr( vA ), mkexpr( vC ), mkexpr( vB ) ) );
21875          }
21876          generate_store_FPRF( Ity_F128, vT, vbi );
21877          break;
21878       }
21879    case 0x1C4:   // xsnmaddqp (VSX Scalar Negative Multiply Add Quad-Precision[using round to Odd])
21880       {
21881          IRTemp vC = newTemp( Ity_F128 );
21882 
21883          assign( vA, getF128Reg( vA_addr ) );
21884          assign( vC, getF128Reg( vT_addr ) );
21885 
21886          if ( R0 == 0 ) {
21887             /* rounding mode specified by RN. Issue inst with R0 = 0 */
21888             DIP("xsnmaddqp v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21889             assign( vT,
21890                qop( Iop_NegMAddF128, rm, mkexpr( vA ),
21891                     mkexpr( vC ), mkexpr( vB ) ) );
21892 
21893          } else {
21894             /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
21895             DIP("xsnmaddqpo v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21896             assign( vT,
21897                     qop( Iop_NegMAddF128, set_round_to_Oddmode(),
21898                          mkexpr( vA ), mkexpr( vC ), mkexpr( vB ) ) );
21899          }
21900          generate_store_FPRF( Ity_F128, vT, vbi );
21901         break;
21902       }
21903    case 0x1E4:   // xsmsubqp (VSX Scalar Negatve Multiply Subtract Quad-Precision[using round to Odd])
21904       {
21905          IRTemp vC = newTemp( Ity_F128 );
21906 
21907          assign( vA, getF128Reg( vA_addr ) );
21908          assign( vC, getF128Reg( vT_addr ) );
21909 
21910          if ( R0 == 0 ) {
21911             /* rounding mode specified by RN. Issue inst with R0 = 0 */
21912             DIP("xsnmsubqp v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21913             assign( vT,
21914                qop( Iop_NegMSubF128, rm, mkexpr( vA ),
21915                     mkexpr( vC ), mkexpr( vB ) ) );
21916 
21917          } else {
21918             /* rounding mode specified by Round to odd. Issue inst with R0 = 1 */
21919             DIP("xsnmsubqpo v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21920             assign( vT,
21921                     qop( Iop_NegMSubF128, set_round_to_Oddmode(),
21922                          mkexpr( vA ), mkexpr( vC ), mkexpr( vB ) ) );
21923          }
21924          generate_store_FPRF( Ity_F128, vT, vbi );
21925          break;
21926       }
21927    case 0x204:     // xssubqp (VSX Scalar Subtract Quad-Precision[using round to Odd])
21928       {
21929          assign( vA, getF128Reg( vA_addr ) );
21930          if ( R0 == 0 ) {
21931             /* use rounding mode specified by RN. Issue inst with R0 = 0 */
21932             DIP("xssubqp v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21933             assign( vT, triop( Iop_SubF128, rm, mkexpr( vA ), mkexpr( vB ) ) );
21934 
21935          } else {
21936             /* use rounding mode specified by Round to odd. Issue inst with R0 = 1 */
21937             DIP("xssubqpo v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21938             assign( vT, triop( Iop_SubF128, set_round_to_Oddmode(), mkexpr( vA ),
21939                                mkexpr( vB ) ) );
21940          }
21941          generate_store_FPRF( Ity_F128, vT, vbi );
21942         break;
21943       }
21944    case 0x224:     // xsdivqp (VSX Scalar Divide Quad-Precision[using round to Odd])
21945       {
21946          assign( vA, getF128Reg( vA_addr ) );
21947          if ( R0 == 0 ) {
21948             /* use rounding mode specified by RN. Issue inst with R0 = 0 */
21949             DIP("xsdivqp v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21950             assign( vT, triop( Iop_DivF128, rm, mkexpr( vA ), mkexpr( vB ) ) );
21951 
21952          } else {
21953             /* use rounding mode specified by Round to odd. Issue inst with R0 = 1 */
21954             DIP("xsdivqpo v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
21955             assign( vT, triop( Iop_DivF128, set_round_to_Oddmode(), mkexpr( vA ),
21956                                mkexpr( vB ) ) );
21957          }
21958          generate_store_FPRF( Ity_F128, vT, vbi );
21959          break;
21960       }
21961    case 0x324:  // xssqrtqp (VSX Scalar Square root Quad-Precision[using round to Odd])
21962       {
21963          UInt inst_select = IFIELD( theInstr, 16, 5 );
21964 
21965          switch (inst_select) {
21966          case 27:
21967             {
21968                if ( R0 == 0 ) { // xssqrtqp
21969                   /* rounding mode specified by RN. Issue inst with R0 = 0 */
21970                   DIP("xssqrtqp v%d,v%d\n",  vT_addr, vB_addr);
21971                   assign( vT, binop( Iop_SqrtF128, rm, mkexpr( vB ) ) );
21972 
21973                } else {      // xssqrtqpo
21974                   /* rounding mode is Round to odd. Issue inst with R0 = 1 */
21975                   DIP("xssqrtqpo v%d,v%d\n",  vT_addr, vB_addr);
21976                   assign( vT, binop( Iop_SqrtF128, set_round_to_Oddmode(),
21977                                      mkexpr( vB ) ) );
21978                }
21979                generate_store_FPRF( Ity_F128, vT, vbi );
21980                break;
21981             }   /* end case 27 */
21982          default:
21983             vex_printf("dis_vx_Floating_Point_Arithmetic_quad_precision(0x324 unknown inst_select)\n");
21984             return False;
21985          }  /* end switch inst_select */
21986          break;
21987       }   /* end case 0x324 */
21988 
21989    case 0x344:
21990       {
21991          UInt inst_select = IFIELD( theInstr, 16, 5);
21992 
21993          switch (inst_select) {
21994          case 1:    // xscvqpuwz  VSX Scalar Truncate & Convert Quad-Precision
21995                     // format to Unsigned Word format
21996             {
21997                DIP("xscvqpuwz v%d,v%d\n",  vT_addr, vB_addr);
21998                assign( vT, unop( Iop_TruncF128toI32U, mkexpr( vB ) ) );
21999                break;
22000             }
22001          case 2:    // xscvudqp  VSX Scalar Convert from Unsigned Doubleword
22002                     // format to Quad-Precision format
22003             {
22004                IRTemp tmp = newTemp( Ity_I64 );
22005 
22006                DIP("xscvudqp v%d,v%d\n",  vT_addr, vB_addr);
22007                assign( tmp, unop( Iop_ReinterpF64asI64,
22008                                   unop( Iop_F128HItoF64, mkexpr( vB ) ) ) );
22009                assign( vT, unop( Iop_I64UtoF128, mkexpr( tmp ) ) );
22010                generate_store_FPRF( Ity_F128, vT, vbi );
22011                break;
22012             }
22013          case 9:    // xsvqpswz  VSX Scalar Truncate & Convert Quad-Precision
22014                     // format to Signed Word format
22015             {
22016                DIP("xscvqpswz v%d,v%d\n",  vT_addr, vB_addr);
22017                assign( vT, unop( Iop_TruncF128toI32S, mkexpr( vB ) ) );
22018                break;
22019             }
22020          case 10:   // xscvsdqp  VSX Scalar from Signed Doubleword format
22021                     // Quad-Precision format
22022             {
22023                IRTemp tmp = newTemp( Ity_I64 );
22024 
22025                DIP("xscvsdqp v%d,v%d\n",  vT_addr, vB_addr);
22026 
22027                assign( tmp, unop( Iop_ReinterpF64asI64,
22028                                   unop( Iop_F128HItoF64, mkexpr( vB ) ) ) );
22029                assign( vT, unop( Iop_I64StoF128, mkexpr( tmp ) ) );
22030                generate_store_FPRF( Ity_F128, vT, vbi );
22031                break;
22032             }
22033         case 17:    // xsvqpudz  VSX Scalar Truncate & Convert Quad-Precision
22034                     // format to Unigned Doubleword format
22035             {
22036               DIP("xscvqpudz v%d,v%d\n",  vT_addr, vB_addr);
22037                assign( vT, unop( Iop_TruncF128toI64U, mkexpr( vB ) ) );
22038                break;
22039             }
22040          case 20: //  xscvqpdp  Scalar round & Conver Quad-Precision
22041                   //  format to Double-Precision format [using round to Odd]
22042             {
22043                IRTemp ftmp = newTemp( Ity_F64 );
22044                IRTemp tmp = newTemp( Ity_I64 );
22045 
22046                /* This instruction takes a 128-bit floating point value and
22047                 * converts it to a 64-bit floating point value.  The 64-bit
22048                 * result is stored in the upper 64-bit of the 128-bit result
22049                 * register.  The lower 64-bit are undefined.
22050                 */
22051                if (R0 == 0) { //  xscvqpdp
22052                   /* rounding mode specified by RN. Issue inst with R0 = 0 */
22053                   DIP("xscvqpdp v%d,v%d\n",  vT_addr, vB_addr);
22054 
22055                   assign( ftmp, binop( Iop_F128toF64, rm, mkexpr( vB ) ) );
22056 
22057                } else {       //  xscvqpdpo
22058                   /* rounding mode is Round to odd. Issue inst with R0 = 1 */
22059                   DIP("xscvqpdpo v%d,v%d\n",  vT_addr, vB_addr);
22060                   assign( ftmp,
22061                           binop( Iop_F128toF64,
22062                                  set_round_to_Oddmode(), mkexpr( vB ) ) );
22063                }
22064 
22065                /* store 64-bit float in upper 64-bits of 128-bit register,
22066                 * lower 64-bits are zero.
22067                 */
22068                if (host_endness == VexEndnessLE)
22069                   assign( vT,
22070                           binop( Iop_F64HLtoF128,
22071                                  mkexpr( ftmp ),
22072                                  unop( Iop_ReinterpI64asF64, mkU64( 0 ) ) ) );
22073                else
22074                   assign( vT,
22075                           binop( Iop_F64HLtoF128,
22076                                  unop( Iop_ReinterpI64asF64, mkU64( 0 ) ),
22077                                  mkexpr( ftmp ) ) );
22078 
22079                assign( tmp, unop( Iop_ReinterpF64asI64,
22080                                   unop( Iop_F128HItoF64, mkexpr( vT ) ) ) );
22081 
22082                generate_store_FPRF( Ity_I64, tmp, vbi );
22083                break;
22084             }
22085          case 22:    // xscvdpqp VSX Scalar Convert from Double-Precision
22086                      // format to Quad-Precision format
22087             {
22088                DIP("xscvdpqp v%d,v%d\n",  vT_addr, vB_addr);
22089                /* The 64-bit value is in the upper 64 bit of the src */
22090                assign( vT, unop( Iop_F64toF128,
22091                                  unop( Iop_F128HItoF64, mkexpr( vB ) ) ) );
22092 
22093                generate_store_FPRF( Ity_F128, vT, vbi );
22094                break;
22095             }
22096          case 25:    // xsvqpsdz  VSX Scalar Truncate & Convert Quad-Precision
22097                      // format to Signed Doubleword format
22098             {
22099                DIP("xscvqpsdz v%d,v%d\n",  vT_addr, vB_addr);
22100                assign( vT, unop( Iop_TruncF128toI64S, mkexpr( vB ) ) );
22101                break;
22102             }
22103          default:
22104            vex_printf( "dis_vx_Floating_Point_Arithmetic_quad_precision invalid inst_select (ppc)(opc2)\n" );
22105            return False;
22106          }  /* switch inst_select */
22107       }   /* end case 0x344 */
22108       break;
22109    default:    /* switch opc2 */
22110       vex_printf( "dis_vx_Floating_Point_Arithmetic_quad_precision(ppc)(opc2)\n" );
22111       return False;
22112    }
22113    putF128Reg( vT_addr, mkexpr( vT ) );
22114    return True;
22115 }
22116 
22117 
22118 /* VSX Scalar Quad-Precision instructions */
22119 static Bool
dis_vx_scalar_quad_precision(UInt theInstr)22120 dis_vx_scalar_quad_precision ( UInt theInstr )
22121 {
22122    /* This function emulates the 128-bit floating point instructions
22123     * using existing 128-bit vector instructions (Iops).  The 128-bit
22124     * floating point instructions use the same 128-bit vector register
22125     * set.
22126     */
22127    /* XX1-Form */
22128    UChar opc1 = ifieldOPC( theInstr );
22129    UInt opc2 = ifieldOPClo10( theInstr );
22130    UChar vT_addr = ifieldRegDS( theInstr ) + 32;
22131    UChar vA_addr = ifieldRegA( theInstr ) + 32;
22132    UChar vB_addr = ifieldRegB( theInstr ) + 32;
22133    IRTemp vA = newTemp( Ity_V128 );
22134    IRTemp vB = newTemp( Ity_V128 );
22135    IRTemp vT = newTemp( Ity_V128 );
22136 
22137    assign( vB, getVSReg( vB_addr ) );
22138 
22139    if (opc1 != 0x3F) {
22140       vex_printf( "dis_vx_scalar_quad_precision(ppc)(instr)\n" );
22141       return False;
22142    }
22143 
22144    switch (opc2) {
22145 
22146    case 0x064:     // xscpsgnqp (VSX Scalar Copy Sign Quad-Precision)
22147       {
22148          IRTemp sign_vA = newTemp( Ity_I64 );
22149          IRTemp vB_hi = newTemp( Ity_I64 );
22150 
22151          DIP("xscpsgnqp v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
22152 
22153          assign( vA, getVSReg(vA_addr) );
22154 
22155          assign( sign_vA, binop( Iop_And64,
22156                                  unop( Iop_V128HIto64,
22157                                        mkexpr( vA ) ),
22158                                  mkU64( 0x8000000000000000ULL ) ) );
22159          assign( vB_hi, binop( Iop_Or64,
22160                                binop( Iop_And64,
22161                                       unop( Iop_V128HIto64,
22162                                             mkexpr( vB ) ),
22163                                       mkU64( 0x7FFFFFFFFFFFFFFFULL ) ),
22164                                mkexpr( sign_vA ) ) );
22165          assign( vT, binop( Iop_64HLtoV128,
22166                             mkexpr( vB_hi ),
22167                             unop( Iop_V128to64, mkexpr( vB ) ) ) );
22168          break;
22169       }
22170 
22171    case 0x084:     // xscmpoqp (VSX Scalar Compare Ordered Quad-Precision)
22172    case 0x284:     // xscmpuqp (VSX Scalar Compare Unrdered Quad-Precision)
22173       {
22174          /* Note, only differece between xscmoqp and xscmpuqp is the
22175             exception flag settings which are not supported anyway. */
22176          IRExpr *bit4, *bit5, *bit6, *bit7;
22177          IRExpr *bit_zero, *bit_inf, *same_sign;
22178          UInt BF = IFIELD( theInstr, 23, 3 );
22179          IRTemp eq_lt_gt = newTemp( Ity_I32 );
22180          IRTemp CC = newTemp( Ity_I32 );
22181 
22182          if (opc2 == 0x084) {
22183             DIP("xscmpoqp %d,v%d,v%d\n",  BF, vA_addr, vB_addr);
22184          } else {
22185             DIP("xscmpuqp %d,v%d,v%d\n",  BF, vA_addr, vB_addr);
22186          }
22187 
22188          assign( vA, getVSReg(vA_addr));
22189 
22190          /* A and B have the same sign */
22191          same_sign =  binop( Iop_CmpEQ64,
22192                              binop( Iop_Shr64,
22193                                     unop( Iop_V128HIto64,
22194                                           mkexpr( vA ) ),
22195                                     mkU8( 63 ) ),
22196                              binop( Iop_Shr64,
22197                                     unop( Iop_V128HIto64,
22198                                           mkexpr( vB ) ),
22199                                     mkU8( 63 ) ) );
22200 
22201          /* A < B */
22202          bit4 = Quad_precision_gt( vB, vA );
22203 
22204          /*  A > B  */
22205          bit5 = Quad_precision_gt( vA, vB );
22206 
22207          /* A equal B */
22208          bit6 = mkAND1( binop( Iop_CmpEQ64,
22209                                unop( Iop_V128HIto64,
22210                                      mkexpr( vA ) ),
22211                                unop( Iop_V128HIto64,
22212                                      mkexpr( vB ) ) ),
22213                         binop( Iop_CmpEQ64,
22214                                unop( Iop_V128to64,
22215                                      mkexpr( vA ) ),
22216                                unop( Iop_V128to64,
22217                                      mkexpr( vB ) ) ) );
22218 
22219          /* test both zero don't care about sign */
22220          bit_zero = mkAND1( is_Zero( Ity_V128, vA ), is_Zero( Ity_V128, vB ) );
22221 
22222          /* test both for infinity, don't care about sign */
22223          bit_inf = mkAND1(
22224                           mkAND1( is_Inf( Ity_V128, vA ), is_Inf( Ity_V128, vB ) ),
22225                           binop( Iop_CmpEQ64,
22226                                  binop( Iop_And64,
22227                                         unop( Iop_V128to64,
22228                                               mkexpr( vA ) ),
22229                                         mkU64( 0x80000000) ),
22230                                  binop( Iop_And64,
22231                                         unop( Iop_V128to64,
22232                                               mkexpr( vB ) ),
22233                                         mkU64( 0x80000000) ) ) );
22234 
22235          /* exp A or exp B is NaN */
22236          bit7 = mkOR1( is_NaN( Ity_V128, vA ),
22237                        is_NaN( Ity_V128, vB ) );
22238 
22239          assign( eq_lt_gt,
22240                  binop( Iop_Or32,
22241                         binop( Iop_Or32,
22242                                binop( Iop_Shl32,
22243                                       unop( Iop_1Uto32, bit4 ),
22244                                       mkU8( 3 ) ),
22245                                binop( Iop_Shl32,
22246                                       unop( Iop_1Uto32, bit5 ),
22247                                       mkU8( 2 ) ) ),
22248                         binop( Iop_Or32,
22249                                binop( Iop_Shl32,
22250                                       unop( Iop_1Uto32, bit6 ),
22251                                       mkU8( 1 ) ),
22252                                binop( Iop_Or32,
22253                                       binop( Iop_Shl32,
22254                                              unop( Iop_1Uto32,
22255                                                    bit_zero ),
22256                                              mkU8( 1 ) ),
22257                                       binop( Iop_Shl32,
22258                                              unop( Iop_1Uto32,
22259                                                    mkAND1( bit_inf, same_sign ) ),
22260                                              mkU8( 1 ) ) ) ) ) );
22261 
22262          assign(CC, binop( Iop_Or32,
22263                            binop( Iop_And32,
22264                                   unop( Iop_Not32,
22265                                         unop( Iop_1Sto32, bit7 ) ),
22266                                   mkexpr( eq_lt_gt ) ),
22267                            unop( Iop_1Uto32, bit7 ) ) );
22268 
22269          /* put result of the comparison into CC and FPCC */
22270          putGST_field( PPC_GST_CR, mkexpr( CC ), BF );
22271          putFPCC( mkexpr( CC ) );
22272          return True;
22273       }
22274       break;
22275 
22276    case 0xA4:     // xscmpexpqp (VSX Scalar Compare Exponents Double-Precision)
22277       {
22278          IRExpr *bit4, *bit5, *bit6, *bit7;
22279          UInt BF = IFIELD( theInstr, 23, 3 );
22280 
22281          IRTemp eq_lt_gt = newTemp( Ity_I32 );
22282          IRTemp CC = newTemp( Ity_I32 );
22283 
22284          DIP("xscmpexpqp %d,v%d,v%d\n",  BF, vA_addr, vB_addr);
22285 
22286          assign( vA, getVSReg(vA_addr));
22287 
22288          /* A exp < B exp */
22289          bit4 = binop( Iop_CmpLT64U,
22290                       binop( Iop_And64,
22291                              unop( Iop_V128HIto64,
22292                                    mkexpr( vA ) ),
22293                              mkU64( 0x7FFF000000000000 ) ),
22294                       binop( Iop_And64,
22295                              unop( Iop_V128HIto64,
22296                                    mkexpr( vB ) ),
22297                              mkU64( 0x7FFF000000000000 ) ) );
22298          /*  exp > B exp */
22299          bit5 = binop( Iop_CmpLT64U,
22300                       binop( Iop_And64,
22301                              unop( Iop_V128HIto64,
22302                                    mkexpr( vB ) ),
22303                              mkU64( 0x7FFF000000000000 ) ),
22304                       binop( Iop_And64,
22305                              unop( Iop_V128HIto64,
22306                                    mkexpr( vA ) ),
22307                              mkU64( 0x7FFF000000000000 ) ) );
22308          /* test equal */
22309          bit6 = binop( Iop_CmpEQ64,
22310                       binop( Iop_And64,
22311                              unop( Iop_V128HIto64,
22312                                    mkexpr( vA ) ),
22313                              mkU64( 0x7FFF000000000000 ) ),
22314                       binop( Iop_And64,
22315                              unop( Iop_V128HIto64,
22316                                    mkexpr( vB ) ),
22317                              mkU64( 0x7FFF000000000000 ) ) );
22318 
22319          /* exp A or exp B is NaN */
22320          bit7 = mkOR1( is_NaN( Ity_V128, vA ),
22321                        is_NaN( Ity_V128, vB ) );
22322 
22323          /* NaN over rules the other comparisons */
22324          assign( eq_lt_gt, binop( Iop_Or32,
22325                                   binop( Iop_Shl32,
22326                                          unop( Iop_1Uto32, bit4 ),
22327                                          mkU8( 3) ),
22328                                   binop( Iop_Or32,
22329                                          binop( Iop_Shl32,
22330                                                 unop( Iop_1Uto32, bit5 ),
22331                                                 mkU8( 2) ),
22332                                          binop( Iop_Shl32,
22333                                                 unop( Iop_1Uto32, bit6 ),
22334                                                 mkU8( 1 ) ) ) ) );
22335          assign(CC, binop( Iop_Or32,
22336                            binop( Iop_And32,
22337                                   unop( Iop_Not32,
22338                                         unop( Iop_1Sto32, bit7 ) ),
22339                                   mkexpr( eq_lt_gt ) ),
22340                            unop( Iop_1Uto32, bit7 ) ) );
22341 
22342          /* put result of the comparison into CC and FPCC */
22343          putGST_field( PPC_GST_CR, mkexpr( CC ), BF );
22344          putFPCC( mkexpr( CC ) );
22345          return True;
22346       }
22347       break;
22348 
22349    case 0x2C4:    // xststdcqp (VSX Scalar Quad-Precision Test Data Class)
22350       {
22351          UInt BF = IFIELD( theInstr, 23, 3 );
22352          UInt DCMX_mask = IFIELD( theInstr, 16, 7 );
22353          IRTemp CC = newTemp( Ity_I64 );
22354          IRTemp NaN = newTemp( Ity_I64 );
22355          IRTemp inf = newTemp( Ity_I64 );
22356          IRTemp pos = newTemp( Ity_I64 );
22357          IRTemp DCM = newTemp( Ity_I64 );
22358          IRTemp zero = newTemp( Ity_I64 );
22359          IRTemp dnorm = newTemp( Ity_I64 );
22360 
22361          DIP("xststdcqp  %d,v%d,%d\n",  BF, vB_addr, DCMX_mask);
22362 
22363          assign( zero, unop( Iop_1Uto64, is_Zero( Ity_V128, vB ) ) );
22364          assign( pos, unop( Iop_1Uto64,
22365                             binop( Iop_CmpEQ64,
22366                                    binop( Iop_Shr64,
22367                                           unop( Iop_V128HIto64,
22368                                                 mkexpr( vB ) ),
22369                                           mkU8( 63 ) ),
22370                                    mkU64( 0 ) ) ) );
22371 
22372          assign( NaN, unop( Iop_1Uto64, is_NaN( Ity_V128, vB ) ) );
22373          assign( inf, unop( Iop_1Uto64, is_Inf( Ity_V128, vB ) ) );
22374 
22375          assign( dnorm, unop( Iop_1Uto64, is_Denorm( Ity_V128, vB ) ) );
22376          assign( DCM, create_DCM( Ity_I64, NaN, inf, zero, dnorm, pos ) );
22377          assign( CC, binop( Iop_Or64,
22378                             binop( Iop_And64,    /* vB sign bit */
22379                                   binop( Iop_Shr64,
22380                                          unop( Iop_V128HIto64, mkexpr( vB ) ),
22381                                          mkU8( 60 ) ),
22382                                   mkU64( 0x8 ) ),
22383                            binop( Iop_Shl64,
22384                                   unop( Iop_1Uto64,
22385                                         binop( Iop_CmpNE64,
22386                                                binop( Iop_And64,
22387                                                       mkexpr( DCM ),
22388                                                       mkU64( DCMX_mask ) ),
22389                                                mkU64( 0 ) ) ),
22390                                    mkU8( 1 ) ) ) );
22391 
22392          putGST_field( PPC_GST_CR, unop(Iop_64to32, mkexpr( CC ) ), BF );
22393          putFPCC( unop(Iop_64to32, mkexpr( CC ) ) );
22394          return True;
22395       }
22396       break;
22397 
22398    case 0x324:    // xsabsqp  (VSX Scalar Absolute Quad-Precision)
22399                   // xsxexpqp (VSX Scalaar Extract Exponent Quad-Precision)
22400                   // xsnabsqp (VSX Scalar Negative Absolute Quad-Precision)
22401                   // xsnegqp  (VSX Scalar Negate Quad-Precision)
22402                   // xsxsigqp (VSX Scalar Extract Significand Quad-Precision)
22403       {
22404          UInt inst_select = IFIELD( theInstr, 16, 5);
22405 
22406          switch (inst_select) {
22407          case 0:
22408             DIP("xsabsqp  v%d,v%d\n",  vT_addr, vB_addr);
22409             assign( vT, binop( Iop_AndV128, mkexpr( vB ),
22410                                binop( Iop_64HLtoV128,
22411                                       mkU64( 0x7FFFFFFFFFFFFFFF ),
22412                                       mkU64( 0xFFFFFFFFFFFFFFFF ) ) ) );
22413             break;
22414 
22415          case 2:
22416             DIP("xsxexpqp  v%d,v%d\n",  vT_addr, vB_addr);
22417             assign( vT, binop( Iop_ShrV128,
22418                                binop( Iop_AndV128, mkexpr( vB ),
22419                                       binop( Iop_64HLtoV128,
22420                                              mkU64( 0x7FFF000000000000 ),
22421                                              mkU64( 0x0000000000000000 ) ) ),
22422                                mkU8( 48 ) ) );
22423             break;
22424 
22425          case 8:
22426             DIP("xsnabsqp  v%d,v%d\n",  vT_addr, vB_addr);
22427             assign( vT, binop( Iop_OrV128, mkexpr( vB ),
22428                             binop( Iop_64HLtoV128,
22429                                    mkU64( 0x8000000000000000 ),
22430                                    mkU64( 0x0000000000000000 ) ) ) );
22431             break;
22432 
22433          case 16:
22434             DIP("xsnegqp  v%d,v%d\n",  vT_addr, vB_addr);
22435             assign( vT, binop( Iop_XorV128, mkexpr( vB ),
22436                             binop( Iop_64HLtoV128,
22437                                    mkU64( 0x8000000000000000 ),
22438                                    mkU64( 0x0000000000000000 ) ) ) );
22439             break;
22440 
22441          case 18:
22442          {
22443             IRTemp expZero = newTemp( Ity_I64 );
22444             IRTemp expInfinity = newTemp( Ity_I64 );
22445 
22446             DIP("xsxsigqp  v%d,v%d\n",  vT_addr, vB_addr);
22447 
22448             assign( expZero, unop( Iop_1Uto64,
22449                                    binop( Iop_CmpNE64,
22450                                           binop( Iop_And64,
22451                                                  unop( Iop_V128HIto64,
22452                                                        mkexpr( vB ) ),
22453                                                  mkU64( 0x7FFF000000000000 ) ),
22454                                           mkU64( 0x0 ) ) ) );
22455 
22456             assign( expInfinity,
22457                     unop( Iop_1Uto64,
22458                           binop( Iop_CmpNE64,
22459                                  binop( Iop_And64,
22460                                         unop( Iop_V128HIto64,
22461                                               mkexpr( vB ) ),
22462                                         mkU64( 0x7FFF000000000000 ) ),
22463                                  mkU64( 0x7FFF000000000000 ) ) ) );
22464 
22465             /* Clear upper 16 bits to 0x0000.  If the exp was zero or infinity
22466              * set bit 48 (lsb = 0) to 0, otherwise  set bit 48 to 1.
22467              */
22468             assign( vT,
22469                     binop( Iop_OrV128,
22470                            binop( Iop_ShrV128,
22471                                   binop( Iop_ShlV128,
22472                                          mkexpr( vB ),
22473                                          mkU8( 16 ) ),
22474                                   mkU8( 16 ) ),
22475                            binop( Iop_64HLtoV128,
22476                                   binop( Iop_Shl64,
22477                                          binop( Iop_And64,
22478                                                 mkexpr( expZero ),
22479                                                 mkexpr( expInfinity ) ),
22480                                          mkU8( 48 ) ),
22481                                   mkU64( 0 ) ) ) );
22482          }
22483          break;
22484 
22485          default:
22486             vex_printf( "dis_vx_scalar_quad_precision invalid inst_select (ppc)(opc2)\n" );
22487             return False;
22488          }
22489       }
22490       break;
22491    case 0x364:    // xsiexpqp (VST Scalar Insert Exponent Quad-Precision)
22492       {
22493          IRTemp exp = newTemp( Ity_I64 );
22494 
22495          DIP("xsiexpqp  v%d,v%d,v%d\n",  vT_addr, vA_addr, vB_addr);
22496 
22497          assign( vA, getVSReg( vA_addr ) );
22498          assign( exp, binop( Iop_And64,
22499                                  unop( Iop_V128HIto64,
22500                                        mkexpr( vB ) ),
22501                                  mkU64( 0x7FFFULL ) ) );
22502          assign( vT, binop( Iop_64HLtoV128,
22503                             binop( Iop_Or64,
22504                                    binop( Iop_And64,
22505                                           unop( Iop_V128HIto64,
22506                                                 mkexpr( vA ) ),
22507                                           mkU64( 0x8000FFFFFFFFFFFFULL ) ),
22508                                    binop( Iop_Shl64,
22509                                           mkexpr( exp ),
22510                                           mkU8( 48 ) ) ),
22511                             unop( Iop_V128to64,
22512                                   mkexpr( vA ) ) ) );
22513       }
22514       break;
22515 
22516    default:
22517       vex_printf( "dis_vx_scalar_quad_precision(ppc)(opc2)\n" );
22518 
22519       return False;
22520    }
22521 
22522    putVSReg( vT_addr, mkexpr( vT ) );
22523    return True;
22524 }
22525 
22526 /*
22527  * VSX permute and other miscealleous instructions
22528  */
22529 static Bool
dis_vx_permute_misc(UInt theInstr,UInt opc2)22530 dis_vx_permute_misc( UInt theInstr, UInt opc2 )
22531 {
22532    /* XX3-Form */
22533    UChar opc1 = ifieldOPC( theInstr );
22534    UChar XT = ifieldRegXT ( theInstr );
22535    UChar XA = ifieldRegXA ( theInstr );
22536    UChar XB = ifieldRegXB ( theInstr );
22537    IRTemp vT = newTemp( Ity_V128 );
22538    IRTemp vA = newTemp( Ity_V128 );
22539    IRTemp vB = newTemp( Ity_V128 );
22540 
22541    if (opc1 != 0x3C) {
22542       vex_printf( "dis_vx_permute_misc(ppc)(instr)\n" );
22543       return False;
22544    }
22545 
22546    assign( vA, getVSReg( XA ) );
22547    assign( vB, getVSReg( XB ) );
22548 
22549    switch (opc2) {
22550       case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate)
22551       {
22552          UChar SHW = ifieldSHW ( theInstr );
22553          IRTemp result = newTemp(Ity_V128);
22554          if ( SHW != 0 ) {
22555              IRTemp hi = newTemp(Ity_V128);
22556              IRTemp lo = newTemp(Ity_V128);
22557              assign( hi, binop(Iop_ShlV128, mkexpr(vA), mkU8(SHW*32)) );
22558              assign( lo, binop(Iop_ShrV128, mkexpr(vB), mkU8(128-SHW*32)) );
22559              assign ( result, binop(Iop_OrV128, mkexpr(hi), mkexpr(lo)) );
22560          } else
22561              assign ( result, mkexpr(vA) );
22562          DIP("xxsldwi v%d,v%d,v%d,%d\n", XT, XA, XB, SHW);
22563          putVSReg( XT, mkexpr(result) );
22564          break;
22565       }
22566       case 0x28: // xpermdi (VSX Permute Doubleword Immediate)
22567       {
22568          UChar DM = ifieldDM ( theInstr );
22569          IRTemp hi = newTemp(Ity_I64);
22570          IRTemp lo = newTemp(Ity_I64);
22571 
22572          if (DM & 0x2)
22573            assign( hi, unop(Iop_V128to64, mkexpr(vA)) );
22574          else
22575            assign( hi, unop(Iop_V128HIto64, mkexpr(vA)) );
22576 
22577          if (DM & 0x1)
22578            assign( lo, unop(Iop_V128to64, mkexpr(vB)) );
22579          else
22580            assign( lo, unop(Iop_V128HIto64, mkexpr(vB)) );
22581 
22582          assign( vT, binop(Iop_64HLtoV128, mkexpr(hi), mkexpr(lo)) );
22583 
22584          DIP("xxpermdi v%d,v%d,v%d,0x%x\n", XT, XA, XB, DM);
22585          putVSReg( XT, mkexpr( vT ) );
22586          break;
22587       }
22588       case 0x48: // xxmrghw (VSX Merge High Word)
22589       case 0xc8: // xxmrglw (VSX Merge Low Word)
22590       {
22591          const HChar type = (opc2 == 0x48) ? 'h' : 'l';
22592          IROp word_op = (opc2 == 0x48) ? Iop_V128HIto64 : Iop_V128to64;
22593          IRTemp a64 = newTemp(Ity_I64);
22594          IRTemp ahi32 = newTemp(Ity_I32);
22595          IRTemp alo32 = newTemp(Ity_I32);
22596          IRTemp b64 = newTemp(Ity_I64);
22597          IRTemp bhi32 = newTemp(Ity_I32);
22598          IRTemp blo32 = newTemp(Ity_I32);
22599 
22600          assign( a64, unop(word_op, mkexpr(vA)) );
22601          assign( ahi32, unop(Iop_64HIto32, mkexpr(a64)) );
22602          assign( alo32, unop(Iop_64to32, mkexpr(a64)) );
22603 
22604          assign( b64, unop(word_op, mkexpr(vB)) );
22605          assign( bhi32, unop(Iop_64HIto32, mkexpr(b64)) );
22606          assign( blo32, unop(Iop_64to32, mkexpr(b64)) );
22607 
22608          assign( vT, binop(Iop_64HLtoV128,
22609                            binop(Iop_32HLto64, mkexpr(ahi32), mkexpr(bhi32)),
22610                            binop(Iop_32HLto64, mkexpr(alo32), mkexpr(blo32))) );
22611 
22612          DIP("xxmrg%cw v%d,v%d,v%d\n", type, XT, XA, XB);
22613          putVSReg( XT, mkexpr( vT ) );
22614          break;
22615       }
22616       case 0x018: // xxsel (VSX Select)
22617       {
22618          UChar XC = ifieldRegXC(theInstr);
22619          IRTemp vC = newTemp( Ity_V128 );
22620          assign( vC, getVSReg( XC ) );
22621          DIP("xxsel v%d,v%d,v%d,v%d\n", XT, XA, XB, XC);
22622          /* vD = (vA & ~vC) | (vB & vC) */
22623          putVSReg( XT, binop(Iop_OrV128,
22624             binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
22625             binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
22626          break;
22627       }
22628 
22629       case 0x68: // xxperm  (VSX Permute )
22630       case 0xE8: // xxpermr (VSX Permute right-index )
22631       {
22632 
22633          /* The xxperm  instruction performs the same operation as
22634             the vperm except the xxperm operates on the VSR register
22635             file. while vperm operates on the VR register file.
22636             Lets borrow some code here from vperm. The mapping of
22637             the source registers is also a little different.
22638          */
22639          IRTemp a_perm  = newTemp(Ity_V128);
22640          IRTemp b_perm  = newTemp(Ity_V128);
22641          IRTemp mask    = newTemp(Ity_V128);
22642          IRTemp perm_val = newTemp(Ity_V128);
22643          IRTemp vB_adj = newTemp( Ity_V128 );
22644 
22645          if ( opc2 == 0x68 ) {
22646             DIP("xxperm v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
22647 
22648          } else {
22649             /* Same as xperm just the index is 31 - idx */
22650             DIP("xxpermr v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
22651          }
22652 
22653          assign( vT, getVSReg( XT ) );
22654 
22655          if ( opc2 == 0x68 ) // xxperm
22656             assign( vB_adj, mkexpr( vB ) );
22657 
22658          else                // xxpermr
22659             assign( vB_adj,
22660                     binop( Iop_Sub16x8,
22661                            unop( Iop_Dup8x16, mkU8( 0x1F ) ),
22662                            mkexpr( vB ) ) );
22663 
22664          /* Limit the Perm8x16 steering values to 0 .. 15 as that is what
22665             IR specifies, and also to hide irrelevant bits from
22666             memcheck.
22667          */
22668          assign( perm_val,
22669                  binop( Iop_AndV128, mkexpr( vB_adj ),
22670                         unop( Iop_Dup8x16, mkU8( 0xF ) ) ) );
22671          assign( a_perm,
22672                  binop( Iop_Perm8x16, mkexpr( vA ), mkexpr( perm_val ) ) );
22673          assign( b_perm,
22674                  binop( Iop_Perm8x16, mkexpr( vT ), mkexpr( perm_val ) ) );
22675          assign( mask, binop( Iop_SarN8x16,
22676                               binop( Iop_ShlN8x16, mkexpr( vB_adj ),
22677                                      mkU8( 3 ) ),
22678                               mkU8( 7 ) ) );
22679          // dst = (a & ~mask) | (b & mask)
22680          putVSReg( XT, binop( Iop_OrV128,
22681                               binop( Iop_AndV128, mkexpr( a_perm ),
22682                                      unop( Iop_NotV128, mkexpr( mask ) ) ),
22683                               binop( Iop_AndV128, mkexpr( b_perm ),
22684                                      mkexpr( mask ) ) ) );
22685          break;
22686       }
22687 
22688       case 0x148: // xxspltw (VSX Splat Word)
22689       {
22690          UChar UIM   = ifieldRegA(theInstr) & 3;
22691          UChar sh_uim = (3 - (UIM)) * 32;
22692          DIP("xxspltw v%d,v%d,%d\n", XT, XB, UIM);
22693          putVSReg( XT,
22694                    unop( Iop_Dup32x4,
22695                          unop( Iop_V128to32,
22696                                binop( Iop_ShrV128, mkexpr( vB ), mkU8( sh_uim ) ) ) ) );
22697          break;
22698       }
22699 
22700       default:
22701          vex_printf( "dis_vx_permute_misc(ppc)(opc2)\n" );
22702          return False;
22703    }
22704    return True;
22705 }
22706 
22707 /*
22708   AltiVec Load Instructions
22709 */
dis_av_load(const VexAbiInfo * vbi,UInt theInstr)22710 static Bool dis_av_load ( const VexAbiInfo* vbi, UInt theInstr )
22711 {
22712    /* X-Form */
22713    UChar opc1     = ifieldOPC(theInstr);
22714    UChar vD_addr  = ifieldRegDS(theInstr);
22715    UChar rA_addr  = ifieldRegA(theInstr);
22716    UChar rB_addr  = ifieldRegB(theInstr);
22717    UInt  opc2     = ifieldOPClo10(theInstr);
22718    UChar b0       = ifieldBIT0(theInstr);
22719 
22720    IRType ty         = mode64 ? Ity_I64 : Ity_I32;
22721    IRTemp EA         = newTemp(ty);
22722    IRTemp EA_align16 = newTemp(ty);
22723 
22724    if (opc1 != 0x1F || b0 != 0) {
22725       vex_printf("dis_av_load(ppc)(instr)\n");
22726       return False;
22727    }
22728 
22729    assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
22730    assign( EA_align16, addr_align( mkexpr(EA), 16 ) );
22731 
22732    switch (opc2) {
22733 
22734    case 0x006: { // lvsl (Load Vector for Shift Left, AV p123)
22735       IRDirty* d;
22736       UInt vD_off = vectorGuestRegOffset(vD_addr);
22737       IRExpr** args_be = mkIRExprVec_5(
22738                          IRExpr_GSPTR(),
22739                          mkU32(vD_off),
22740                          binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
22741                                           mkU32(0xF)),
22742                          mkU32(0)/*left*/,
22743                          mkU32(1)/*Big Endian*/);
22744       IRExpr** args_le = mkIRExprVec_5(
22745                          IRExpr_GSPTR(),
22746                          mkU32(vD_off),
22747                          binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
22748                                           mkU32(0xF)),
22749                          mkU32(0)/*left*/,
22750                          mkU32(0)/*Little Endian*/);
22751       if (!mode64) {
22752          d = unsafeIRDirty_0_N (
22753                         0/*regparms*/,
22754                         "ppc32g_dirtyhelper_LVS",
22755                         fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
22756                         args_be );
22757       } else {
22758          if (host_endness == VexEndnessBE)
22759             d = unsafeIRDirty_0_N (
22760                            0/*regparms*/,
22761                            "ppc64g_dirtyhelper_LVS",
22762                            fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
22763                            args_be );
22764          else
22765             d = unsafeIRDirty_0_N (
22766                            0/*regparms*/,
22767                            "ppc64g_dirtyhelper_LVS",
22768                            fnptr_to_fnentry( vbi, &ppc64g_dirtyhelper_LVS ),
22769                            args_le );
22770       }
22771       DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
22772       /* declare guest state effects */
22773       d->nFxState = 1;
22774       vex_bzero(&d->fxState, sizeof(d->fxState));
22775       d->fxState[0].fx     = Ifx_Write;
22776       d->fxState[0].offset = vD_off;
22777       d->fxState[0].size   = sizeof(U128);
22778 
22779       /* execute the dirty call, side-effecting guest state */
22780       stmt( IRStmt_Dirty(d) );
22781       break;
22782    }
22783    case 0x026: { // lvsr (Load Vector for Shift Right, AV p125)
22784       IRDirty* d;
22785       UInt vD_off = vectorGuestRegOffset(vD_addr);
22786       IRExpr** args_be = mkIRExprVec_5(
22787                              IRExpr_GSPTR(),
22788                              mkU32(vD_off),
22789                              binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
22790                                               mkU32(0xF)),
22791                              mkU32(1)/*right*/,
22792                              mkU32(1)/*Big Endian*/);
22793       IRExpr** args_le = mkIRExprVec_5(
22794                              IRExpr_GSPTR(),
22795                              mkU32(vD_off),
22796                              binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
22797                                               mkU32(0xF)),
22798                              mkU32(1)/*right*/,
22799                              mkU32(0)/*Little Endian*/);
22800 
22801       if (!mode64) {
22802          d = unsafeIRDirty_0_N (
22803                         0/*regparms*/,
22804                         "ppc32g_dirtyhelper_LVS",
22805                         fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
22806                         args_be );
22807       } else {
22808          if (host_endness == VexEndnessBE)
22809             d = unsafeIRDirty_0_N (
22810                            0/*regparms*/,
22811                            "ppc64g_dirtyhelper_LVS",
22812                            fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
22813                            args_be );
22814          else
22815             d = unsafeIRDirty_0_N (
22816                            0/*regparms*/,
22817                            "ppc64g_dirtyhelper_LVS",
22818                            fnptr_to_fnentry( vbi, &ppc64g_dirtyhelper_LVS ),
22819                            args_le );
22820       }
22821       DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
22822       /* declare guest state effects */
22823       d->nFxState = 1;
22824       vex_bzero(&d->fxState, sizeof(d->fxState));
22825       d->fxState[0].fx     = Ifx_Write;
22826       d->fxState[0].offset = vD_off;
22827       d->fxState[0].size   = sizeof(U128);
22828 
22829       /* execute the dirty call, side-effecting guest state */
22830       stmt( IRStmt_Dirty(d) );
22831       break;
22832    }
22833    case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119)
22834       DIP("lvebx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
22835       /* loads addressed byte into vector[EA[0:3]
22836          since all other destination bytes are undefined,
22837          can simply load entire vector from 16-aligned EA */
22838       putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
22839       break;
22840 
22841    case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121)
22842       DIP("lvehx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
22843       /* see note for lvebx */
22844       putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
22845       break;
22846 
22847    case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122)
22848       DIP("lvewx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
22849       /* see note for lvebx */
22850       putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
22851       break;
22852 
22853    case 0x067: // lvx (Load Vector Indexed, AV p127)
22854       DIP("lvx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
22855       putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
22856       break;
22857 
22858    case 0x167: // lvxl (Load Vector Indexed LRU, AV p128)
22859       DIP("lvxl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
22860       putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
22861       break;
22862 
22863    default:
22864       vex_printf("dis_av_load(ppc)(opc2)\n");
22865       return False;
22866    }
22867    return True;
22868 }
22869 
22870 /*
22871   AltiVec Store Instructions
22872 */
dis_av_store(UInt theInstr)22873 static Bool dis_av_store ( UInt theInstr )
22874 {
22875    /* X-Form */
22876    UChar opc1     = ifieldOPC(theInstr);
22877    UChar vS_addr  = ifieldRegDS(theInstr);
22878    UChar rA_addr  = ifieldRegA(theInstr);
22879    UChar rB_addr  = ifieldRegB(theInstr);
22880    UInt  opc2     = ifieldOPClo10(theInstr);
22881    UChar b0       = ifieldBIT0(theInstr);
22882 
22883    IRType ty           = mode64 ? Ity_I64 : Ity_I32;
22884    IRTemp EA           = newTemp(ty);
22885    IRTemp addr_aligned = newTemp(ty);
22886    IRTemp vS           = newTemp(Ity_V128);
22887    IRTemp eb           = newTemp(Ity_I8);
22888    IRTemp idx          = newTemp(Ity_I8);
22889 
22890    if (opc1 != 0x1F || b0 != 0) {
22891       vex_printf("dis_av_store(ppc)(instr)\n");
22892       return False;
22893    }
22894 
22895    assign( vS, getVReg(vS_addr));
22896    assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
22897 
22898    switch (opc2) {
22899    case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131)
22900       DIP("stvebx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
22901       assign( eb, binop(Iop_And8, mkU8(0xF),
22902                         unop(Iop_32to8,
22903                              mkNarrowTo32(ty, mkexpr(EA)) )) );
22904      if (host_endness == VexEndnessLE) {
22905          assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
22906       } else {
22907          assign( idx, binop(Iop_Shl8,
22908                             binop(Iop_Sub8, mkU8(15), mkexpr(eb)),
22909                             mkU8(3)) );
22910       }
22911       store( mkexpr(EA),
22912              unop( Iop_32to8, unop(Iop_V128to32,
22913                    binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
22914       break;
22915    }
22916    case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132)
22917       DIP("stvehx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
22918       assign( addr_aligned, addr_align(mkexpr(EA), 2) );
22919       assign( eb, binop(Iop_And8, mkU8(0xF),
22920                         mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
22921       if (host_endness == VexEndnessLE) {
22922           assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
22923       } else {
22924          assign( idx, binop(Iop_Shl8,
22925                             binop(Iop_Sub8, mkU8(14), mkexpr(eb)),
22926                             mkU8(3)) );
22927       }
22928       store( mkexpr(addr_aligned),
22929              unop( Iop_32to16, unop(Iop_V128to32,
22930                    binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
22931       break;
22932    }
22933    case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133)
22934       DIP("stvewx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
22935       assign( addr_aligned, addr_align(mkexpr(EA), 4) );
22936       assign( eb, binop(Iop_And8, mkU8(0xF),
22937                         mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
22938       if (host_endness == VexEndnessLE) {
22939          assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
22940       } else {
22941          assign( idx, binop(Iop_Shl8,
22942                             binop(Iop_Sub8, mkU8(12), mkexpr(eb)),
22943                             mkU8(3)) );
22944       }
22945       store( mkexpr( addr_aligned),
22946              unop( Iop_V128to32,
22947                    binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) );
22948       break;
22949    }
22950 
22951    case 0x0E7: // stvx (Store Vector Indexed, AV p134)
22952       DIP("stvx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
22953       store( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
22954       break;
22955 
22956    case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135)
22957       DIP("stvxl v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
22958       store( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
22959       break;
22960 
22961    default:
22962       vex_printf("dis_av_store(ppc)(opc2)\n");
22963       return False;
22964    }
22965    return True;
22966 }
22967 
22968 /*
22969   AltiVec Arithmetic Instructions
22970 */
dis_av_arith(UInt theInstr)22971 static Bool dis_av_arith ( UInt theInstr )
22972 {
22973    /* VX-Form */
22974    UChar opc1     = ifieldOPC(theInstr);
22975    UChar vD_addr  = ifieldRegDS(theInstr);
22976    UChar vA_addr  = ifieldRegA(theInstr);
22977    UChar vB_addr  = ifieldRegB(theInstr);
22978    UInt  opc2     = IFIELD( theInstr, 0, 11 );
22979 
22980    IRTemp vA = newTemp(Ity_V128);
22981    IRTemp vB = newTemp(Ity_V128);
22982    IRTemp z3 = newTemp(Ity_I64);
22983    IRTemp z2 = newTemp(Ity_I64);
22984    IRTemp z1 = newTemp(Ity_I64);
22985    IRTemp z0 = newTemp(Ity_I64);
22986    IRTemp aEvn, aOdd;
22987    IRTemp a15, a14, a13, a12, a11, a10, a9, a8;
22988    IRTemp a7, a6, a5, a4, a3, a2, a1, a0;
22989    IRTemp b3, b2, b1, b0;
22990 
22991    aEvn = aOdd = IRTemp_INVALID;
22992    a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID;
22993    a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID;
22994    b3 = b2 = b1 = b0 = IRTemp_INVALID;
22995 
22996    assign( vA, getVReg( vA_addr ) );
22997    assign( vB, getVReg( vB_addr ) );
22998 
22999    if (opc1 != 0x4) {
23000       vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n");
23001       return False;
23002    }
23003 
23004    switch (opc2) {
23005    /* Add */
23006    case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136)
23007       DIP("vaddcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23008       /* unsigned_ov(x+y) = (y >u not(x)) */
23009       putVReg( vD_addr, binop( Iop_ShrN32x4,
23010                                binop( Iop_CmpGT32Ux4, mkexpr( vB ),
23011                                     unop( Iop_NotV128, mkexpr( vA ) ) ),
23012                               mkU8( 31 ) ) );
23013       break;
23014    }
23015    case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141)
23016       DIP("vaddubm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23017       putVReg( vD_addr, binop(Iop_Add8x16, mkexpr(vA), mkexpr(vB)) );
23018       break;
23019 
23020    case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143)
23021       DIP("vadduhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23022       putVReg( vD_addr, binop(Iop_Add16x8, mkexpr(vA), mkexpr(vB)) );
23023       break;
23024 
23025    case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145)
23026       DIP("vadduwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23027       putVReg( vD_addr, binop(Iop_Add32x4, mkexpr(vA), mkexpr(vB)) );
23028       break;
23029 
23030    case 0x0C0: // vaddudm (Add Unsigned Double Word Modulo)
23031       DIP("vaddudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23032       putVReg( vD_addr, binop(Iop_Add64x2, mkexpr(vA), mkexpr(vB)) );
23033       break;
23034 
23035    case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142)
23036       DIP("vaddubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23037       putVReg( vD_addr, binop(Iop_QAdd8Ux16, mkexpr(vA), mkexpr(vB)) );
23038       // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16
23039       break;
23040 
23041    case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144)
23042       DIP("vadduhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23043       putVReg( vD_addr, binop(Iop_QAdd16Ux8, mkexpr(vA), mkexpr(vB)) );
23044       // TODO: set VSCR[SAT]
23045       break;
23046 
23047    case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146)
23048       DIP("vadduws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23049       putVReg( vD_addr, binop(Iop_QAdd32Ux4, mkexpr(vA), mkexpr(vB)) );
23050       // TODO: set VSCR[SAT]
23051       break;
23052 
23053    case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138)
23054       DIP("vaddsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23055       putVReg( vD_addr, binop(Iop_QAdd8Sx16, mkexpr(vA), mkexpr(vB)) );
23056       // TODO: set VSCR[SAT]
23057       break;
23058 
23059    case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139)
23060       DIP("vaddshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23061       putVReg( vD_addr, binop(Iop_QAdd16Sx8, mkexpr(vA), mkexpr(vB)) );
23062       // TODO: set VSCR[SAT]
23063       break;
23064 
23065    case 0x380: // vaddsws (Add Signed Word Saturate, AV p140)
23066       DIP("vaddsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23067       putVReg( vD_addr, binop(Iop_QAdd32Sx4, mkexpr(vA), mkexpr(vB)) );
23068       // TODO: set VSCR[SAT]
23069       break;
23070 
23071 
23072    /* Subtract */
23073    case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260)
23074       DIP("vsubcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23075       /* unsigned_ov(x-y) = (y >u x) */
23076       putVReg( vD_addr, binop(Iop_ShrN32x4,
23077                               unop(Iop_NotV128,
23078                                    binop(Iop_CmpGT32Ux4, mkexpr(vB),
23079                                          mkexpr(vA))),
23080                               mkU8(31)) );
23081       break;
23082    }
23083    case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265)
23084       DIP("vsububm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23085       putVReg( vD_addr, binop(Iop_Sub8x16, mkexpr(vA), mkexpr(vB)) );
23086       break;
23087 
23088    case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267)
23089       DIP("vsubuhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23090       putVReg( vD_addr, binop(Iop_Sub16x8, mkexpr(vA), mkexpr(vB)) );
23091       break;
23092 
23093    case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269)
23094       DIP("vsubuwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23095       putVReg( vD_addr, binop(Iop_Sub32x4, mkexpr(vA), mkexpr(vB)) );
23096       break;
23097 
23098    case 0x4C0: // vsubudm (Subtract Unsigned Double Word Modulo)
23099       DIP("vsubudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23100       putVReg( vD_addr, binop(Iop_Sub64x2, mkexpr(vA), mkexpr(vB)) );
23101       break;
23102 
23103    case 0x600: // vsububs (Subtract Unsigned Byte Saturate, AV p266)
23104       DIP("vsububs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23105       putVReg( vD_addr, binop(Iop_QSub8Ux16, mkexpr(vA), mkexpr(vB)) );
23106       // TODO: set VSCR[SAT]
23107       break;
23108 
23109    case 0x640: // vsubuhs (Subtract Unsigned HWord Saturate, AV p268)
23110       DIP("vsubuhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23111       putVReg( vD_addr, binop(Iop_QSub16Ux8, mkexpr(vA), mkexpr(vB)) );
23112       // TODO: set VSCR[SAT]
23113       break;
23114 
23115    case 0x680: // vsubuws (Subtract Unsigned Word Saturate, AV p270)
23116       DIP("vsubuws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23117       putVReg( vD_addr, binop(Iop_QSub32Ux4, mkexpr(vA), mkexpr(vB)) );
23118       // TODO: set VSCR[SAT]
23119       break;
23120 
23121    case 0x700: // vsubsbs (Subtract Signed Byte Saturate, AV p262)
23122       DIP("vsubsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23123       putVReg( vD_addr, binop(Iop_QSub8Sx16, mkexpr(vA), mkexpr(vB)) );
23124       // TODO: set VSCR[SAT]
23125       break;
23126 
23127    case 0x740: // vsubshs (Subtract Signed Half Word Saturate, AV p263)
23128       DIP("vsubshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23129       putVReg( vD_addr, binop(Iop_QSub16Sx8, mkexpr(vA), mkexpr(vB)) );
23130       // TODO: set VSCR[SAT]
23131       break;
23132 
23133    case 0x780: // vsubsws (Subtract Signed Word Saturate, AV p264)
23134       DIP("vsubsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23135       putVReg( vD_addr, binop(Iop_QSub32Sx4, mkexpr(vA), mkexpr(vB)) );
23136       // TODO: set VSCR[SAT]
23137       break;
23138 
23139 
23140    /* Maximum */
23141    case 0x002: // vmaxub (Maximum Unsigned Byte, AV p182)
23142       DIP("vmaxub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23143       putVReg( vD_addr, binop(Iop_Max8Ux16, mkexpr(vA), mkexpr(vB)) );
23144       break;
23145 
23146    case 0x042: // vmaxuh (Maximum Unsigned Half Word, AV p183)
23147       DIP("vmaxuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23148       putVReg( vD_addr, binop(Iop_Max16Ux8, mkexpr(vA), mkexpr(vB)) );
23149       break;
23150 
23151    case 0x082: // vmaxuw (Maximum Unsigned Word, AV p184)
23152       DIP("vmaxuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23153       putVReg( vD_addr, binop(Iop_Max32Ux4, mkexpr(vA), mkexpr(vB)) );
23154       break;
23155 
23156    case 0x0C2: // vmaxud (Maximum Unsigned Double word)
23157       DIP("vmaxud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23158       putVReg( vD_addr, binop(Iop_Max64Ux2, mkexpr(vA), mkexpr(vB)) );
23159       break;
23160 
23161    case 0x102: // vmaxsb (Maximum Signed Byte, AV p179)
23162       DIP("vmaxsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23163       putVReg( vD_addr, binop(Iop_Max8Sx16, mkexpr(vA), mkexpr(vB)) );
23164       break;
23165 
23166    case 0x142: // vmaxsh (Maximum Signed Half Word, AV p180)
23167       DIP("vmaxsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23168       putVReg( vD_addr, binop(Iop_Max16Sx8, mkexpr(vA), mkexpr(vB)) );
23169       break;
23170 
23171    case 0x182: // vmaxsw (Maximum Signed Word, AV p181)
23172       DIP("vmaxsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23173       putVReg( vD_addr, binop(Iop_Max32Sx4, mkexpr(vA), mkexpr(vB)) );
23174       break;
23175 
23176    case 0x1C2: // vmaxsd (Maximum Signed Double word)
23177       DIP("vmaxsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23178       putVReg( vD_addr, binop(Iop_Max64Sx2, mkexpr(vA), mkexpr(vB)) );
23179       break;
23180 
23181    /* Minimum */
23182    case 0x202: // vminub (Minimum Unsigned Byte, AV p191)
23183       DIP("vminub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23184       putVReg( vD_addr, binop(Iop_Min8Ux16, mkexpr(vA), mkexpr(vB)) );
23185       break;
23186 
23187    case 0x242: // vminuh (Minimum Unsigned Half Word, AV p192)
23188       DIP("vminuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23189       putVReg( vD_addr, binop(Iop_Min16Ux8, mkexpr(vA), mkexpr(vB)) );
23190       break;
23191 
23192    case 0x282: // vminuw (Minimum Unsigned Word, AV p193)
23193       DIP("vminuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23194       putVReg( vD_addr, binop(Iop_Min32Ux4, mkexpr(vA), mkexpr(vB)) );
23195       break;
23196 
23197    case 0x2C2: // vminud (Minimum Unsigned Double Word)
23198       DIP("vminud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23199       putVReg( vD_addr, binop(Iop_Min64Ux2, mkexpr(vA), mkexpr(vB)) );
23200       break;
23201 
23202    case 0x302: // vminsb (Minimum Signed Byte, AV p188)
23203       DIP("vminsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23204       putVReg( vD_addr, binop(Iop_Min8Sx16, mkexpr(vA), mkexpr(vB)) );
23205       break;
23206 
23207    case 0x342: // vminsh (Minimum Signed Half Word, AV p189)
23208       DIP("vminsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23209       putVReg( vD_addr, binop(Iop_Min16Sx8, mkexpr(vA), mkexpr(vB)) );
23210       break;
23211 
23212    case 0x382: // vminsw (Minimum Signed Word, AV p190)
23213       DIP("vminsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23214       putVReg( vD_addr, binop(Iop_Min32Sx4, mkexpr(vA), mkexpr(vB)) );
23215       break;
23216 
23217    case 0x3C2: // vminsd (Minimum Signed Double Word)
23218       DIP("vminsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23219       putVReg( vD_addr, binop(Iop_Min64Sx2, mkexpr(vA), mkexpr(vB)) );
23220       break;
23221 
23222 
23223    /* Average */
23224    case 0x402: // vavgub (Average Unsigned Byte, AV p152)
23225       DIP("vavgub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23226       putVReg( vD_addr, binop(Iop_Avg8Ux16, mkexpr(vA), mkexpr(vB)) );
23227       break;
23228 
23229    case 0x442: // vavguh (Average Unsigned Half Word, AV p153)
23230       DIP("vavguh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23231       putVReg( vD_addr, binop(Iop_Avg16Ux8, mkexpr(vA), mkexpr(vB)) );
23232       break;
23233 
23234    case 0x482: // vavguw (Average Unsigned Word, AV p154)
23235       DIP("vavguw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23236       putVReg( vD_addr, binop(Iop_Avg32Ux4, mkexpr(vA), mkexpr(vB)) );
23237       break;
23238 
23239    case 0x502: // vavgsb (Average Signed Byte, AV p149)
23240       DIP("vavgsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23241       putVReg( vD_addr, binop(Iop_Avg8Sx16, mkexpr(vA), mkexpr(vB)) );
23242       break;
23243 
23244    case 0x542: // vavgsh (Average Signed Half Word, AV p150)
23245       DIP("vavgsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23246       putVReg( vD_addr, binop(Iop_Avg16Sx8, mkexpr(vA), mkexpr(vB)) );
23247       break;
23248 
23249    case 0x582: // vavgsw (Average Signed Word, AV p151)
23250       DIP("vavgsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23251       putVReg( vD_addr, binop(Iop_Avg32Sx4, mkexpr(vA), mkexpr(vB)) );
23252       break;
23253 
23254 
23255    /* Multiply */
23256    case 0x008: // vmuloub (Multiply Odd Unsigned Byte, AV p213)
23257       DIP("vmuloub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23258       putVReg( vD_addr,
23259                binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)));
23260       break;
23261 
23262    case 0x048: // vmulouh (Multiply Odd Unsigned Half Word, AV p214)
23263       DIP("vmulouh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23264       putVReg( vD_addr,
23265                binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)));
23266       break;
23267 
23268    case 0x088: // vmulouw (Multiply Odd Unsigned Word)
23269       DIP("vmulouw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23270       putVReg( vD_addr, binop( Iop_MullEven32Ux4, mkexpr(vA), mkexpr(vB) ) );
23271       break;
23272 
23273    case 0x089: // vmuluwm (Multiply Unsigned Word Modulo)
23274       DIP("vmuluwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23275       putVReg( vD_addr, binop( Iop_Mul32x4, mkexpr(vA), mkexpr(vB) ) );
23276       break;
23277 
23278    case 0x108: // vmulosb (Multiply Odd Signed Byte, AV p211)
23279       DIP("vmulosb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23280       putVReg( vD_addr,
23281                binop(Iop_MullEven8Sx16, mkexpr(vA), mkexpr(vB)));
23282       break;
23283 
23284    case 0x148: // vmulosh (Multiply Odd Signed Half Word, AV p212)
23285       DIP("vmulosh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23286       putVReg( vD_addr,
23287                binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)));
23288       break;
23289 
23290    case 0x188: // vmulosw (Multiply Odd Signed Word)
23291       DIP("vmulosw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23292       putVReg( vD_addr, binop( Iop_MullEven32Sx4, mkexpr(vA), mkexpr(vB) ) );
23293       break;
23294 
23295    case 0x208: // vmuleub (Multiply Even Unsigned Byte, AV p209)
23296       DIP("vmuleub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23297       putVReg( vD_addr, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
23298       break;
23299 
23300    case 0x248: // vmuleuh (Multiply Even Unsigned Half Word, AV p210)
23301       DIP("vmuleuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23302       putVReg( vD_addr, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
23303       break;
23304 
23305    case 0x288: // vmuleuw (Multiply Even Unsigned Word)
23306       DIP("vmuleuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23307       putVReg( vD_addr, MK_Iop_MullOdd32Ux4( mkexpr(vA), mkexpr(vB) ) );
23308       break;
23309 
23310    case 0x308: // vmulesb (Multiply Even Signed Byte, AV p207)
23311       DIP("vmulesb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23312       putVReg( vD_addr, MK_Iop_MullOdd8Sx16( mkexpr(vA), mkexpr(vB) ));
23313       break;
23314 
23315    case 0x348: // vmulesh (Multiply Even Signed Half Word, AV p208)
23316       DIP("vmulesh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23317       putVReg( vD_addr, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
23318       break;
23319 
23320    case 0x388: // vmulesw (Multiply Even Signed Word)
23321       DIP("vmulesw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23322       putVReg( vD_addr, MK_Iop_MullOdd32Sx4( mkexpr(vA), mkexpr(vB) ) );
23323       break;
23324 
23325    /* Sum Across Partial */
23326    case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275)
23327       IRTemp aEE, aEO, aOE, aOO;
23328       aEE = aEO = aOE = aOO = IRTemp_INVALID;
23329       DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23330 
23331       /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */
23332       expand8Ux16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
23333       expand16Ux8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
23334       expand16Ux8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
23335 
23336       /* break V128 to 4xI32's, zero-extending to I64's */
23337       breakV128to4x64U( mkexpr(aEE), &a15, &a11, &a7, &a3 );
23338       breakV128to4x64U( mkexpr(aOE), &a14, &a10, &a6, &a2 );
23339       breakV128to4x64U( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
23340       breakV128to4x64U( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
23341       breakV128to4x64U( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
23342 
23343       /* add lanes */
23344       assign( z3, binop(Iop_Add64, mkexpr(b3),
23345                      binop(Iop_Add64,
23346                         binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
23347                         binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
23348       assign( z2, binop(Iop_Add64, mkexpr(b2),
23349                      binop(Iop_Add64,
23350                          binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
23351                          binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
23352       assign( z1, binop(Iop_Add64, mkexpr(b1),
23353                      binop(Iop_Add64,
23354                          binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
23355                          binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
23356       assign( z0, binop(Iop_Add64, mkexpr(b0),
23357                      binop(Iop_Add64,
23358                          binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
23359                          binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
23360 
23361       /* saturate-narrow to 32bit, and combine to V128 */
23362       putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
23363                                          mkexpr(z1), mkexpr(z0)) );
23364       break;
23365    }
23366    case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273)
23367       IRTemp aEE, aEO, aOE, aOO;
23368       aEE = aEO = aOE = aOO = IRTemp_INVALID;
23369       DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23370 
23371       /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */
23372       expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
23373       expand16Sx8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
23374       expand16Sx8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
23375 
23376       /* break V128 to 4xI32's, sign-extending to I64's */
23377       breakV128to4x64S( mkexpr(aEE), &a15, &a11, &a7, &a3 );
23378       breakV128to4x64S( mkexpr(aOE), &a14, &a10, &a6, &a2 );
23379       breakV128to4x64S( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
23380       breakV128to4x64S( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
23381       breakV128to4x64S( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
23382 
23383       /* add lanes */
23384       assign( z3, binop(Iop_Add64, mkexpr(b3),
23385                      binop(Iop_Add64,
23386                         binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
23387                         binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
23388       assign( z2, binop(Iop_Add64, mkexpr(b2),
23389                      binop(Iop_Add64,
23390                         binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
23391                         binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
23392       assign( z1, binop(Iop_Add64, mkexpr(b1),
23393                      binop(Iop_Add64,
23394                         binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
23395                         binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
23396       assign( z0, binop(Iop_Add64, mkexpr(b0),
23397                      binop(Iop_Add64,
23398                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
23399                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
23400 
23401       /* saturate-narrow to 32bit, and combine to V128 */
23402       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
23403                                          mkexpr(z1), mkexpr(z0)) );
23404       break;
23405    }
23406    case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274)
23407       DIP("vsum4shs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23408 
23409       /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */
23410       expand16Sx8( mkexpr(vA), &aEvn, &aOdd ); // (7,5...),(6,4...)
23411 
23412       /* break V128 to 4xI32's, sign-extending to I64's */
23413       breakV128to4x64S( mkexpr(aEvn), &a7, &a5, &a3, &a1 );
23414       breakV128to4x64S( mkexpr(aOdd), &a6, &a4, &a2, &a0 );
23415       breakV128to4x64S( mkexpr(vB),   &b3, &b2, &b1, &b0 );
23416 
23417       /* add lanes */
23418       assign( z3, binop(Iop_Add64, mkexpr(b3),
23419                         binop(Iop_Add64, mkexpr(a7), mkexpr(a6))));
23420       assign( z2, binop(Iop_Add64, mkexpr(b2),
23421                         binop(Iop_Add64, mkexpr(a5), mkexpr(a4))));
23422       assign( z1, binop(Iop_Add64, mkexpr(b1),
23423                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2))));
23424       assign( z0, binop(Iop_Add64, mkexpr(b0),
23425                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0))));
23426 
23427       /* saturate-narrow to 32bit, and combine to V128 */
23428       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
23429                                          mkexpr(z1), mkexpr(z0)) );
23430       break;
23431    }
23432    case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272)
23433       DIP("vsum2sws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23434 
23435       /* break V128 to 4xI32's, sign-extending to I64's */
23436       breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
23437       breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
23438 
23439       /* add lanes */
23440       assign( z2, binop(Iop_Add64, mkexpr(b2),
23441                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2))) );
23442       assign( z0, binop(Iop_Add64, mkexpr(b0),
23443                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0))) );
23444 
23445       /* saturate-narrow to 32bit, and combine to V128 */
23446       putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkexpr(z2),
23447                                          mkU64(0), mkexpr(z0)) );
23448       break;
23449    }
23450    case 0x788: { // vsumsws  (Sum SW Saturate, AV p271)
23451       DIP("vsumsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23452 
23453       /* break V128 to 4xI32's, sign-extending to I64's */
23454       breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
23455       breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
23456 
23457       /* add lanes */
23458       assign( z0, binop(Iop_Add64, mkexpr(b0),
23459                      binop(Iop_Add64,
23460                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
23461                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
23462 
23463       /* saturate-narrow to 32bit, and combine to V128 */
23464       putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkU64(0),
23465                                          mkU64(0), mkexpr(z0)) );
23466       break;
23467    }
23468    default:
23469       vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2);
23470       return False;
23471    }
23472    return True;
23473 }
23474 
23475 /*
23476   AltiVec Logic Instructions
23477 */
dis_av_logic(UInt theInstr)23478 static Bool dis_av_logic ( UInt theInstr )
23479 {
23480    /* VX-Form */
23481    UChar opc1    = ifieldOPC(theInstr);
23482    UChar vD_addr = ifieldRegDS(theInstr);
23483    UChar vA_addr = ifieldRegA(theInstr);
23484    UChar vB_addr = ifieldRegB(theInstr);
23485    UInt  opc2    = IFIELD( theInstr, 0, 11 );
23486 
23487    IRTemp vA = newTemp(Ity_V128);
23488    IRTemp vB = newTemp(Ity_V128);
23489    assign( vA, getVReg(vA_addr));
23490    assign( vB, getVReg(vB_addr));
23491 
23492    if (opc1 != 0x4) {
23493       vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n");
23494       return False;
23495    }
23496 
23497    switch (opc2) {
23498    case 0x404: // vand (And, AV p147)
23499       DIP("vand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23500       putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), mkexpr(vB)) );
23501       break;
23502 
23503    case 0x444: // vandc (And, AV p148)
23504       DIP("vandc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23505       putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA),
23506                               unop(Iop_NotV128, mkexpr(vB))) );
23507       break;
23508 
23509    case 0x484: // vor (Or, AV p217)
23510       DIP("vor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23511       putVReg( vD_addr, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB)) );
23512       break;
23513 
23514    case 0x4C4: // vxor (Xor, AV p282)
23515       DIP("vxor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23516       putVReg( vD_addr, binop(Iop_XorV128, mkexpr(vA), mkexpr(vB)) );
23517       break;
23518 
23519    case 0x504: // vnor (Nor, AV p216)
23520       DIP("vnor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23521       putVReg( vD_addr,
23522          unop(Iop_NotV128, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB))) );
23523       break;
23524 
23525    case 0x544: // vorc (vA Or'd with complement of vb)
23526       DIP("vorc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23527       putVReg( vD_addr, binop( Iop_OrV128,
23528                                mkexpr( vA ),
23529                                unop( Iop_NotV128, mkexpr( vB ) ) ) );
23530       break;
23531 
23532    case 0x584: // vnand (Nand)
23533       DIP("vnand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23534       putVReg( vD_addr, unop( Iop_NotV128,
23535                               binop(Iop_AndV128, mkexpr( vA ),
23536                               mkexpr( vB ) ) ) );
23537       break;
23538 
23539    case 0x684: // veqv (complemented XOr)
23540       DIP("veqv v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
23541       putVReg( vD_addr, unop( Iop_NotV128,
23542                               binop( Iop_XorV128, mkexpr( vA ),
23543                               mkexpr( vB ) ) ) );
23544       break;
23545 
23546    default:
23547       vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2);
23548       return False;
23549    }
23550    return True;
23551 }
23552 
23553 /*
23554   AltiVec Compare Instructions
23555 */
dis_av_cmp(UInt theInstr)23556 static Bool dis_av_cmp ( UInt theInstr )
23557 {
23558    /* VXR-Form */
23559    UChar opc1     = ifieldOPC(theInstr);
23560    UChar vD_addr  = ifieldRegDS(theInstr);
23561    UChar vA_addr  = ifieldRegA(theInstr);
23562    UChar vB_addr  = ifieldRegB(theInstr);
23563    UChar flag_rC  = ifieldBIT10(theInstr);
23564    UInt  opc2     = IFIELD( theInstr, 0, 10 );
23565 
23566    IRTemp vA = newTemp(Ity_V128);
23567    IRTemp vB = newTemp(Ity_V128);
23568    IRTemp vD = newTemp(Ity_V128);
23569    assign( vA, getVReg(vA_addr));
23570    assign( vB, getVReg(vB_addr));
23571 
23572    if (opc1 != 0x4) {
23573       vex_printf("dis_av_cmp(ppc)(instr)\n");
23574       return False;
23575    }
23576 
23577    switch (opc2) {
23578    case 0x006: // vcmpequb (Compare Equal-to Unsigned B, AV p160)
23579       DIP("vcmpequb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23580                                       vD_addr, vA_addr, vB_addr);
23581       assign( vD, binop(Iop_CmpEQ8x16, mkexpr(vA), mkexpr(vB)) );
23582       break;
23583 
23584    case 0x007: // vcmpneb (Compare Not Equal byte)
23585       DIP("vcmpneb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23586                                       vD_addr, vA_addr, vB_addr);
23587       assign( vD, unop( Iop_NotV128,
23588                         binop( Iop_CmpEQ8x16, mkexpr( vA ), mkexpr( vB ) ) ) );
23589       break;
23590 
23591    case 0x046: // vcmpequh (Compare Equal-to Unsigned HW, AV p161)
23592       DIP("vcmpequh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23593                                       vD_addr, vA_addr, vB_addr);
23594       assign( vD, binop(Iop_CmpEQ16x8, mkexpr(vA), mkexpr(vB)) );
23595       break;
23596 
23597    case 0x047: // vcmpneh (Compare Not Equal-to  Halfword)
23598       DIP("vcmpneh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23599                                       vD_addr, vA_addr, vB_addr);
23600       assign( vD, unop( Iop_NotV128,
23601                         binop( Iop_CmpEQ16x8, mkexpr( vA ), mkexpr( vB ) ) ) );
23602       break;
23603 
23604    case 0x086: // vcmpequw (Compare Equal-to Unsigned W, AV p162)
23605       DIP("vcmpequw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23606                                       vD_addr, vA_addr, vB_addr);
23607       assign( vD, binop(Iop_CmpEQ32x4, mkexpr(vA), mkexpr(vB)) );
23608       break;
23609 
23610    case 0x087: // vcmpnew (Compare Not Equal-to Word)
23611       DIP("vcmpnew%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23612                                       vD_addr, vA_addr, vB_addr);
23613       assign( vD, unop( Iop_NotV128,
23614                         binop( Iop_CmpEQ32x4, mkexpr( vA ), mkexpr( vB ) ) ) );
23615       break;
23616 
23617    case 0x107: // vcmpnezb (Compare Not Equal or Zero byte)
23618       {
23619          IRTemp vAeqvB = newTemp( Ity_V128 );
23620          IRTemp vAeq0  = newTemp( Ity_V128 );
23621          IRTemp vBeq0  = newTemp( Ity_V128 );
23622          IRTemp zero   = newTemp( Ity_V128 );
23623 
23624          DIP("vcmpnezb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23625                                          vD_addr, vA_addr, vB_addr);
23626 
23627          assign( zero, binop( Iop_64HLtoV128, mkU64( 0 ), mkU64( 0 ) ) );
23628          assign( vAeq0, binop( Iop_CmpEQ8x16, mkexpr( vA ), mkexpr( zero ) ) );
23629          assign( vBeq0, binop( Iop_CmpEQ8x16, mkexpr( vB ), mkexpr( zero ) ) );
23630          assign( vAeqvB, unop( Iop_NotV128,
23631                                binop( Iop_CmpEQ8x16, mkexpr( vA ),
23632                                       mkexpr( vB ) ) ) );
23633 
23634          assign( vD, mkOr3_V128( vAeqvB, vAeq0, vBeq0  ) );
23635       }
23636       break;
23637 
23638    case 0x147: // vcmpnezh (Compare Not Equal or Zero Halfword)
23639       {
23640          IRTemp vAeqvB = newTemp( Ity_V128 );
23641          IRTemp vAeq0  = newTemp( Ity_V128 );
23642          IRTemp vBeq0  = newTemp( Ity_V128 );
23643          IRTemp zero   = newTemp( Ity_V128 );
23644 
23645          DIP("vcmpnezh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23646                                          vD_addr, vA_addr, vB_addr);
23647 
23648          assign( zero, binop( Iop_64HLtoV128, mkU64( 0 ), mkU64( 0 ) ) );
23649          assign( vAeq0, binop( Iop_CmpEQ16x8, mkexpr( vA ), mkexpr( zero ) ) );
23650          assign( vBeq0, binop( Iop_CmpEQ16x8, mkexpr( vB ), mkexpr( zero ) ) );
23651          assign( vAeqvB, unop( Iop_NotV128,
23652                                binop(Iop_CmpEQ16x8, mkexpr( vA ),
23653                                      mkexpr( vB ) ) ) );
23654 
23655          assign( vD, binop( Iop_OrV128,
23656                             binop( Iop_OrV128,
23657                                    mkexpr( vAeq0 ),
23658                                    mkexpr( vBeq0 ) ),
23659                             mkexpr( vAeqvB ) ) );
23660       }
23661       break;
23662 
23663    case 0x187: // vcmpnezw (Compare Not Equal or Zero Word)
23664       {
23665          IRTemp vAeqvB = newTemp( Ity_V128 );
23666          IRTemp vAeq0  = newTemp( Ity_V128 );
23667          IRTemp vBeq0  = newTemp( Ity_V128 );
23668          IRTemp zero   = newTemp( Ity_V128 );
23669 
23670          DIP("vcmpnezw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23671                                          vD_addr, vA_addr, vB_addr);
23672 
23673          assign( zero, binop( Iop_64HLtoV128, mkU64( 0 ), mkU64( 0 ) ) );
23674          assign( vAeq0, binop( Iop_CmpEQ32x4, mkexpr( vA ), mkexpr( zero ) ) );
23675          assign( vBeq0, binop( Iop_CmpEQ32x4, mkexpr( vB ), mkexpr( zero ) ) );
23676          assign( vAeqvB, unop( Iop_NotV128,
23677                                binop(Iop_CmpEQ32x4, mkexpr( vA ),
23678                                      mkexpr( vB ) ) ) );
23679 
23680          assign( vD, binop( Iop_OrV128,
23681                             binop( Iop_OrV128,
23682                                    mkexpr( vAeq0 ),
23683                                    mkexpr( vBeq0 ) ),
23684                             mkexpr( vAeqvB ) ) );
23685       }
23686       break;
23687 
23688    case 0x0C7: // vcmpequd (Compare Equal-to Unsigned Doubleword)
23689       DIP("vcmpequd%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23690                                       vD_addr, vA_addr, vB_addr);
23691       assign( vD, binop(Iop_CmpEQ64x2, mkexpr(vA), mkexpr(vB)) );
23692       break;
23693 
23694    case 0x206: // vcmpgtub (Compare Greater-than Unsigned B, AV p168)
23695       DIP("vcmpgtub%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23696                                       vD_addr, vA_addr, vB_addr);
23697       assign( vD, binop(Iop_CmpGT8Ux16, mkexpr(vA), mkexpr(vB)) );
23698       break;
23699 
23700    case 0x246: // vcmpgtuh (Compare Greater-than Unsigned HW, AV p169)
23701       DIP("vcmpgtuh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23702                                       vD_addr, vA_addr, vB_addr);
23703       assign( vD, binop(Iop_CmpGT16Ux8, mkexpr(vA), mkexpr(vB)) );
23704       break;
23705 
23706    case 0x286: // vcmpgtuw (Compare Greater-than Unsigned W, AV p170)
23707       DIP("vcmpgtuw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23708                                        vD_addr, vA_addr, vB_addr);
23709       assign( vD, binop(Iop_CmpGT32Ux4, mkexpr(vA), mkexpr(vB)) );
23710       break;
23711 
23712    case 0x2C7: // vcmpgtud (Compare Greater-than Unsigned double)
23713       DIP("vcmpgtud%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23714                                       vD_addr, vA_addr, vB_addr);
23715       assign( vD, binop(Iop_CmpGT64Ux2, mkexpr(vA), mkexpr(vB)) );
23716       break;
23717 
23718    case 0x306: // vcmpgtsb (Compare Greater-than Signed B, AV p165)
23719       DIP("vcmpgtsb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23720                                        vD_addr, vA_addr, vB_addr);
23721       assign( vD, binop(Iop_CmpGT8Sx16, mkexpr(vA), mkexpr(vB)) );
23722       break;
23723 
23724    case 0x346: // vcmpgtsh (Compare Greater-than Signed HW, AV p166)
23725       DIP("vcmpgtsh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23726                                       vD_addr, vA_addr, vB_addr);
23727       assign( vD, binop(Iop_CmpGT16Sx8, mkexpr(vA), mkexpr(vB)) );
23728       break;
23729 
23730    case 0x386: // vcmpgtsw (Compare Greater-than Signed W, AV p167)
23731       DIP("vcmpgtsw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23732                                       vD_addr, vA_addr, vB_addr);
23733       assign( vD, binop(Iop_CmpGT32Sx4, mkexpr(vA), mkexpr(vB)) );
23734       break;
23735 
23736    case 0x3C7: // vcmpgtsd (Compare Greater-than Signed double)
23737       DIP("vcmpgtsd%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
23738                                       vD_addr, vA_addr, vB_addr);
23739       assign( vD, binop(Iop_CmpGT64Sx2, mkexpr(vA), mkexpr(vB)) );
23740       break;
23741 
23742    default:
23743       vex_printf("dis_av_cmp(ppc)(opc2)\n");
23744       return False;
23745    }
23746 
23747    putVReg( vD_addr, mkexpr(vD) );
23748 
23749    if (flag_rC) {
23750       set_AV_CR6( mkexpr(vD), True );
23751    }
23752    return True;
23753 }
23754 
23755 /*
23756   AltiVec Multiply-Sum Instructions
23757 */
dis_av_multarith(UInt theInstr)23758 static Bool dis_av_multarith ( UInt theInstr )
23759 {
23760    /* VA-Form */
23761    UChar opc1     = ifieldOPC(theInstr);
23762    UChar vD_addr  = ifieldRegDS(theInstr);
23763    UChar vA_addr  = ifieldRegA(theInstr);
23764    UChar vB_addr  = ifieldRegB(theInstr);
23765    UChar vC_addr  = ifieldRegC(theInstr);
23766    UChar opc2     = toUChar( IFIELD( theInstr, 0, 6 ) );
23767 
23768    IRTemp vA    = newTemp(Ity_V128);
23769    IRTemp vB    = newTemp(Ity_V128);
23770    IRTemp vC    = newTemp(Ity_V128);
23771    IRTemp zeros = newTemp(Ity_V128);
23772    IRTemp aLo   = newTemp(Ity_V128);
23773    IRTemp bLo   = newTemp(Ity_V128);
23774    IRTemp cLo   = newTemp(Ity_V128);
23775    IRTemp zLo   = newTemp(Ity_V128);
23776    IRTemp aHi   = newTemp(Ity_V128);
23777    IRTemp bHi   = newTemp(Ity_V128);
23778    IRTemp cHi   = newTemp(Ity_V128);
23779    IRTemp zHi   = newTemp(Ity_V128);
23780    IRTemp abEvn = newTemp(Ity_V128);
23781    IRTemp abOdd = newTemp(Ity_V128);
23782    IRTemp z3    = newTemp(Ity_I64);
23783    IRTemp z2    = newTemp(Ity_I64);
23784    IRTemp z1    = newTemp(Ity_I64);
23785    IRTemp z0    = newTemp(Ity_I64);
23786    IRTemp ab7, ab6, ab5, ab4, ab3, ab2, ab1, ab0;
23787    IRTemp c3, c2, c1, c0;
23788 
23789    ab7 = ab6 = ab5 = ab4 = ab3 = ab2 = ab1 = ab0 = IRTemp_INVALID;
23790    c3 = c2 = c1 = c0 = IRTemp_INVALID;
23791 
23792    assign( vA, getVReg(vA_addr));
23793    assign( vB, getVReg(vB_addr));
23794    assign( vC, getVReg(vC_addr));
23795    assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
23796 
23797    if (opc1 != 0x4) {
23798       vex_printf("dis_av_multarith(ppc)(instr)\n");
23799       return False;
23800    }
23801 
23802    switch (opc2) {
23803    /* Multiply-Add */
23804    case 0x20: { // vmhaddshs (Mult Hi, Add Signed HW Saturate, AV p185)
23805       IRTemp cSigns = newTemp(Ity_V128);
23806       DIP("vmhaddshs v%d,v%d,v%d,v%d\n",
23807           vD_addr, vA_addr, vB_addr, vC_addr);
23808       assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)));
23809       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
23810       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
23811       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
23812       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
23813       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
23814       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
23815 
23816       assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
23817                          binop(Iop_SarN32x4,
23818                                binop(Iop_MullEven16Sx8,
23819                                      mkexpr(aLo), mkexpr(bLo)),
23820                                mkU8(15))) );
23821 
23822       assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
23823                          binop(Iop_SarN32x4,
23824                                binop(Iop_MullEven16Sx8,
23825                                      mkexpr(aHi), mkexpr(bHi)),
23826                                mkU8(15))) );
23827 
23828       putVReg( vD_addr,
23829                binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
23830       break;
23831    }
23832    case 0x21: { // vmhraddshs (Mult High Round, Add Signed HW Saturate, AV p186)
23833       IRTemp zKonst = newTemp(Ity_V128);
23834       IRTemp cSigns = newTemp(Ity_V128);
23835       DIP("vmhraddshs v%d,v%d,v%d,v%d\n",
23836           vD_addr, vA_addr, vB_addr, vC_addr);
23837       assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)) );
23838       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
23839       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
23840       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
23841       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
23842       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
23843       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
23844 
23845       /* shifting our const avoids store/load version of Dup */
23846       assign( zKonst, binop(Iop_ShlN32x4, unop(Iop_Dup32x4, mkU32(0x1)),
23847                             mkU8(14)) );
23848 
23849       assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
23850                          binop(Iop_SarN32x4,
23851                                binop(Iop_Add32x4, mkexpr(zKonst),
23852                                      binop(Iop_MullEven16Sx8,
23853                                            mkexpr(aLo), mkexpr(bLo))),
23854                                mkU8(15))) );
23855 
23856       assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
23857                          binop(Iop_SarN32x4,
23858                                binop(Iop_Add32x4, mkexpr(zKonst),
23859                                      binop(Iop_MullEven16Sx8,
23860                                            mkexpr(aHi), mkexpr(bHi))),
23861                                mkU8(15))) );
23862 
23863       putVReg( vD_addr,
23864                binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
23865       break;
23866    }
23867    case 0x22: { // vmladduhm (Mult Low, Add Unsigned HW Modulo, AV p194)
23868       DIP("vmladduhm v%d,v%d,v%d,v%d\n",
23869           vD_addr, vA_addr, vB_addr, vC_addr);
23870       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
23871       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
23872       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vC)));
23873       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
23874       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
23875       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vC)));
23876       assign(zLo, binop(Iop_Add32x4,
23877                      binop(Iop_MullEven16Ux8, mkexpr(aLo), mkexpr(bLo)),
23878                      mkexpr(cLo)) );
23879       assign(zHi, binop(Iop_Add32x4,
23880                      binop(Iop_MullEven16Ux8, mkexpr(aHi), mkexpr(bHi)),
23881                      mkexpr(cHi)));
23882       putVReg( vD_addr,
23883                binop(Iop_NarrowBin32to16x8, mkexpr(zHi), mkexpr(zLo)) );
23884       break;
23885    }
23886 
23887    case 0x23: { // vmsumudm
23888       DIP("vmsumudm v%d,v%d,v%d,v%d\n",
23889           vD_addr, vA_addr, vB_addr, vC_addr);
23890       /* This instruction takes input vectors VA, VB consisting of 2 usigned
23891          64-bit integer elements and a 128 bit unsigned input U128_C.  The
23892          instruction performs the following operation:
23893 
23894             VA[0] * VB[0] -> U128_mul_result0;
23895             VA[1] * VB[1] -> U128_mul_result1;
23896             U128_C + U128_mul_result0 + U128_mul_result1 -> U128_partial_sum;
23897             carry out and overflow is discarded.
23898       */
23899 
23900       /* The Iop_MulI128low assumes the upper 64-bits in the two input operands
23901          are zero. */
23902       IRTemp mul_result0 = newTemp( Ity_I128 );
23903       IRTemp mul_result1 = newTemp( Ity_I128 );
23904       IRTemp partial_sum_hi = newTemp( Ity_I64 );
23905       IRTemp partial_sum_low = newTemp( Ity_I64 );
23906       IRTemp result_hi  = newTemp( Ity_I64 );
23907       IRTemp result_low = newTemp( Ity_I64 );
23908       IRExpr *ca_sum, *ca_result;
23909 
23910 
23911       /* Do multiplications */
23912       assign ( mul_result0, binop( Iop_MullU64,
23913                                    unop( Iop_V128to64, mkexpr( vA ) ),
23914                                    unop( Iop_V128to64, mkexpr( vB) ) ) );
23915 
23916       assign ( mul_result1, binop( Iop_MullU64,
23917                                    unop( Iop_V128HIto64, mkexpr( vA ) ),
23918                                    unop( Iop_V128HIto64, mkexpr( vB) ) ) );
23919 
23920       /* Add the two 128-bit results using 64-bit unsigned adds, calculate carry
23921          from low 64-bits add into sum of upper 64-bits.  Throw away carry out
23922          of the upper 64-bit sum. */
23923       assign ( partial_sum_low, binop( Iop_Add64,
23924                                        unop( Iop_128to64, mkexpr( mul_result0 ) ),
23925                                        unop( Iop_128to64, mkexpr( mul_result1 ) )
23926                                        ) );
23927 
23928       /* ca_sum is type U32 */
23929       ca_sum =  calculate_XER_CA_64 ( PPCG_FLAG_OP_ADD,
23930                                       mkexpr(partial_sum_low ),
23931                                       unop( Iop_128to64, mkexpr( mul_result0 ) ),
23932                                       unop( Iop_128to64, mkexpr( mul_result1 ) ),
23933                                       mkU64( 0 ) );
23934 
23935       assign ( partial_sum_hi,
23936                binop( Iop_Add64,
23937                       binop( Iop_Add64,
23938                              unop( Iop_128HIto64, mkexpr( mul_result0 ) ),
23939                              unop( Iop_128HIto64, mkexpr( mul_result1 ) ) ),
23940                       binop( Iop_32HLto64, mkU32( 0 ), ca_sum ) ) );
23941 
23942       /* Now add in the value of C */
23943       assign ( result_low, binop( Iop_Add64,
23944                                   mkexpr( partial_sum_low ),
23945                                   unop( Iop_V128to64, mkexpr( vC ) ) ) );
23946 
23947       /* ca_result is type U32 */
23948       ca_result =  calculate_XER_CA_64(  PPCG_FLAG_OP_ADD,
23949                                          mkexpr( result_low ),
23950                                          mkexpr( partial_sum_low ),
23951                                          unop( Iop_V128to64,
23952                                                mkexpr( vC ) ),
23953                                          mkU64( 0 ) );
23954 
23955       assign ( result_hi,
23956                binop( Iop_Add64,
23957                       binop( Iop_Add64,
23958                              mkexpr( partial_sum_hi ),
23959                              unop( Iop_V128HIto64, mkexpr( vC ) ) ),
23960                       binop( Iop_32HLto64, mkU32( 0 ), ca_result ) ) );
23961 
23962       putVReg( vD_addr, binop( Iop_64HLtoV128,
23963                                mkexpr( result_hi ), mkexpr ( result_low ) ) );
23964       break;
23965    }
23966 
23967    /* Multiply-Sum */
23968    case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204)
23969       IRTemp abEE, abEO, abOE, abOO;
23970       abEE = abEO = abOE = abOO = IRTemp_INVALID;
23971       DIP("vmsumubm v%d,v%d,v%d,v%d\n",
23972           vD_addr, vA_addr, vB_addr, vC_addr);
23973 
23974       /* multiply vA,vB (unsigned, widening) */
23975       assign( abEvn, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
23976       assign( abOdd, binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)) );
23977 
23978       /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */
23979       expand16Ux8( mkexpr(abEvn), &abEE, &abEO );
23980       expand16Ux8( mkexpr(abOdd), &abOE, &abOO );
23981 
23982       putVReg( vD_addr,
23983          binop(Iop_Add32x4, mkexpr(vC),
23984                binop(Iop_Add32x4,
23985                      binop(Iop_Add32x4, mkexpr(abEE), mkexpr(abEO)),
23986                      binop(Iop_Add32x4, mkexpr(abOE), mkexpr(abOO)))) );
23987       break;
23988    }
23989    case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201)
23990       IRTemp aEvn, aOdd, bEvn, bOdd;
23991       IRTemp abEE = newTemp(Ity_V128);
23992       IRTemp abEO = newTemp(Ity_V128);
23993       IRTemp abOE = newTemp(Ity_V128);
23994       IRTemp abOO = newTemp(Ity_V128);
23995       aEvn = aOdd = bEvn = bOdd = IRTemp_INVALID;
23996       DIP("vmsummbm v%d,v%d,v%d,v%d\n",
23997           vD_addr, vA_addr, vB_addr, vC_addr);
23998 
23999       /* sign-extend vA, zero-extend vB, for mixed-sign multiply
24000          (separating out adjacent lanes to different vectors) */
24001       expand8Sx16( mkexpr(vA), &aEvn, &aOdd );
24002       expand8Ux16( mkexpr(vB), &bEvn, &bOdd );
24003 
24004       /* multiply vA, vB, again separating adjacent lanes */
24005       assign( abEE, MK_Iop_MullOdd16Sx8( mkexpr(aEvn), mkexpr(bEvn) ));
24006       assign( abEO, binop(Iop_MullEven16Sx8, mkexpr(aEvn), mkexpr(bEvn)) );
24007       assign( abOE, MK_Iop_MullOdd16Sx8( mkexpr(aOdd), mkexpr(bOdd) ));
24008       assign( abOO, binop(Iop_MullEven16Sx8, mkexpr(aOdd), mkexpr(bOdd)) );
24009 
24010       /* add results together, + vC */
24011       putVReg( vD_addr,
24012          binop(Iop_QAdd32Sx4, mkexpr(vC),
24013                binop(Iop_QAdd32Sx4,
24014                      binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)),
24015                      binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)))) );
24016       break;
24017    }
24018    case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205)
24019       DIP("vmsumuhm v%d,v%d,v%d,v%d\n",
24020           vD_addr, vA_addr, vB_addr, vC_addr);
24021       assign( abEvn, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
24022       assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
24023       putVReg( vD_addr,
24024          binop(Iop_Add32x4, mkexpr(vC),
24025                binop(Iop_Add32x4, mkexpr(abEvn), mkexpr(abOdd))) );
24026       break;
24027    }
24028    case 0x27: { // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206)
24029       DIP("vmsumuhs v%d,v%d,v%d,v%d\n",
24030           vD_addr, vA_addr, vB_addr, vC_addr);
24031       /* widening multiply, separating lanes */
24032       assign( abEvn, MK_Iop_MullOdd16Ux8(mkexpr(vA), mkexpr(vB) ));
24033       assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
24034 
24035       /* break V128 to 4xI32's, zero-extending to I64's */
24036       breakV128to4x64U( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
24037       breakV128to4x64U( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
24038       breakV128to4x64U( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
24039 
24040       /* add lanes */
24041       assign( z3, binop(Iop_Add64, mkexpr(c3),
24042                         binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
24043       assign( z2, binop(Iop_Add64, mkexpr(c2),
24044                         binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
24045       assign( z1, binop(Iop_Add64, mkexpr(c1),
24046                         binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
24047       assign( z0, binop(Iop_Add64, mkexpr(c0),
24048                         binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
24049 
24050       /* saturate-narrow to 32bit, and combine to V128 */
24051       putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
24052                                          mkexpr(z1), mkexpr(z0)) );
24053 
24054       break;
24055    }
24056    case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202)
24057       DIP("vmsumshm v%d,v%d,v%d,v%d\n",
24058           vD_addr, vA_addr, vB_addr, vC_addr);
24059       assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
24060       assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
24061       putVReg( vD_addr,
24062          binop(Iop_Add32x4, mkexpr(vC),
24063                binop(Iop_Add32x4, mkexpr(abOdd), mkexpr(abEvn))) );
24064       break;
24065    }
24066    case 0x29: { // vmsumshs (Multiply Sum Signed HW Saturate, AV p203)
24067       DIP("vmsumshs v%d,v%d,v%d,v%d\n",
24068           vD_addr, vA_addr, vB_addr, vC_addr);
24069       /* widening multiply, separating lanes */
24070       assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
24071       assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
24072 
24073       /* break V128 to 4xI32's, sign-extending to I64's */
24074       breakV128to4x64S( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
24075       breakV128to4x64S( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
24076       breakV128to4x64S( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
24077 
24078       /* add lanes */
24079       assign( z3, binop(Iop_Add64, mkexpr(c3),
24080                         binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
24081       assign( z2, binop(Iop_Add64, mkexpr(c2),
24082                         binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
24083       assign( z1, binop(Iop_Add64, mkexpr(c1),
24084                         binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
24085       assign( z0, binop(Iop_Add64, mkexpr(c0),
24086                         binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
24087 
24088       /* saturate-narrow to 32bit, and combine to V128 */
24089       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
24090                                          mkexpr(z1), mkexpr(z0)) );
24091       break;
24092    }
24093    default:
24094       vex_printf("dis_av_multarith(ppc)(opc2)\n");
24095       return False;
24096    }
24097    return True;
24098 }
24099 
24100 /*
24101   AltiVec Polynomial Multiply-Sum Instructions
24102 */
dis_av_polymultarith(UInt theInstr)24103 static Bool dis_av_polymultarith ( UInt theInstr )
24104 {
24105    /* VA-Form */
24106    UChar opc1     = ifieldOPC(theInstr);
24107    UChar vD_addr  = ifieldRegDS(theInstr);
24108    UChar vA_addr  = ifieldRegA(theInstr);
24109    UChar vB_addr  = ifieldRegB(theInstr);
24110    UChar vC_addr  = ifieldRegC(theInstr);
24111    UInt  opc2     = IFIELD(theInstr, 0, 11);
24112    IRTemp vA    = newTemp(Ity_V128);
24113    IRTemp vB    = newTemp(Ity_V128);
24114    IRTemp vC    = newTemp(Ity_V128);
24115 
24116    assign( vA, getVReg(vA_addr));
24117    assign( vB, getVReg(vB_addr));
24118    assign( vC, getVReg(vC_addr));
24119 
24120    if (opc1 != 0x4) {
24121       vex_printf("dis_av_polymultarith(ppc)(instr)\n");
24122       return False;
24123    }
24124 
24125    switch (opc2) {
24126       /* Polynomial Multiply-Add */
24127       case 0x408:  // vpmsumb   Vector Polynomial Multiply-sum Byte
24128          DIP("vpmsumb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24129          putVReg( vD_addr, binop(Iop_PolynomialMulAdd8x16,
24130                                  mkexpr(vA), mkexpr(vB)) );
24131          break;
24132       case 0x448:  // vpmsumd   Vector Polynomial Multiply-sum Double Word
24133          DIP("vpmsumd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24134          putVReg( vD_addr, binop(Iop_PolynomialMulAdd64x2,
24135                                  mkexpr(vA), mkexpr(vB)) );
24136          break;
24137       case 0x488:  // vpmsumw   Vector Polynomial Multiply-sum Word
24138          DIP("vpmsumw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24139          putVReg( vD_addr, binop(Iop_PolynomialMulAdd32x4,
24140                                  mkexpr(vA), mkexpr(vB)) );
24141          break;
24142       case 0x4C8:  // vpmsumh   Vector Polynomial Multiply-sum Half Word
24143          DIP("vpmsumh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24144          putVReg( vD_addr, binop(Iop_PolynomialMulAdd16x8,
24145                                  mkexpr(vA), mkexpr(vB)) );
24146          break;
24147       default:
24148          vex_printf("dis_av_polymultarith(ppc)(opc2=0x%x)\n", opc2);
24149          return False;
24150    }
24151    return True;
24152 }
24153 
24154 /*
24155   AltiVec Shift/Rotate Instructions
24156 */
dis_av_shift(UInt theInstr)24157 static Bool dis_av_shift ( UInt theInstr )
24158 {
24159    /* VX-Form */
24160    UChar opc1    = ifieldOPC(theInstr);
24161    UChar vD_addr = ifieldRegDS(theInstr);
24162    UChar vA_addr = ifieldRegA(theInstr);
24163    UChar vB_addr = ifieldRegB(theInstr);
24164    UInt  opc2    = IFIELD( theInstr, 0, 11 );
24165 
24166    IRTemp vA = newTemp(Ity_V128);
24167    IRTemp vB = newTemp(Ity_V128);
24168    assign( vA, getVReg(vA_addr));
24169    assign( vB, getVReg(vB_addr));
24170 
24171    if (opc1 != 0x4){
24172       vex_printf("dis_av_shift(ppc)(instr)\n");
24173       return False;
24174    }
24175 
24176    switch (opc2) {
24177    /* Rotate */
24178    case 0x004: // vrlb (Rotate Left Integer B, AV p234)
24179       DIP("vrlb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24180       putVReg( vD_addr, binop(Iop_Rol8x16, mkexpr(vA), mkexpr(vB)) );
24181       break;
24182 
24183    case 0x044: // vrlh (Rotate Left Integer HW, AV p235)
24184       DIP("vrlh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24185       putVReg( vD_addr, binop(Iop_Rol16x8, mkexpr(vA), mkexpr(vB)) );
24186       break;
24187 
24188    case 0x084: // vrlw (Rotate Left Integer W, AV p236)
24189       DIP("vrlw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24190       putVReg( vD_addr, binop(Iop_Rol32x4, mkexpr(vA), mkexpr(vB)) );
24191       break;
24192 
24193    case 0x0C4: // vrld (Rotate Left Integer Double Word)
24194       DIP("vrld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24195       putVReg( vD_addr, binop(Iop_Rol64x2, mkexpr(vA), mkexpr(vB)) );
24196       break;
24197 
24198 
24199    /* Shift Left */
24200    case 0x104: // vslb (Shift Left Integer B, AV p240)
24201       DIP("vslb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24202       putVReg( vD_addr, binop(Iop_Shl8x16, mkexpr(vA), mkexpr(vB)) );
24203       break;
24204 
24205    case 0x144: // vslh (Shift Left Integer HW, AV p242)
24206       DIP("vslh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24207       putVReg( vD_addr, binop(Iop_Shl16x8, mkexpr(vA), mkexpr(vB)) );
24208       break;
24209 
24210    case 0x184: // vslw (Shift Left Integer W, AV p244)
24211       DIP("vslw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24212       putVReg( vD_addr, binop(Iop_Shl32x4, mkexpr(vA), mkexpr(vB)) );
24213       break;
24214 
24215    case 0x5C4: // vsld (Shift Left Integer Double Word)
24216       DIP("vsld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24217       putVReg( vD_addr, binop(Iop_Shl64x2, mkexpr(vA), mkexpr(vB)) );
24218       break;
24219 
24220    case 0x1C4: { // vsl (Shift Left, AV p239)
24221       IRTemp sh = newTemp(Ity_I8);
24222       DIP("vsl v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24223       assign( sh, binop(Iop_And8, mkU8(0x7),
24224                         unop(Iop_32to8,
24225                              unop(Iop_V128to32, mkexpr(vB)))) );
24226       putVReg( vD_addr,
24227                binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
24228       break;
24229    }
24230    case 0x40C: { // vslo (Shift Left by Octet, AV p243)
24231       IRTemp sh = newTemp(Ity_I8);
24232       DIP("vslo v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24233       assign( sh, binop(Iop_And8, mkU8(0x78),
24234                         unop(Iop_32to8,
24235                              unop(Iop_V128to32, mkexpr(vB)))) );
24236       putVReg( vD_addr,
24237                binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
24238       break;
24239    }
24240 
24241 
24242    /* Shift Right */
24243    case 0x204: // vsrb (Shift Right B, AV p256)
24244       DIP("vsrb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24245       putVReg( vD_addr, binop(Iop_Shr8x16, mkexpr(vA), mkexpr(vB)) );
24246       break;
24247 
24248    case 0x244: // vsrh (Shift Right HW, AV p257)
24249       DIP("vsrh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24250       putVReg( vD_addr, binop(Iop_Shr16x8, mkexpr(vA), mkexpr(vB)) );
24251       break;
24252 
24253    case 0x284: // vsrw (Shift Right W, AV p259)
24254       DIP("vsrw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24255       putVReg( vD_addr, binop(Iop_Shr32x4, mkexpr(vA), mkexpr(vB)) );
24256       break;
24257 
24258    case 0x2C4: { // vsr (Shift Right, AV p251)
24259       IRTemp sh = newTemp(Ity_I8);
24260       DIP("vsr v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24261       assign( sh, binop(Iop_And8, mkU8(0x7),
24262                         unop(Iop_32to8,
24263                              unop(Iop_V128to32, mkexpr(vB)))) );
24264       putVReg( vD_addr,
24265                binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
24266       break;
24267    }
24268    case 0x304: // vsrab (Shift Right Alg B, AV p253)
24269       DIP("vsrab v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24270       putVReg( vD_addr, binop(Iop_Sar8x16, mkexpr(vA), mkexpr(vB)) );
24271       break;
24272 
24273    case 0x344: // vsrah (Shift Right Alg HW, AV p254)
24274       DIP("vsrah v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24275       putVReg( vD_addr, binop(Iop_Sar16x8, mkexpr(vA), mkexpr(vB)) );
24276       break;
24277 
24278    case 0x384: // vsraw (Shift Right Alg W, AV p255)
24279       DIP("vsraw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24280       putVReg( vD_addr, binop(Iop_Sar32x4, mkexpr(vA), mkexpr(vB)) );
24281       break;
24282 
24283    case 0x3C4: // vsrad (Shift Right Alg Double Word)
24284       DIP("vsrad v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24285       putVReg( vD_addr, binop(Iop_Sar64x2, mkexpr(vA), mkexpr(vB)) );
24286       break;
24287 
24288    case 0x44C: { // vsro (Shift Right by Octet, AV p258)
24289       IRTemp sh = newTemp(Ity_I8);
24290       DIP("vsro v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24291       assign( sh, binop(Iop_And8, mkU8(0x78),
24292                         unop(Iop_32to8,
24293                              unop(Iop_V128to32, mkexpr(vB)))) );
24294       putVReg( vD_addr,
24295                binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
24296       break;
24297    }
24298 
24299    case 0x6C4: // vsrd (Shift Right Double Word)
24300       DIP("vsrd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24301       putVReg( vD_addr, binop(Iop_Shr64x2, mkexpr(vA), mkexpr(vB)) );
24302       break;
24303 
24304 
24305    default:
24306       vex_printf("dis_av_shift(ppc)(opc2)\n");
24307       return False;
24308    }
24309    return True;
24310 }
24311 
24312 /*
24313   AltiVec Permute Instructions
24314 */
dis_av_permute(UInt theInstr)24315 static Bool dis_av_permute ( UInt theInstr )
24316 {
24317    /* VA-Form, VX-Form */
24318    UChar opc1      = ifieldOPC(theInstr);
24319    UChar vD_addr   = ifieldRegDS(theInstr);
24320    UChar vA_addr   = ifieldRegA(theInstr);
24321    UChar UIMM_5    = vA_addr;
24322    UChar vB_addr   = ifieldRegB(theInstr);
24323    UChar vC_addr   = ifieldRegC(theInstr);
24324    UChar b10       = ifieldBIT10(theInstr);
24325    UChar SHB_uimm4 = toUChar( IFIELD( theInstr, 6, 4 ) );
24326    UInt  opc2      = toUChar( IFIELD( theInstr, 0, 6 ) );
24327 
24328    UChar SIMM_8 = extend_s_5to8(UIMM_5);
24329 
24330    IRTemp vA = newTemp(Ity_V128);
24331    IRTemp vB = newTemp(Ity_V128);
24332    IRTemp vC = newTemp(Ity_V128);
24333    assign( vA, getVReg(vA_addr));
24334    assign( vB, getVReg(vB_addr));
24335    assign( vC, getVReg(vC_addr));
24336 
24337    if (opc1 != 0x4) {
24338       vex_printf("dis_av_permute(ppc)(instr)\n");
24339       return False;
24340    }
24341 
24342    switch (opc2) {
24343    case 0x2A: // vsel (Conditional Select, AV p238)
24344       DIP("vsel v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
24345       /* vD = (vA & ~vC) | (vB & vC) */
24346       putVReg( vD_addr, binop(Iop_OrV128,
24347          binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
24348          binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
24349       return True;
24350 
24351    case 0x2B: { // vperm (Permute, AV p218)
24352       /* limited to two args for IR, so have to play games... */
24353       IRTemp a_perm  = newTemp(Ity_V128);
24354       IRTemp b_perm  = newTemp(Ity_V128);
24355       IRTemp mask    = newTemp(Ity_V128);
24356       IRTemp vC_andF = newTemp(Ity_V128);
24357       DIP("vperm v%d,v%d,v%d,v%d\n",
24358           vD_addr, vA_addr, vB_addr, vC_addr);
24359       /* Limit the Perm8x16 steering values to 0 .. 15 as that is what
24360          IR specifies, and also to hide irrelevant bits from
24361          memcheck */
24362       assign( vC_andF,
24363               binop(Iop_AndV128, mkexpr(vC),
24364                                  unop(Iop_Dup8x16, mkU8(0xF))) );
24365       assign( a_perm,
24366               binop(Iop_Perm8x16, mkexpr(vA), mkexpr(vC_andF)) );
24367       assign( b_perm,
24368               binop(Iop_Perm8x16, mkexpr(vB), mkexpr(vC_andF)) );
24369       // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0
24370       assign( mask, binop(Iop_SarN8x16,
24371                           binop(Iop_ShlN8x16, mkexpr(vC), mkU8(3)),
24372                           mkU8(7)) );
24373       // dst = (a & ~mask) | (b & mask)
24374       putVReg( vD_addr, binop(Iop_OrV128,
24375                               binop(Iop_AndV128, mkexpr(a_perm),
24376                                     unop(Iop_NotV128, mkexpr(mask))),
24377                               binop(Iop_AndV128, mkexpr(b_perm),
24378                                     mkexpr(mask))) );
24379       return True;
24380    }
24381    case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241)
24382       if (b10 != 0) {
24383          vex_printf("dis_av_permute(ppc)(vsldoi)\n");
24384          return False;
24385       }
24386       DIP("vsldoi v%d,v%d,v%d,%d\n",
24387           vD_addr, vA_addr, vB_addr, SHB_uimm4);
24388       if (SHB_uimm4 == 0)
24389          putVReg( vD_addr, mkexpr(vA) );
24390       else
24391          putVReg( vD_addr,
24392             binop(Iop_OrV128,
24393                   binop(Iop_ShlV128, mkexpr(vA), mkU8(SHB_uimm4*8)),
24394                   binop(Iop_ShrV128, mkexpr(vB), mkU8((16-SHB_uimm4)*8))) );
24395       return True;
24396    case 0x2D: {  // vpermxor (Vector Permute and Exclusive-OR)
24397       IRTemp a_perm  = newTemp(Ity_V128);
24398       IRTemp b_perm  = newTemp(Ity_V128);
24399       IRTemp vrc_a   = newTemp(Ity_V128);
24400       IRTemp vrc_b   = newTemp(Ity_V128);
24401 
24402       DIP("vpermxor v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
24403 
24404       /* IBM index  is 0:7, Change index value to index 7:0 */
24405       assign( vrc_b, binop( Iop_AndV128, mkexpr( vC ),
24406                             unop( Iop_Dup8x16, mkU8( 0xF ) ) ) );
24407       assign( vrc_a, binop( Iop_ShrV128,
24408                             binop( Iop_AndV128, mkexpr( vC ),
24409                                    unop( Iop_Dup8x16, mkU8( 0xF0 ) ) ),
24410                             mkU8 ( 4 ) ) );
24411       assign( a_perm, binop( Iop_Perm8x16, mkexpr( vA ), mkexpr( vrc_a ) ) );
24412       assign( b_perm, binop( Iop_Perm8x16, mkexpr( vB ), mkexpr( vrc_b ) ) );
24413       putVReg( vD_addr, binop( Iop_XorV128,
24414                                mkexpr( a_perm ), mkexpr( b_perm) ) );
24415       return True;
24416    }
24417 
24418    case 0x3B: {  // vpermr (Vector Permute Right-indexed)
24419       /* limited to two args for IR, so have to play games... */
24420       IRTemp a_perm  = newTemp( Ity_V128 );
24421       IRTemp b_perm  = newTemp( Ity_V128 );
24422       IRTemp mask    = newTemp( Ity_V128 );
24423       IRTemp vC_andF = newTemp( Ity_V128 );
24424       IRTemp vC_adj = newTemp( Ity_V128 );
24425 
24426       DIP( "vpermr v%d,v%d,v%d,v%d\n",
24427            vD_addr, vA_addr, vB_addr, vC_addr);
24428       /* Limit the Perm8x16 steering values to 0 .. 15 as that is what
24429          IR specifies, and also to hide irrelevant bits from
24430          memcheck.
24431       */
24432 
24433       assign( vC_adj,
24434                     binop( Iop_Sub16x8,
24435 			   unop( Iop_Dup8x16, mkU8( 0x1F ) ),
24436 			   mkexpr( vC ) ) );
24437       assign( vC_andF,
24438               binop( Iop_AndV128, mkexpr( vC_adj),
24439                      unop( Iop_Dup8x16, mkU8( 0xF ) ) ) );
24440       assign( a_perm,
24441               binop( Iop_Perm8x16, mkexpr( vA ), mkexpr( vC_andF ) ) );
24442       assign( b_perm,
24443               binop( Iop_Perm8x16, mkexpr( vB ), mkexpr( vC_andF ) ) );
24444       // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0
24445       assign( mask, binop(Iop_SarN8x16,
24446                           binop( Iop_ShlN8x16, mkexpr( vC_adj ),
24447                                  mkU8( 3 ) ), mkU8( 7 ) ) );
24448       // dst = (a & ~mask) | (b & mask)
24449       putVReg( vD_addr, binop( Iop_OrV128,
24450                               binop( Iop_AndV128, mkexpr( a_perm ),
24451                                     unop( Iop_NotV128, mkexpr( mask ) ) ),
24452                               binop( Iop_AndV128, mkexpr( b_perm ),
24453                                     mkexpr( mask ) ) ) );
24454       return True;
24455    }
24456 
24457    default:
24458      break; // Fall through...
24459    }
24460 
24461    opc2 = IFIELD( theInstr, 0, 11 );
24462    switch (opc2) {
24463 
24464    /* Merge */
24465    case 0x00C: // vmrghb (Merge High B, AV p195)
24466       DIP("vmrghb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24467       putVReg( vD_addr,
24468                binop(Iop_InterleaveHI8x16, mkexpr(vA), mkexpr(vB)) );
24469       break;
24470 
24471    case 0x04C: // vmrghh (Merge High HW, AV p196)
24472       DIP("vmrghh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24473       putVReg( vD_addr,
24474                binop(Iop_InterleaveHI16x8, mkexpr(vA), mkexpr(vB)) );
24475       break;
24476 
24477    case 0x08C: // vmrghw (Merge High W, AV p197)
24478       DIP("vmrghw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24479       putVReg( vD_addr,
24480                binop(Iop_InterleaveHI32x4, mkexpr(vA), mkexpr(vB)) );
24481       break;
24482 
24483    case 0x10C: // vmrglb (Merge Low B, AV p198)
24484       DIP("vmrglb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24485       putVReg( vD_addr,
24486                binop(Iop_InterleaveLO8x16, mkexpr(vA), mkexpr(vB)) );
24487       break;
24488 
24489    case 0x14C: // vmrglh (Merge Low HW, AV p199)
24490       DIP("vmrglh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24491       putVReg( vD_addr,
24492                binop(Iop_InterleaveLO16x8, mkexpr(vA), mkexpr(vB)) );
24493       break;
24494 
24495    case 0x18C: // vmrglw (Merge Low W, AV p200)
24496       DIP("vmrglw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24497       putVReg( vD_addr,
24498                binop(Iop_InterleaveLO32x4, mkexpr(vA), mkexpr(vB)) );
24499       break;
24500 
24501    /* Extract instructions */
24502    case 0x20D: // vextractub  (Vector Extract Unsigned Byte)
24503    {
24504       UChar uim = IFIELD( theInstr, 16, 4 );
24505 
24506       DIP("vextractub v%d,v%d,%d\n", vD_addr, vB_addr, uim);
24507 
24508       putVReg( vD_addr, binop( Iop_ShlV128,
24509                                binop( Iop_AndV128,
24510                                       binop( Iop_ShrV128,
24511                                              mkexpr( vB ),
24512                                              unop( Iop_32to8,
24513                                                    binop( Iop_Mul32,
24514                                                           mkU32( 8 ),
24515                                                           mkU32( 31 - uim ) ) ) ),
24516                                       binop( Iop_64HLtoV128,
24517                                              mkU64( 0x0ULL ),
24518                                              mkU64( 0xFFULL ) ) ),
24519                                mkU8( 64 ) ) );
24520    }
24521    break;
24522 
24523    case 0x24D: // vextractuh  (Vector Extract Unsigned Halfword)
24524    {
24525       UChar uim = IFIELD( theInstr, 16, 4 );
24526 
24527       DIP("vextractuh v%d,v%d,%d\n", vD_addr, vB_addr, uim);
24528 
24529       putVReg( vD_addr, binop( Iop_ShlV128,
24530                                binop( Iop_AndV128,
24531                                       binop( Iop_ShrV128,
24532                                              mkexpr( vB ),
24533                                              unop( Iop_32to8,
24534                                                    binop( Iop_Mul32,
24535                                                           mkU32( 8 ),
24536                                                           mkU32( 30 - uim ) ) ) ),
24537                                       binop( Iop_64HLtoV128,
24538                                              mkU64( 0x0ULL ),
24539                                              mkU64( 0xFFFFULL ) ) ),
24540                                mkU8( 64 ) ) );
24541    }
24542    break;
24543 
24544    case 0x28D: // vextractuw  (Vector Extract Unsigned Word)
24545    {
24546       UChar uim = IFIELD( theInstr, 16, 4 );
24547 
24548       DIP("vextractuw v%d,v%d,%d\n", vD_addr, vB_addr, uim);
24549 
24550       putVReg( vD_addr,
24551                binop( Iop_ShlV128,
24552                       binop( Iop_AndV128,
24553                              binop( Iop_ShrV128,
24554                                     mkexpr( vB ),
24555                                     unop( Iop_32to8,
24556                                           binop( Iop_Mul32,
24557                                                  mkU32( 8 ),
24558                                                  mkU32( 28 - uim ) ) ) ),
24559                              binop( Iop_64HLtoV128,
24560                                     mkU64( 0x0ULL ),
24561                                     mkU64( 0xFFFFFFFFULL ) ) ),
24562                       mkU8( 64 ) ) );
24563    }
24564    break;
24565 
24566    case 0x2CD: // vextractd  (Vector Extract Double Word)
24567    {
24568       UChar uim = IFIELD( theInstr, 16, 4 );
24569 
24570       DIP("vextractd v%d,v%d,%d\n", vD_addr, vB_addr, uim);
24571 
24572       putVReg( vD_addr,
24573                binop( Iop_ShlV128,
24574                       binop( Iop_AndV128,
24575                              binop( Iop_ShrV128,
24576                                     mkexpr( vB ),
24577                                     unop( Iop_32to8,
24578                                           binop( Iop_Mul32,
24579                                                  mkU32( 8 ),
24580                                                  mkU32( 24 - uim ) ) ) ),
24581                              binop( Iop_64HLtoV128,
24582                                     mkU64( 0x0ULL ),
24583                                     mkU64( 0xFFFFFFFFFFFFFFFFULL ) ) ),
24584                       mkU8( 64 ) ) );
24585    }
24586    break;
24587 
24588    /* Insert instructions */
24589    case 0x30D:  // vinsertb  (Vector insert Unsigned Byte)
24590    {
24591       UChar uim = IFIELD( theInstr, 16, 4 );
24592       IRTemp shift = newTemp( Ity_I8 );
24593       IRTemp vD = newTemp( Ity_V128 );
24594 
24595       DIP("vinsertb v%d,v%d,%d\n", vD_addr, vB_addr, uim);
24596 
24597       assign( vD, getVReg( vD_addr ) );
24598 
24599       assign( shift, unop( Iop_32to8,
24600                            binop( Iop_Mul32,
24601                                   mkU32( 8 ),
24602                                   mkU32( 15 - ( uim + 0 ) ) ) ) );
24603 
24604       putVReg( vD_addr,
24605                binop( Iop_OrV128,
24606                       binop( Iop_ShlV128,
24607                              binop( Iop_AndV128,
24608                                     binop( Iop_ShrV128,
24609                                            mkexpr( vB ),
24610                                            mkU8( ( 15 - 7 )*8 ) ),
24611                                     binop( Iop_64HLtoV128,
24612                                            mkU64( 0x0ULL ),
24613                                            mkU64( 0xFFULL ) ) ),
24614                              mkexpr( shift ) ),
24615                       binop( Iop_AndV128,
24616                              unop( Iop_NotV128,
24617                                    binop( Iop_ShlV128,
24618                                           binop( Iop_64HLtoV128,
24619                                                  mkU64( 0x0ULL ),
24620                                                  mkU64( 0xFFULL ) ),
24621                                           mkexpr( shift ) ) ),
24622                              mkexpr( vD ) ) ) );
24623    }
24624    break;
24625 
24626    case 0x34D: // vinserth  (Vector insert Halfword)
24627    {
24628       UChar uim = IFIELD( theInstr, 16, 4 );
24629       IRTemp shift = newTemp( Ity_I8 );
24630       IRTemp vD = newTemp( Ity_V128 );
24631 
24632       DIP("vinserth v%d,v%d,%d\n", vD_addr, vB_addr, uim);
24633 
24634       assign( vD, getVReg( vD_addr ) );
24635 
24636       assign( shift, unop( Iop_32to8,
24637                            binop( Iop_Mul32,
24638                                   mkU32( 8 ),
24639                                   mkU32( 15 - ( uim + 1 ) ) ) ) );
24640 
24641       putVReg( vD_addr,
24642                binop( Iop_OrV128,
24643                       binop( Iop_ShlV128,
24644                              binop( Iop_AndV128,
24645                                     binop( Iop_ShrV128,
24646                                            mkexpr( vB ),
24647                                            mkU8( (7 - 3)*16 ) ),
24648                                     binop( Iop_64HLtoV128,
24649                                            mkU64( 0x0ULL ),
24650                                            mkU64( 0xFFFFULL ) ) ),
24651                              mkexpr( shift ) ),
24652                       binop( Iop_AndV128,
24653                              unop( Iop_NotV128,
24654                                    binop( Iop_ShlV128,
24655                                           binop( Iop_64HLtoV128,
24656                                                  mkU64( 0x0ULL ),
24657                                                  mkU64( 0xFFFFULL ) ),
24658                                           mkexpr( shift ) ) ),
24659                              mkexpr( vD ) ) ) );
24660    }
24661    break;
24662 
24663    case 0x38D: // vinsertw  (Vector insert Word)
24664    {
24665       UChar uim = IFIELD( theInstr, 16, 4 );
24666       IRTemp shift = newTemp( Ity_I8 );
24667       IRTemp vD = newTemp( Ity_V128 );
24668 
24669       DIP("vinsertw v%d,v%d,%d\n", vD_addr, vB_addr, uim);
24670 
24671       assign( vD, getVReg( vD_addr ) );
24672 
24673       assign( shift, unop( Iop_32to8,
24674                            binop( Iop_Mul32,
24675                                   mkU32( 8 ),
24676                                   mkU32( 15 - ( uim + 3 ) ) ) ) );
24677 
24678       putVReg( vD_addr,
24679                binop( Iop_OrV128,
24680                       binop( Iop_ShlV128,
24681                              binop( Iop_AndV128,
24682                                     binop( Iop_ShrV128,
24683                                            mkexpr( vB ),
24684                                            mkU8( (3 - 1) * 32 ) ),
24685                                     binop( Iop_64HLtoV128,
24686                                            mkU64( 0x0ULL ),
24687                                            mkU64( 0xFFFFFFFFULL ) ) ),
24688                              mkexpr( shift ) ),
24689                       binop( Iop_AndV128,
24690                              unop( Iop_NotV128,
24691                                    binop( Iop_ShlV128,
24692                                           binop( Iop_64HLtoV128,
24693                                                  mkU64( 0x0ULL ),
24694                                                  mkU64( 0xFFFFFFFFULL ) ),
24695                                           mkexpr( shift ) ) ),
24696                              mkexpr( vD ) ) ) );
24697    }
24698    break;
24699 
24700    case 0x3CD: // vinsertd  (Vector insert Doubleword)
24701    {
24702       UChar uim = IFIELD( theInstr, 16, 4 );
24703       IRTemp shift = newTemp( Ity_I8 );
24704       IRTemp vD = newTemp( Ity_V128 );
24705 
24706       DIP("vinsertd v%d,v%d,%d\n", vD_addr, vB_addr, uim);
24707 
24708       assign( vD, getVReg( vD_addr ) );
24709 
24710       assign( shift, unop( Iop_32to8,
24711                            binop( Iop_Mul32,
24712                                   mkU32( 8 ),
24713                                   mkU32( 15 - ( uim + 7 ) ) ) ) );
24714 
24715       putVReg( vD_addr,
24716                binop( Iop_OrV128,
24717                       binop( Iop_ShlV128,
24718                              binop( Iop_AndV128,
24719                                     binop( Iop_ShrV128,
24720                                            mkexpr( vB ),
24721                                            mkU8( ( 1 - 0 ) * 64 ) ),
24722                                     binop( Iop_64HLtoV128,
24723                                            mkU64( 0x0ULL ),
24724                                            mkU64( 0xFFFFFFFFFFFFFFFFULL ) ) ),
24725                              mkexpr( shift ) ),
24726                       binop( Iop_AndV128,
24727                              unop( Iop_NotV128,
24728                                    binop( Iop_ShlV128,
24729                                           binop( Iop_64HLtoV128,
24730                                                  mkU64( 0x0ULL ),
24731                                                  mkU64( 0xFFFFFFFFFFFFFFFFULL ) ),
24732                                           mkexpr( shift ) ) ),
24733                              mkexpr( vD ) ) ) );
24734    }
24735    break;
24736 
24737    /* Splat */
24738    case 0x20C: { // vspltb (Splat Byte, AV p245)
24739       /* vD = Dup8x16( vB[UIMM_5] ) */
24740       UChar sh_uimm = (15 - (UIMM_5 & 15)) * 8;
24741       DIP("vspltb v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
24742       putVReg( vD_addr, unop(Iop_Dup8x16,
24743            unop(Iop_32to8, unop(Iop_V128to32,
24744                 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
24745       break;
24746    }
24747    case 0x24C: { // vsplth (Splat Half Word, AV p246)
24748       UChar sh_uimm = (7 - (UIMM_5 & 7)) * 16;
24749       DIP("vsplth v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
24750       putVReg( vD_addr, unop(Iop_Dup16x8,
24751            unop(Iop_32to16, unop(Iop_V128to32,
24752                 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
24753       break;
24754    }
24755    case 0x28C: { // vspltw (Splat Word, AV p250)
24756       /* vD = Dup32x4( vB[UIMM_5] ) */
24757       UChar sh_uimm = (3 - (UIMM_5 & 3)) * 32;
24758       DIP("vspltw v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
24759       putVReg( vD_addr, unop(Iop_Dup32x4,
24760          unop(Iop_V128to32,
24761               binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm)))) );
24762       break;
24763    }
24764    case 0x30C: // vspltisb (Splat Immediate Signed B, AV p247)
24765       DIP("vspltisb v%d,%d\n", vD_addr, (Char)SIMM_8);
24766       putVReg( vD_addr, unop(Iop_Dup8x16, mkU8(SIMM_8)) );
24767       break;
24768 
24769    case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248)
24770       DIP("vspltish v%d,%d\n", vD_addr, (Char)SIMM_8);
24771       putVReg( vD_addr,
24772                unop(Iop_Dup16x8, mkU16(extend_s_8to32(SIMM_8))) );
24773       break;
24774 
24775    case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249)
24776       DIP("vspltisw v%d,%d\n", vD_addr, (Char)SIMM_8);
24777       putVReg( vD_addr,
24778                unop(Iop_Dup32x4, mkU32(extend_s_8to32(SIMM_8))) );
24779       break;
24780 
24781    case 0x68C: // vmrgow (Merge Odd Word)
24782      DIP("vmrgow v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24783       /*   VD[0] <- VA[1]
24784            VD[1] <- VB[1]
24785            VD[2] <- VA[3]
24786            VD[3] <- VB[3]
24787       */
24788       putVReg( vD_addr,
24789                binop(Iop_CatOddLanes32x4, mkexpr(vA), mkexpr(vB) ) );
24790       break;
24791 
24792    case 0x78C: // vmrgew (Merge Even Word)
24793       DIP("vmrgew v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
24794       /*   VD[0] <- VA[0]
24795            VD[1] <- VB[0]
24796            VD[2] <- VA[2]
24797            VD[3] <- VB[2]
24798       */
24799       putVReg( vD_addr,
24800                binop(Iop_CatEvenLanes32x4, mkexpr(vA), mkexpr(vB) ) );
24801       break;
24802 
24803    default:
24804       vex_printf("dis_av_permute(ppc)(opc2)\n");
24805       return False;
24806    }
24807    return True;
24808 }
24809 
24810 /*
24811   Vector Integer Absolute Difference
24812 */
dis_abs_diff(UInt theInstr)24813 static Bool dis_abs_diff ( UInt theInstr )
24814 {
24815    /* VX-Form */
24816    UChar opc1     = ifieldOPC( theInstr );
24817    UChar vT_addr  = ifieldRegDS( theInstr );
24818    UChar vA_addr  = ifieldRegA( theInstr );
24819    UChar vB_addr  = ifieldRegB( theInstr );
24820    UInt  opc2     = IFIELD( theInstr, 0, 11 );
24821 
24822    IRTemp vA    = newTemp( Ity_V128 );
24823    IRTemp vB    = newTemp( Ity_V128 );
24824    IRTemp vT    = newTemp( Ity_V128 );
24825 
24826    IRTemp vAminusB = newTemp( Ity_V128 );
24827    IRTemp vBminusA = newTemp( Ity_V128 );
24828    IRTemp vMask    = newTemp( Ity_V128 );
24829 
24830    assign( vA, getVReg( vA_addr ) );
24831    assign( vB, getVReg( vB_addr ) );
24832 
24833    if ( opc1 != 0x4 ) {
24834       vex_printf("dis_abs_diff(ppc)(instr)\n");
24835       return False;
24836    }
24837 
24838    switch ( opc2 ) {
24839    case 0x403: // vabsdub  Vector absolute difference Unsigned Byte
24840    {
24841       DIP("vabsdub v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr);
24842 
24843       /* Determine which of the corresponding bytes is larger,
24844        * create mask with 1's in byte positions where vA[i] > vB[i]
24845        */
24846       assign( vMask, binop( Iop_CmpGT8Ux16, mkexpr( vA ), mkexpr( vB ) ) );
24847 
24848       assign( vAminusB,
24849               binop( Iop_AndV128,
24850                      binop( Iop_Sub8x16, mkexpr( vA ), mkexpr( vB ) ),
24851                      mkexpr( vMask ) ) );
24852 
24853       assign( vBminusA,
24854               binop( Iop_AndV128,
24855                      binop( Iop_Sub8x16, mkexpr( vB ), mkexpr( vA ) ),
24856                      unop ( Iop_NotV128, mkexpr( vMask ) ) ) );
24857 
24858       assign( vT, binop( Iop_OrV128,
24859                          mkexpr( vAminusB ),
24860                          mkexpr( vBminusA ) ) );
24861    }
24862    break;
24863 
24864    case 0x443: // vabsduh  Vector absolute difference Unsigned Halfword
24865    {
24866       DIP("vabsduh v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr);
24867 
24868       /* Determine which of the corresponding halfwords is larger,
24869        * create mask with 1's in halfword positions where vA[i] > vB[i]
24870        */
24871       assign( vMask, binop( Iop_CmpGT16Ux8, mkexpr( vA ), mkexpr( vB ) ) );
24872 
24873       assign( vAminusB,
24874               binop( Iop_AndV128,
24875                      binop( Iop_Sub16x8, mkexpr( vA ), mkexpr( vB ) ),
24876                      mkexpr( vMask ) ) );
24877 
24878       assign( vBminusA,
24879               binop( Iop_AndV128,
24880                      binop( Iop_Sub16x8, mkexpr( vB ), mkexpr( vA ) ),
24881                      unop ( Iop_NotV128, mkexpr( vMask ) ) ) );
24882 
24883       assign( vT, binop( Iop_OrV128,
24884                          mkexpr( vAminusB ),
24885                          mkexpr( vBminusA ) ) );
24886    }
24887    break;
24888 
24889    case 0x483: // vabsduw  Vector absolute difference Unsigned Word
24890    {
24891          DIP("vabsduw v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr);
24892 
24893          /* Determine which of the corresponding words is larger,
24894           * create mask with 1's in word positions where vA[i] > vB[i]
24895           */
24896          assign( vMask, binop( Iop_CmpGT32Ux4, mkexpr( vA ), mkexpr( vB ) ) );
24897 
24898          assign( vAminusB,
24899                  binop( Iop_AndV128,
24900                         binop( Iop_Sub32x4, mkexpr( vA ), mkexpr( vB ) ),
24901                         mkexpr( vMask ) ) );
24902 
24903          assign( vBminusA,
24904                  binop( Iop_AndV128,
24905                         binop( Iop_Sub32x4, mkexpr( vB ), mkexpr( vA ) ),
24906                         unop ( Iop_NotV128, mkexpr( vMask ) ) ) );
24907 
24908          assign( vT, binop( Iop_OrV128,
24909                             mkexpr( vAminusB ),
24910                             mkexpr( vBminusA ) ) );
24911    }
24912    break;
24913 
24914    default:
24915       return False;
24916    }
24917 
24918    putVReg( vT_addr, mkexpr( vT ) );
24919 
24920   return True;
24921 }
24922 
24923 /*
24924   AltiVec 128 bit integer multiply by 10 Instructions
24925 */
dis_av_mult10(UInt theInstr)24926 static Bool dis_av_mult10 ( UInt theInstr )
24927 {
24928    /* VX-Form */
24929    UChar opc1     = ifieldOPC(theInstr);
24930    UChar vT_addr  = ifieldRegDS(theInstr);
24931    UChar vA_addr  = ifieldRegA(theInstr);
24932    UChar vB_addr  = ifieldRegB(theInstr);
24933    UInt  opc2     = IFIELD( theInstr, 0, 11 );
24934 
24935    IRTemp vA    = newTemp(Ity_V128);
24936    assign( vA, getVReg(vA_addr));
24937 
24938    if (opc1 != 0x4) {
24939       vex_printf("dis_av_mult10(ppc)(instr)\n");
24940       return False;
24941    }
24942    switch (opc2) {
24943    case 0x001: { // vmul10cuq (Vector Multiply-by-10 and write carry
24944       DIP("vmul10cuq v%d,v%d\n", vT_addr, vA_addr);
24945       putVReg( vT_addr,
24946                unop( Iop_MulI128by10Carry, mkexpr( vA ) ) );
24947       break;
24948   }
24949    case 0x041: { // vmul10uq (Vector Multiply-by-10 Extended and write carry
24950                  //           Unsigned Quadword VX form)
24951       IRTemp vB    = newTemp(Ity_V128);
24952       assign( vB, getVReg(vB_addr));
24953       DIP("vmul10ecuq v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr);
24954       putVReg( vT_addr,
24955                binop( Iop_MulI128by10ECarry, mkexpr( vA ), mkexpr( vB ) ) );
24956       break;
24957    }
24958    case 0x201: { // vmul10uq (Vector Multiply-by-10 Unsigned Quadword VX form)
24959       DIP("vmul10uq v%d,v%d\n", vT_addr, vA_addr);
24960       putVReg( vT_addr,
24961                unop( Iop_MulI128by10, mkexpr( vA ) ) );
24962       break;
24963    }
24964   case 0x241: { // vmul10uq (Vector Multiply-by-10 Extended
24965                 //           Unsigned Quadword VX form)
24966       IRTemp vB    = newTemp(Ity_V128);
24967       assign( vB, getVReg(vB_addr));
24968       DIP("vmul10euq v%d,v%d,v%d\n", vT_addr, vA_addr, vB_addr);
24969       putVReg( vT_addr,
24970                binop( Iop_MulI128by10E, mkexpr( vA ), mkexpr( vB ) ) );
24971       break;
24972    }
24973    default:
24974       vex_printf("dis_av_mult10(ppc)(opc2)\n");
24975       return False;
24976    }
24977    return True;
24978 }
24979 
24980 /*
24981   AltiVec Pack/Unpack Instructions
24982 */
dis_av_pack(UInt theInstr)24983 static Bool dis_av_pack ( UInt theInstr )
24984 {
24985    /* VX-Form */
24986    UChar opc1     = ifieldOPC(theInstr);
24987    UChar vD_addr  = ifieldRegDS(theInstr);
24988    UChar vA_addr  = ifieldRegA(theInstr);
24989    UChar vB_addr  = ifieldRegB(theInstr);
24990    UInt  opc2     = IFIELD( theInstr, 0, 11 );
24991 
24992    IRTemp signs = IRTemp_INVALID;
24993    IRTemp zeros = IRTemp_INVALID;
24994    IRTemp vA    = newTemp(Ity_V128);
24995    IRTemp vB    = newTemp(Ity_V128);
24996    assign( vA, getVReg(vA_addr));
24997    assign( vB, getVReg(vB_addr));
24998 
24999    if (opc1 != 0x4) {
25000       vex_printf("dis_av_pack(ppc)(instr)\n");
25001       return False;
25002    }
25003    switch (opc2) {
25004    /* Packing */
25005    case 0x00E: // vpkuhum (Pack Unsigned HW Unsigned Modulo, AV p224)
25006       DIP("vpkuhum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
25007       putVReg( vD_addr,
25008                binop(Iop_NarrowBin16to8x16, mkexpr(vA), mkexpr(vB)) );
25009       return True;
25010 
25011    case 0x04E: // vpkuwum (Pack Unsigned W Unsigned Modulo, AV p226)
25012       DIP("vpkuwum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
25013       putVReg( vD_addr,
25014                binop(Iop_NarrowBin32to16x8, mkexpr(vA), mkexpr(vB)) );
25015       return True;
25016 
25017    case 0x08E: // vpkuhus (Pack Unsigned HW Unsigned Saturate, AV p225)
25018       DIP("vpkuhus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
25019       putVReg( vD_addr,
25020                binop(Iop_QNarrowBin16Uto8Ux16, mkexpr(vA), mkexpr(vB)) );
25021       // TODO: set VSCR[SAT]
25022       return True;
25023 
25024    case 0x0CE: // vpkuwus (Pack Unsigned W Unsigned Saturate, AV p227)
25025       DIP("vpkuwus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
25026       putVReg( vD_addr,
25027                binop(Iop_QNarrowBin32Uto16Ux8, mkexpr(vA), mkexpr(vB)) );
25028       // TODO: set VSCR[SAT]
25029       return True;
25030 
25031    case 0x10E: { // vpkshus (Pack Signed HW Unsigned Saturate, AV p221)
25032       // This insn does a signed->unsigned saturating conversion.
25033       // Conversion done here, then uses unsigned->unsigned vpk insn:
25034       //  => UnsignedSaturatingNarrow( x & ~ (x >>s 15) )
25035       IRTemp vA_tmp = newTemp(Ity_V128);
25036       IRTemp vB_tmp = newTemp(Ity_V128);
25037       DIP("vpkshus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
25038       assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
25039                             unop(Iop_NotV128,
25040                                  binop(Iop_SarN16x8,
25041                                        mkexpr(vA), mkU8(15)))) );
25042       assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
25043                             unop(Iop_NotV128,
25044                                  binop(Iop_SarN16x8,
25045                                        mkexpr(vB), mkU8(15)))) );
25046       putVReg( vD_addr, binop(Iop_QNarrowBin16Uto8Ux16,
25047                               mkexpr(vA_tmp), mkexpr(vB_tmp)) );
25048       // TODO: set VSCR[SAT]
25049       return True;
25050    }
25051    case 0x14E: { // vpkswus (Pack Signed W Unsigned Saturate, AV p223)
25052       // This insn does a signed->unsigned saturating conversion.
25053       // Conversion done here, then uses unsigned->unsigned vpk insn:
25054       //  => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
25055       IRTemp vA_tmp = newTemp(Ity_V128);
25056       IRTemp vB_tmp = newTemp(Ity_V128);
25057       DIP("vpkswus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
25058       assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
25059                             unop(Iop_NotV128,
25060                                  binop(Iop_SarN32x4,
25061                                        mkexpr(vA), mkU8(31)))) );
25062       assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
25063                             unop(Iop_NotV128,
25064                                  binop(Iop_SarN32x4,
25065                                        mkexpr(vB), mkU8(31)))) );
25066       putVReg( vD_addr, binop(Iop_QNarrowBin32Uto16Ux8,
25067                               mkexpr(vA_tmp), mkexpr(vB_tmp)) );
25068       // TODO: set VSCR[SAT]
25069       return True;
25070    }
25071    case 0x18E: // vpkshss (Pack Signed HW Signed Saturate, AV p220)
25072       DIP("vpkshss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
25073       putVReg( vD_addr,
25074                binop(Iop_QNarrowBin16Sto8Sx16, mkexpr(vA), mkexpr(vB)) );
25075       // TODO: set VSCR[SAT]
25076       return True;
25077 
25078    case 0x1CE: // vpkswss (Pack Signed W Signed Saturate, AV p222)
25079       DIP("vpkswss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
25080       putVReg( vD_addr,
25081                binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(vA), mkexpr(vB)) );
25082       // TODO: set VSCR[SAT]
25083       return True;
25084 
25085    case 0x30E: { // vpkpx (Pack Pixel, AV p219)
25086       /* CAB: Worth a new primop? */
25087       /* Using shifts to compact pixel elements, then packing them */
25088       IRTemp a1 = newTemp(Ity_V128);
25089       IRTemp a2 = newTemp(Ity_V128);
25090       IRTemp a3 = newTemp(Ity_V128);
25091       IRTemp a_tmp = newTemp(Ity_V128);
25092       IRTemp b1 = newTemp(Ity_V128);
25093       IRTemp b2 = newTemp(Ity_V128);
25094       IRTemp b3 = newTemp(Ity_V128);
25095       IRTemp b_tmp = newTemp(Ity_V128);
25096       DIP("vpkpx v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
25097       assign( a1, binop(Iop_ShlN16x8,
25098                         binop(Iop_ShrN32x4, mkexpr(vA), mkU8(19)),
25099                         mkU8(10)) );
25100       assign( a2, binop(Iop_ShlN16x8,
25101                         binop(Iop_ShrN16x8, mkexpr(vA), mkU8(11)),
25102                         mkU8(5)) );
25103       assign( a3,  binop(Iop_ShrN16x8,
25104                          binop(Iop_ShlN16x8, mkexpr(vA), mkU8(8)),
25105                          mkU8(11)) );
25106       assign( a_tmp, binop(Iop_OrV128, mkexpr(a1),
25107                            binop(Iop_OrV128, mkexpr(a2), mkexpr(a3))) );
25108 
25109       assign( b1, binop(Iop_ShlN16x8,
25110                         binop(Iop_ShrN32x4, mkexpr(vB), mkU8(19)),
25111                         mkU8(10)) );
25112       assign( b2, binop(Iop_ShlN16x8,
25113                         binop(Iop_ShrN16x8, mkexpr(vB), mkU8(11)),
25114                         mkU8(5)) );
25115       assign( b3,  binop(Iop_ShrN16x8,
25116                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(8)),
25117                          mkU8(11)) );
25118       assign( b_tmp, binop(Iop_OrV128, mkexpr(b1),
25119                            binop(Iop_OrV128, mkexpr(b2), mkexpr(b3))) );
25120 
25121       putVReg( vD_addr, binop(Iop_NarrowBin32to16x8,
25122                               mkexpr(a_tmp), mkexpr(b_tmp)) );
25123       return True;
25124    }
25125 
25126    case 0x44E: // vpkudum (Pack Unsigned Double Word Unsigned Modulo)
25127       DIP("vpkudum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
25128       putVReg( vD_addr,
25129                binop(Iop_NarrowBin64to32x4, mkexpr(vA), mkexpr(vB)) );
25130       return True;
25131 
25132    case 0x4CE: // vpkudus (Pack Unsigned Double Word Unsigned Saturate)
25133       DIP("vpkudus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
25134       putVReg( vD_addr,
25135                binop(Iop_QNarrowBin64Uto32Ux4, mkexpr(vA), mkexpr(vB)) );
25136       // TODO: set VSCR[SAT]
25137       return True;
25138 
25139    case 0x54E: { // vpksdus (Pack Signed Double Word Unsigned Saturate)
25140       // This insn does a doubled signed->double unsigned saturating conversion
25141       // Conversion done here, then uses unsigned->unsigned vpk insn:
25142       //  => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
25143       // This is similar to the technique used for vpkswus, except done
25144       // with double word integers versus word integers.
25145       IRTemp vA_tmp = newTemp(Ity_V128);
25146       IRTemp vB_tmp = newTemp(Ity_V128);
25147       DIP("vpksdus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
25148       assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
25149                             unop(Iop_NotV128,
25150                                  binop(Iop_SarN64x2,
25151                                        mkexpr(vA), mkU8(63)))) );
25152       assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
25153                             unop(Iop_NotV128,
25154                                  binop(Iop_SarN64x2,
25155                                        mkexpr(vB), mkU8(63)))) );
25156       putVReg( vD_addr, binop(Iop_QNarrowBin64Uto32Ux4,
25157                               mkexpr(vA_tmp), mkexpr(vB_tmp)) );
25158       // TODO: set VSCR[SAT]
25159       return True;
25160    }
25161 
25162    case 0x5CE: // vpksdss (Pack Signed double word Signed Saturate)
25163       DIP("vpksdss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
25164       putVReg( vD_addr,
25165                binop(Iop_QNarrowBin64Sto32Sx4, mkexpr(vA), mkexpr(vB)) );
25166       // TODO: set VSCR[SAT]
25167       return True;
25168    default:
25169       break; // Fall through...
25170    }
25171 
25172 
25173    if (vA_addr != 0) {
25174       vex_printf("dis_av_pack(ppc)(vA_addr)\n");
25175       return False;
25176    }
25177 
25178    signs = newTemp(Ity_V128);
25179    zeros = newTemp(Ity_V128);
25180    assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
25181 
25182    switch (opc2) {
25183    /* Unpacking */
25184    case 0x20E: { // vupkhsb (Unpack High Signed B, AV p277)
25185       DIP("vupkhsb v%d,v%d\n", vD_addr, vB_addr);
25186       assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
25187       putVReg( vD_addr,
25188                binop(Iop_InterleaveHI8x16, mkexpr(signs), mkexpr(vB)) );
25189       break;
25190    }
25191    case 0x24E: { // vupkhsh (Unpack High Signed HW, AV p278)
25192       DIP("vupkhsh v%d,v%d\n", vD_addr, vB_addr);
25193       assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
25194       putVReg( vD_addr,
25195                binop(Iop_InterleaveHI16x8, mkexpr(signs), mkexpr(vB)) );
25196       break;
25197    }
25198    case 0x28E: { // vupklsb (Unpack Low Signed B, AV p280)
25199       DIP("vupklsb v%d,v%d\n", vD_addr, vB_addr);
25200       assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
25201       putVReg( vD_addr,
25202                binop(Iop_InterleaveLO8x16, mkexpr(signs), mkexpr(vB)) );
25203       break;
25204    }
25205    case 0x2CE: { // vupklsh (Unpack Low Signed HW, AV p281)
25206       DIP("vupklsh v%d,v%d\n", vD_addr, vB_addr);
25207       assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
25208       putVReg( vD_addr,
25209                binop(Iop_InterleaveLO16x8, mkexpr(signs), mkexpr(vB)) );
25210       break;
25211    }
25212    case 0x34E: { // vupkhpx (Unpack High Pixel16, AV p276)
25213       /* CAB: Worth a new primop? */
25214       /* Using shifts to isolate pixel elements, then expanding them */
25215       IRTemp z0  = newTemp(Ity_V128);
25216       IRTemp z1  = newTemp(Ity_V128);
25217       IRTemp z01 = newTemp(Ity_V128);
25218       IRTemp z2  = newTemp(Ity_V128);
25219       IRTemp z3  = newTemp(Ity_V128);
25220       IRTemp z23 = newTemp(Ity_V128);
25221       DIP("vupkhpx v%d,v%d\n", vD_addr, vB_addr);
25222       assign( z0,  binop(Iop_ShlN16x8,
25223                          binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
25224                          mkU8(8)) );
25225       assign( z1,  binop(Iop_ShrN16x8,
25226                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
25227                          mkU8(11)) );
25228       assign( z01, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
25229                          binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
25230       assign( z2,  binop(Iop_ShrN16x8,
25231                          binop(Iop_ShlN16x8,
25232                                binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
25233                                mkU8(11)),
25234                          mkU8(3)) );
25235       assign( z3,  binop(Iop_ShrN16x8,
25236                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
25237                          mkU8(11)) );
25238       assign( z23, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
25239                          binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
25240       putVReg( vD_addr,
25241                binop(Iop_OrV128,
25242                      binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
25243                      mkexpr(z23)) );
25244       break;
25245    }
25246    case 0x3CE: { // vupklpx (Unpack Low Pixel16, AV p279)
25247       /* identical to vupkhpx, except interleaving LO */
25248       IRTemp z0  = newTemp(Ity_V128);
25249       IRTemp z1  = newTemp(Ity_V128);
25250       IRTemp z01 = newTemp(Ity_V128);
25251       IRTemp z2  = newTemp(Ity_V128);
25252       IRTemp z3  = newTemp(Ity_V128);
25253       IRTemp z23 = newTemp(Ity_V128);
25254       DIP("vupklpx v%d,v%d\n", vD_addr, vB_addr);
25255       assign( z0,  binop(Iop_ShlN16x8,
25256                          binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
25257                          mkU8(8)) );
25258       assign( z1,  binop(Iop_ShrN16x8,
25259                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
25260                          mkU8(11)) );
25261       assign( z01, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
25262                          binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
25263       assign( z2,  binop(Iop_ShrN16x8,
25264                          binop(Iop_ShlN16x8,
25265                                binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
25266                                mkU8(11)),
25267                          mkU8(3)) );
25268       assign( z3,  binop(Iop_ShrN16x8,
25269                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
25270                          mkU8(11)) );
25271       assign( z23, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
25272                          binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
25273       putVReg( vD_addr,
25274                binop(Iop_OrV128,
25275                      binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
25276                      mkexpr(z23)) );
25277       break;
25278    }
25279    case 0x64E: { // vupkhsw (Unpack High Signed Word)
25280       DIP("vupkhsw v%d,v%d\n", vD_addr, vB_addr);
25281       assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) );
25282       putVReg( vD_addr,
25283                binop(Iop_InterleaveHI32x4, mkexpr(signs), mkexpr(vB)) );
25284       break;
25285    }
25286    case 0x6CE: { // vupklsw (Unpack Low Signed Word)
25287       DIP("vupklsw v%d,v%d\n", vD_addr, vB_addr);
25288       assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) );
25289       putVReg( vD_addr,
25290                binop(Iop_InterleaveLO32x4, mkexpr(signs), mkexpr(vB)) );
25291       break;
25292    }
25293    default:
25294       vex_printf("dis_av_pack(ppc)(opc2)\n");
25295       return False;
25296    }
25297    return True;
25298 }
25299 
25300 /*
25301   AltiVec Cipher Instructions
25302 */
dis_av_cipher(UInt theInstr)25303 static Bool dis_av_cipher ( UInt theInstr )
25304 {
25305    /* VX-Form */
25306    UChar opc1     = ifieldOPC(theInstr);
25307    UChar vD_addr  = ifieldRegDS(theInstr);
25308    UChar vA_addr  = ifieldRegA(theInstr);
25309    UChar vB_addr  = ifieldRegB(theInstr);
25310    UInt  opc2     = IFIELD( theInstr, 0, 11 );
25311 
25312    IRTemp vA    = newTemp(Ity_V128);
25313    IRTemp vB    = newTemp(Ity_V128);
25314    assign( vA, getVReg(vA_addr));
25315    assign( vB, getVReg(vB_addr));
25316 
25317    if (opc1 != 0x4) {
25318       vex_printf("dis_av_cipher(ppc)(instr)\n");
25319       return False;
25320    }
25321    switch (opc2) {
25322       case 0x508: // vcipher (Vector Inverser Cipher)
25323          DIP("vcipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
25324          putVReg( vD_addr,
25325                   binop(Iop_CipherV128, mkexpr(vA), mkexpr(vB)) );
25326          return True;
25327 
25328       case 0x509: // vcipherlast (Vector Inverser Cipher Last)
25329          DIP("vcipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
25330          putVReg( vD_addr,
25331                   binop(Iop_CipherLV128, mkexpr(vA), mkexpr(vB)) );
25332          return True;
25333 
25334       case 0x548: // vncipher (Vector Inverser Cipher)
25335          DIP("vncipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
25336          putVReg( vD_addr,
25337                   binop(Iop_NCipherV128, mkexpr(vA), mkexpr(vB)) );
25338          return True;
25339 
25340       case 0x549: // vncipherlast (Vector Inverser Cipher Last)
25341          DIP("vncipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
25342          putVReg( vD_addr,
25343                   binop(Iop_NCipherLV128, mkexpr(vA), mkexpr(vB)) );
25344          return True;
25345 
25346       case 0x5C8: /* vsbox (Vector SubBytes, this does the cipher
25347        * subBytes transform)
25348        */
25349          DIP("vsbox v%d,v%d\n", vD_addr, vA_addr);
25350          putVReg( vD_addr,
25351                   unop(Iop_CipherSV128, mkexpr(vA) ) );
25352          return True;
25353 
25354       default:
25355          vex_printf("dis_av_cipher(ppc)(opc2)\n");
25356          return False;
25357    }
25358    return True;
25359 }
25360 
25361 /*
25362   AltiVec Secure Hash Instructions
25363 */
dis_av_hash(UInt theInstr)25364 static Bool dis_av_hash ( UInt theInstr )
25365 {
25366    /* VX-Form */
25367    UChar opc1     = ifieldOPC(theInstr);
25368    UChar vRT_addr = ifieldRegDS(theInstr);
25369    UChar vRA_addr  = ifieldRegA(theInstr);
25370    UChar s_field  = IFIELD( theInstr, 11, 5 );  // st and six field
25371    UChar st       = IFIELD( theInstr, 15, 1 );  // st
25372    UChar six      = IFIELD( theInstr, 11, 4 );  // six field
25373    UInt  opc2     = IFIELD( theInstr, 0, 11 );
25374 
25375    IRTemp vA    = newTemp(Ity_V128);
25376    IRTemp dst    = newTemp(Ity_V128);
25377    assign( vA, getVReg(vRA_addr));
25378 
25379    if (opc1 != 0x4) {
25380       vex_printf("dis_av_hash(ppc)(instr)\n");
25381       return False;
25382    }
25383 
25384    switch (opc2) {
25385       case 0x682:  // vshasigmaw
25386          DIP("vshasigmaw v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six);
25387          assign( dst, binop( Iop_SHA256, mkexpr( vA ), mkU8( s_field) ) );
25388          putVReg( vRT_addr, mkexpr(dst));
25389          return True;
25390 
25391       case 0x6C2:  // vshasigmad,
25392          DIP("vshasigmad v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six);
25393          putVReg( vRT_addr, binop( Iop_SHA512, mkexpr( vA ), mkU8( s_field) ) );
25394          return True;
25395 
25396       default:
25397          vex_printf("dis_av_hash(ppc)(opc2)\n");
25398          return False;
25399    }
25400    return True;
25401 }
25402 
25403 /*
25404  * This function is used by the Vector add/subtract [extended] modulo/carry
25405  * instructions.
25406  *   - For the non-extended add instructions, the cin arg is set to zero.
25407  *   - For the extended add instructions, cin is the integer value of
25408  *     src3.bit[127].
25409  *   - For the non-extended subtract instructions, src1 is added to the one's
25410  *     complement of src2 + 1.  We re-use the cin argument to hold the '1'
25411  *     value for this operation.
25412  *   - For the extended subtract instructions, cin is the integer value of src3.bit[127].
25413  */
_get_quad_modulo_or_carry(IRExpr * vecA,IRExpr * vecB,IRExpr * cin,Bool modulo)25414 static IRTemp _get_quad_modulo_or_carry(IRExpr * vecA, IRExpr * vecB,
25415                                         IRExpr * cin, Bool modulo)
25416 {
25417    IRTemp _vecA_32   = IRTemp_INVALID;
25418    IRTemp _vecB_32   = IRTemp_INVALID;
25419    IRTemp res_32     = IRTemp_INVALID;
25420    IRTemp res_64     = IRTemp_INVALID;
25421    IRTemp result     = IRTemp_INVALID;
25422    IRTemp tmp_result = IRTemp_INVALID;
25423    IRTemp carry      = IRTemp_INVALID;
25424    Int i;
25425    IRExpr * _vecA_low64 =  unop( Iop_V128to64, vecA );
25426    IRExpr * _vecB_low64 =  unop( Iop_V128to64, vecB );
25427    IRExpr * _vecA_high64 = unop( Iop_V128HIto64, vecA );
25428    IRExpr * _vecB_high64 = unop( Iop_V128HIto64, vecB );
25429 
25430    carry = newTemp(Ity_I32);
25431    assign( carry, cin );
25432 
25433    for (i = 0; i < 4; i++) {
25434       _vecA_32 = newTemp(Ity_I32);
25435       _vecB_32 = newTemp(Ity_I32);
25436       res_32   = newTemp(Ity_I32);
25437       res_64   = newTemp(Ity_I64);
25438 
25439       switch (i) {
25440       case 0:
25441          assign(_vecA_32, unop( Iop_64to32, _vecA_low64 ) );
25442          assign(_vecB_32, unop( Iop_64to32, _vecB_low64 ) );
25443          break;
25444       case 1:
25445          assign(_vecA_32, unop( Iop_64HIto32, _vecA_low64 ) );
25446          assign(_vecB_32, unop( Iop_64HIto32, _vecB_low64 ) );
25447          break;
25448       case 2:
25449          assign(_vecA_32, unop( Iop_64to32, _vecA_high64 ) );
25450          assign(_vecB_32, unop( Iop_64to32, _vecB_high64 ) );
25451          break;
25452       case 3:
25453          assign(_vecA_32, unop( Iop_64HIto32, _vecA_high64 ) );
25454          assign(_vecB_32, unop( Iop_64HIto32, _vecB_high64 ) );
25455          break;
25456       }
25457 
25458       assign( res_64, binop( Iop_Add64,
25459                              binop ( Iop_Add64,
25460                                      binop( Iop_32HLto64,
25461                                             mkU32( 0 ),
25462                                             mkexpr(_vecA_32) ),
25463                                      binop( Iop_32HLto64,
25464                                             mkU32( 0 ),
25465                                             mkexpr(_vecB_32) ) ),
25466                              binop( Iop_32HLto64,
25467                                     mkU32( 0 ),
25468                                     mkexpr( carry ) ) ) );
25469 
25470       /* Calculate the carry to the next higher 32 bits. */
25471       carry = newTemp(Ity_I32);
25472       assign(carry, unop( Iop_64HIto32, mkexpr( res_64 ) ) );
25473 
25474       /* result is the lower 32-bits */
25475       assign(res_32, unop( Iop_64to32, mkexpr( res_64 ) ) );
25476 
25477       if (modulo) {
25478          result = newTemp(Ity_V128);
25479          assign(result, binop( Iop_OrV128,
25480                               (i == 0) ? binop( Iop_64HLtoV128,
25481                                                 mkU64(0),
25482                                                 mkU64(0) ) : mkexpr(tmp_result),
25483                               binop( Iop_ShlV128,
25484                                      binop( Iop_64HLtoV128,
25485                                             mkU64(0),
25486                                             binop( Iop_32HLto64,
25487                                                    mkU32(0),
25488                                                    mkexpr(res_32) ) ),
25489                                      mkU8(i * 32) ) ) );
25490          tmp_result = newTemp(Ity_V128);
25491          assign(tmp_result, mkexpr(result));
25492       }
25493    }
25494    if (modulo)
25495       return result;
25496    else
25497       return carry;
25498 }
25499 
25500 
dis_av_quad(UInt theInstr)25501 static Bool dis_av_quad ( UInt theInstr )
25502 {
25503    /* VX-Form */
25504    UChar opc1     = ifieldOPC(theInstr);
25505    UChar vRT_addr = ifieldRegDS(theInstr);
25506    UChar vRA_addr = ifieldRegA(theInstr);
25507    UChar vRB_addr = ifieldRegB(theInstr);
25508    UChar vRC_addr;
25509    UInt  opc2     = IFIELD( theInstr, 0, 11 );
25510 
25511    IRTemp vA    = newTemp(Ity_V128);
25512    IRTemp vB    = newTemp(Ity_V128);
25513    IRTemp vC    = IRTemp_INVALID;
25514    IRTemp cin    = IRTemp_INVALID;
25515    assign( vA, getVReg(vRA_addr));
25516    assign( vB, getVReg(vRB_addr));
25517 
25518    if (opc1 != 0x4) {
25519       vex_printf("dis_av_quad(ppc)(instr)\n");
25520       return False;
25521    }
25522 
25523    switch (opc2) {
25524    case 0x140:  // vaddcuq
25525      DIP("vaddcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
25526      putVReg( vRT_addr, unop( Iop_32UtoV128,
25527                               mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
25528                                                                mkexpr(vB),
25529                                                                mkU32(0), False) ) ) );
25530      return True;
25531    case 0x100: // vadduqm
25532       DIP("vadduqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
25533       putVReg( vRT_addr, mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
25534                                                           mkexpr(vB), mkU32(0), True) ) );
25535       return True;
25536    case 0x540: // vsubcuq
25537       DIP("vsubcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
25538       putVReg( vRT_addr,
25539                unop( Iop_32UtoV128,
25540                      mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
25541                                                       unop( Iop_NotV128,
25542                                                             mkexpr(vB) ),
25543                                                       mkU32(1), False) ) ) );
25544       return True;
25545    case 0x500: // vsubuqm
25546       DIP("vsubuqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
25547       putVReg( vRT_addr,
25548                mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
25549                                                 unop( Iop_NotV128, mkexpr(vB) ),
25550                                                 mkU32(1), True) ) );
25551       return True;
25552    case 0x054C: // vbpermq
25553    {
25554 #define BPERMD_IDX_MASK 0x00000000000000FFULL
25555 #define BPERMD_BIT_MASK 0x8000000000000000ULL
25556       int i;
25557       IRExpr * vB_expr = mkexpr(vB);
25558       IRExpr * res = binop(Iop_AndV128, mkV128(0), mkV128(0));
25559       DIP("vbpermq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
25560       for (i = 0; i < 16; i++) {
25561          IRTemp idx_tmp = newTemp( Ity_V128 );
25562          IRTemp perm_bit = newTemp( Ity_V128 );
25563          IRTemp idx = newTemp( Ity_I8 );
25564          IRTemp idx_LT127 = newTemp( Ity_I1 );
25565          IRTemp idx_LT127_ity128 = newTemp( Ity_V128 );
25566 
25567          assign( idx_tmp,
25568                  binop( Iop_AndV128,
25569                         binop( Iop_64HLtoV128,
25570                                mkU64(0),
25571                                mkU64(BPERMD_IDX_MASK) ),
25572                         vB_expr ) );
25573          assign( idx_LT127,
25574                  binop( Iop_CmpEQ32,
25575                         unop ( Iop_64to32,
25576                                unop( Iop_V128to64, binop( Iop_ShrV128,
25577                                                           mkexpr(idx_tmp),
25578                                                           mkU8(7) ) ) ),
25579                         mkU32(0) ) );
25580 
25581          /* Below, we set idx to determine which bit of vA to use for the
25582           * perm bit.  If idx_LT127 is 0, the perm bit is forced to '0'.
25583           */
25584          assign( idx,
25585                  binop( Iop_And8,
25586                         unop( Iop_1Sto8,
25587                               mkexpr(idx_LT127) ),
25588                         unop( Iop_32to8,
25589                               unop( Iop_V128to32, mkexpr( idx_tmp ) ) ) ) );
25590 
25591          assign( idx_LT127_ity128,
25592                  binop( Iop_64HLtoV128,
25593                         mkU64(0),
25594                         unop( Iop_32Uto64,
25595                               unop( Iop_1Uto32, mkexpr(idx_LT127 ) ) ) ) );
25596          assign( perm_bit,
25597                  binop( Iop_AndV128,
25598                         mkexpr( idx_LT127_ity128 ),
25599                         binop( Iop_ShrV128,
25600                                binop( Iop_AndV128,
25601                                       binop (Iop_64HLtoV128,
25602                                              mkU64( BPERMD_BIT_MASK ),
25603                                              mkU64(0)),
25604                                       binop( Iop_ShlV128,
25605                                              mkexpr( vA ),
25606                                              mkexpr( idx ) ) ),
25607                                mkU8( 127 ) ) ) );
25608          res = binop( Iop_OrV128,
25609                       res,
25610                       binop( Iop_ShlV128,
25611                              mkexpr( perm_bit ),
25612                              mkU8( i + 64 ) ) );
25613          vB_expr = binop( Iop_ShrV128, vB_expr, mkU8( 8 ) );
25614       }
25615       putVReg( vRT_addr, res);
25616       return True;
25617 #undef BPERMD_IDX_MASK
25618 #undef BPERMD_BIT_MASK
25619    }
25620 
25621    default:
25622       break;  // fall through
25623    }
25624 
25625    opc2     = IFIELD( theInstr, 0, 6 );
25626    vRC_addr = ifieldRegC(theInstr);
25627    vC = newTemp(Ity_V128);
25628    cin = newTemp(Ity_I32);
25629    switch (opc2) {
25630       case 0x3D: // vaddecuq
25631          assign( vC, getVReg(vRC_addr));
25632          DIP("vaddecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
25633              vRC_addr);
25634          assign(cin, binop( Iop_And32,
25635                             unop( Iop_64to32,
25636                                   unop( Iop_V128to64, mkexpr(vC) ) ),
25637                             mkU32(1) ) );
25638          putVReg( vRT_addr,
25639                   unop( Iop_32UtoV128,
25640                         mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB),
25641                                                          mkexpr(cin),
25642                                                          False) ) ) );
25643          return True;
25644       case 0x3C: // vaddeuqm
25645          assign( vC, getVReg(vRC_addr));
25646          DIP("vaddeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
25647              vRC_addr);
25648          assign(cin, binop( Iop_And32,
25649                             unop( Iop_64to32,
25650                                   unop( Iop_V128to64, mkexpr(vC) ) ),
25651                             mkU32(1) ) );
25652          putVReg( vRT_addr,
25653                   mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB),
25654                                                    mkexpr(cin),
25655                                                    True) ) );
25656          return True;
25657       case 0x3F: // vsubecuq
25658          assign( vC, getVReg(vRC_addr));
25659          DIP("vsubecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
25660              vRC_addr);
25661          assign(cin, binop( Iop_And32,
25662                             unop( Iop_64to32,
25663                                   unop( Iop_V128to64, mkexpr(vC) ) ),
25664                             mkU32(1) ) );
25665          putVReg( vRT_addr,
25666                   unop( Iop_32UtoV128,
25667                         mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
25668                                                          unop( Iop_NotV128,
25669                                                                mkexpr(vB) ),
25670                                                          mkexpr(cin),
25671                                                          False) ) ) );
25672          return True;
25673       case 0x3E: // vsubeuqm
25674          assign( vC, getVReg(vRC_addr));
25675          DIP("vsubeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
25676              vRC_addr);
25677          assign(cin, binop( Iop_And32,
25678                             unop( Iop_64to32,
25679                                   unop( Iop_V128to64, mkexpr(vC) ) ),
25680                             mkU32(1) ) );
25681          putVReg( vRT_addr,
25682                   mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
25683                                                    unop( Iop_NotV128, mkexpr(vB) ),
25684                                                    mkexpr(cin),
25685                                                    True) ) );
25686          return True;
25687       default:
25688          vex_printf("dis_av_quad(ppc)(opc2.2)\n");
25689          return False;
25690    }
25691 
25692    return True;
25693 }
25694 
bcd_sign_code_adjust(UInt ps,IRExpr * tmp)25695 static IRExpr * bcd_sign_code_adjust( UInt ps, IRExpr * tmp)
25696 {
25697    /* The Iop_BCDAdd and Iop_BCDSub will result in the corresponding Power PC
25698     * instruction being issued with ps = 0.  If ps = 1, the sign code, which
25699     * is in the least significant four bits of the result, needs to be updated
25700     * per the ISA:
25701     *
25702     *    If PS=0, the sign code of the result is set to 0b1100.
25703     *    If PS=1, the sign code of the result is set to 0b1111.
25704     *
25705     * Note, the ps value is NOT being passed down to the instruction issue
25706     * because passing a constant via triop() breaks the vbit-test test.  The
25707     * vbit-tester assumes it can set non-zero shadow bits for the triop()
25708     * arguments.  Thus they have to be expressions not a constant.
25709     * Use 32-bit compare instructiions as 64-bit compares are not supported
25710     * in 32-bit mode.
25711     */
25712    IRTemp mask  = newTemp(Ity_I64);
25713    IRExpr *rtn;
25714 
25715    if ( ps == 0 ) {
25716       /* sign code is correct, just return it.  */
25717       rtn = tmp;
25718 
25719    } else {
25720       /* Check if lower four bits are 0b1100, if so, change to 0b1111 */
25721       /* Make this work in 32-bit mode using only 32-bit compares */
25722       assign( mask, unop( Iop_1Sto64,
25723                           binop( Iop_CmpEQ32, mkU32( 0xC ),
25724                                  binop( Iop_And32, mkU32( 0xF ),
25725                                         unop( Iop_64to32,
25726                                               unop( Iop_V128to64, tmp )
25727                                               ) ) ) ) );
25728       rtn = binop( Iop_64HLtoV128,
25729                    unop( Iop_V128HIto64, tmp ),
25730                    binop( Iop_Or64,
25731                           binop( Iop_And64, mkU64( 0xF ), mkexpr( mask ) ),
25732                           unop( Iop_V128to64, tmp ) ) );
25733    }
25734 
25735    return rtn;
25736 }
25737 
25738 /*
25739   AltiVec BCD Arithmetic instructions.
25740   These instructions modify CR6 for various conditions in the result,
25741   including when an overflow occurs.  We could easily detect all conditions
25742   except when an overflow occurs.  But since we can't be 100% accurate
25743   in our emulation of CR6, it seems best to just not support it all.
25744 */
dis_av_bcd_misc(UInt theInstr,const VexAbiInfo * vbi)25745 static Bool dis_av_bcd_misc ( UInt theInstr, const VexAbiInfo* vbi )
25746 {
25747    UChar opc1     = ifieldOPC(theInstr);
25748    UChar vRT_addr = ifieldRegDS(theInstr);
25749    UChar vRA_addr = ifieldRegA(theInstr);
25750    UChar vRB_addr = ifieldRegB(theInstr);
25751    IRTemp vA      = newTemp(Ity_V128);
25752    IRTemp vB      = newTemp(Ity_V128);
25753    UInt  opc2     = IFIELD( theInstr, 0, 11 );
25754    IRExpr *pos, *neg, *valid, *zero, *sign;
25755    IRTemp eq_lt_gt = newTemp( Ity_I32 );
25756 
25757    assign( vA, getVReg(vRA_addr));
25758    assign( vB, getVReg(vRB_addr));
25759 
25760    if (opc1 != 0x4) {
25761       vex_printf("dis_av_bcd_misc(ppc)(instr)\n");
25762       return False;
25763    }
25764 
25765    switch (opc2) {
25766    case 0x341: // bcdcpsgn. Decimal Copy Sign VX-form
25767       {
25768          IRExpr *sign_vb, *value_va;
25769          DIP("bcdcpsgn. v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
25770 
25771          zero =
25772             BCDstring_zero( binop( Iop_AndV128,
25773                                    binop( Iop_64HLtoV128,
25774                                           mkU64( 0xFFFFFFFFFFFFFFFF ),
25775                                           mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
25776                                    mkexpr( vA ) ) );
25777 
25778          /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
25779           * codes 0xB and 0xD are negative.
25780           */
25781          sign = binop( Iop_And64, mkU64( 0xF ),
25782                        unop( Iop_V128to64, mkexpr( vB ) ) );
25783 
25784          neg = mkOR1( binop( Iop_CmpEQ64,
25785                              sign,
25786                              mkU64 ( 0xB ) ),
25787                       binop( Iop_CmpEQ64,
25788                              sign,
25789                              mkU64 ( 0xD ) ) );
25790 
25791          pos = mkNOT1( neg );
25792 
25793          /* invalid if vA or vB is not valid */
25794          valid =
25795             unop( Iop_64to32,
25796                   binop( Iop_And64,
25797                          is_BCDstring128( vbi,
25798                                           /*Signed*/True, mkexpr( vA ) ),
25799                          is_BCDstring128( vbi,
25800                                           /*Signed*/True, mkexpr( vB ) ) ) );
25801 
25802          sign_vb = binop( Iop_AndV128,
25803                           binop( Iop_64HLtoV128,
25804                                  mkU64( 0 ),
25805                                  mkU64( 0xF ) ),
25806                           mkexpr( vB ) );
25807 
25808          value_va = binop( Iop_AndV128,
25809                            binop( Iop_64HLtoV128,
25810                                   mkU64( 0xFFFFFFFFFFFFFFFF ),
25811                                   mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
25812                            mkexpr( vA ) );
25813          putVReg( vRT_addr, binop( Iop_OrV128, sign_vb, value_va ) );
25814       }
25815       break;
25816 
25817    default:
25818       vex_printf("dis_av_bcd_misc(ppc)(opc2)\n");
25819       return False;
25820    }
25821 
25822    /* set CR field 6 to:
25823     *    0b1000  if vB less then 0, i.e. vB is neg and not zero,
25824     *    0b0100  if vB greter then 0,  i.e. vB is pos and not zero,
25825     *    0b1000  if vB equals 0,
25826     *    0b0001  if vB is invalid  over rules lt, gt, eq
25827     */
25828    assign( eq_lt_gt,
25829            binop( Iop_Or32,
25830                   binop( Iop_Shl32,
25831                          unop( Iop_1Uto32,
25832                                mkAND1( neg,
25833                                        mkNOT1( zero ) ) ),
25834                          mkU8( 3 ) ),
25835                   binop( Iop_Or32,
25836                          binop( Iop_Shl32,
25837                                 unop( Iop_1Uto32,
25838                                       mkAND1( pos,
25839                                               mkNOT1( zero ) ) ),
25840                                 mkU8( 2 ) ),
25841                          binop( Iop_Shl32,
25842                                 unop( Iop_1Uto32, zero ),
25843                                 mkU8( 1 ) ) ) ) );
25844 
25845    IRTemp valid_mask = newTemp( Ity_I32 );
25846 
25847    assign( valid_mask, unop( Iop_1Sto32, unop( Iop_32to1, valid ) ) );
25848 
25849    putGST_field( PPC_GST_CR,
25850                  binop( Iop_Or32,
25851                         binop( Iop_And32,
25852                                mkexpr( valid_mask ),
25853                                mkexpr( eq_lt_gt ) ),
25854                         binop( Iop_And32,
25855                                unop( Iop_Not32, mkexpr( valid_mask ) ),
25856                                mkU32( 1 ) ) ),
25857                  6 );
25858    return True;
25859 }
25860 
dis_av_bcd(UInt theInstr,const VexAbiInfo * vbi)25861 static Bool dis_av_bcd ( UInt theInstr, const VexAbiInfo* vbi )
25862 {
25863    /* VX-Form */
25864    UChar opc1     = ifieldOPC(theInstr);
25865    UChar vRT_addr = ifieldRegDS(theInstr);
25866    UChar vRA_addr = ifieldRegA(theInstr);
25867    UChar vRB_addr = ifieldRegB(theInstr);
25868    UChar ps       = IFIELD( theInstr, 9, 1 );
25869    UInt  opc2     = IFIELD( theInstr, 0, 9 );
25870    IRTemp vA    = newTemp(Ity_V128);
25871    IRTemp vB    = newTemp(Ity_V128);
25872    IRTemp dst    = newTemp(Ity_V128);
25873    IRExpr *pos, *neg, *valid, *zero, *sign_digit, *in_range;
25874    IRTemp eq_lt_gt = newTemp( Ity_I32 );
25875    IRExpr *overflow, *value;
25876 
25877    assign( vA, getVReg(vRA_addr));
25878    assign( vB, getVReg(vRB_addr));
25879 
25880    if (opc1 != 0x4) {
25881       vex_printf("dis_av_bcd(ppc)(instr)\n");
25882       return False;
25883    }
25884 
25885    switch (opc2) {
25886    case 0x1:   // bcdadd.
25887    case 0x41:  // bcdsub.
25888       {
25889          /* NOTE 64 bit compares are not supported in 32-bit mode.  Use
25890           * 32-bit compares only.
25891           */
25892 
25893          IRExpr *sign, *res_smaller;
25894          IRExpr *signA, *signB, *sign_digitA, *sign_digitB;
25895          IRExpr *zeroA, *zeroB, *posA, *posB, *negA, *negB;
25896 
25897          if ( opc2 == 0x1 ) {
25898             DIP("bcdadd. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps);
25899             assign( dst, bcd_sign_code_adjust( ps,
25900                                                binop( Iop_BCDAdd,
25901                                                       mkexpr( vA ),
25902                                                       mkexpr( vB ) ) ) );
25903          } else {
25904             DIP("bcdsub. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps);
25905             assign( dst, bcd_sign_code_adjust( ps,
25906                                                binop( Iop_BCDSub,
25907                                                       mkexpr( vA ),
25908                                                       mkexpr( vB ) ) ) );
25909          }
25910 
25911          putVReg( vRT_addr, mkexpr( dst ) );
25912          /* set CR field 6 */
25913          /* result */
25914          zero = BCDstring_zero( binop( Iop_AndV128,
25915                                        binop( Iop_64HLtoV128,
25916                                               mkU64( 0xFFFFFFFFFFFFFFFF ),
25917                                               mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
25918                                        mkexpr(dst) ) );  // ignore sign
25919 
25920          sign_digit = binop( Iop_And32, mkU32( 0xF ),
25921                              unop( Iop_64to32,
25922                                    unop( Iop_V128to64, mkexpr( dst ) ) ) );
25923 
25924          sign = mkOR1( binop( Iop_CmpEQ32,
25925                               sign_digit,
25926                               mkU32 ( 0xB ) ),
25927                        binop( Iop_CmpEQ32,
25928                               sign_digit,
25929                               mkU32 ( 0xD ) ) );
25930          neg = mkAND1( sign, mkNOT1( zero ) );
25931 
25932          /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */
25933          pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) );
25934          valid =  unop( Iop_64to32,
25935                         binop( Iop_And64,
25936                                is_BCDstring128( vbi,
25937                                                 /*Signed*/True, mkexpr( vA ) ),
25938                                is_BCDstring128( vbi,
25939                                                 /*Signed*/True, mkexpr( vB ) )
25940                                                 ) );
25941 
25942          /* src A */
25943          zeroA = BCDstring_zero( binop( Iop_AndV128,
25944                                         binop( Iop_64HLtoV128,
25945                                                mkU64( 0xFFFFFFFFFFFFFFFF ),
25946                                                mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
25947                                         mkexpr( vA ) ) );  // ignore sign
25948          sign_digitA = binop( Iop_And32, mkU32( 0xF ),
25949                               unop( Iop_64to32,
25950                                     unop( Iop_V128to64, mkexpr( vA ) ) ) );
25951 
25952          signA = mkOR1( binop( Iop_CmpEQ32,
25953                                sign_digitA,
25954                                mkU32 ( 0xB ) ),
25955                         binop( Iop_CmpEQ32,
25956                                sign_digitA,
25957                                mkU32 ( 0xD ) ) );
25958          negA = mkAND1( signA, mkNOT1( zeroA ) );
25959          /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */
25960          posA = mkAND1( mkNOT1( signA ), mkNOT1( zeroA ) );
25961 
25962          /* src B */
25963          zeroB = BCDstring_zero( binop( Iop_AndV128,
25964                                         binop( Iop_64HLtoV128,
25965                                                mkU64( 0xFFFFFFFFFFFFFFFF ),
25966                                                mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
25967                                         mkexpr( vB ) ) );  // ignore sign
25968          sign_digitB = binop( Iop_And32, mkU32( 0xF ),
25969                               unop( Iop_64to32,
25970                                     unop( Iop_V128to64, mkexpr( vB ) ) ) );
25971 
25972          signB = mkOR1( binop( Iop_CmpEQ32,
25973                                sign_digitB,
25974                                mkU32 ( 0xB ) ),
25975                         binop( Iop_CmpEQ32,
25976                                sign_digitB,
25977                                mkU32 ( 0xD ) ) );
25978          negB = mkAND1( signB, mkNOT1( zeroB ) );
25979 
25980 
25981          /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */
25982          posB = mkAND1( mkNOT1( signB ), mkNOT1( zeroB ) );
25983 
25984 
25985          if (mode64) {
25986 	    res_smaller = mkAND1( CmpGT128U( mkexpr( vA ), mkexpr( dst ) ),
25987 				  CmpGT128U( mkexpr( vB ), mkexpr( dst ) ) );
25988 
25989          } else {
25990             /* Have to do this with 32-bit compares, expensive */
25991             res_smaller = mkAND1( UNSIGNED_CMP_GT_V128( mkexpr( vA ),
25992                                                         mkexpr( dst ) ),
25993                                   UNSIGNED_CMP_GT_V128( mkexpr( vB ),
25994                                                         mkexpr( dst ) ) );
25995          }
25996 
25997          if ( opc2 == 0x1) {
25998             /* Overflow for Add can only occur if the signs of the operands
25999              * are the same and the two operands are non-zero.  On overflow,
26000              * the PPC hardware produces a result consisting of just the lower
26001              * digits of the result.  So, if the result is less then both
26002              * operands and the sign of the operands are the same overflow
26003              * occured.
26004              */
26005             overflow = mkOR1( mkAND1( res_smaller, mkAND1( negA, negB ) ),
26006                               mkAND1( res_smaller, mkAND1( posA, posB ) ) );
26007          } else {
26008             /* Overflow for Add can only occur if the signs of the operands
26009              * are the different and the two operands are non-zero.  On overflow,
26010              * the PPC hardware produces a result consisting of just the lower
26011              * digits of the result.  So, if the result is less then both
26012              * operands and the sign of the operands are different overflow
26013              * occured.
26014              */
26015             overflow = mkOR1( mkAND1( res_smaller, mkAND1( negA, posB ) ),
26016                               mkAND1( res_smaller, mkAND1( posA, negB ) ) );
26017          }
26018       }
26019      break;
26020 
26021    case 0x081: // bcdus.  Decimal Unsigned Shift VX-form
26022    case 0x0C1: // bcds.   Decimal Shift VX-form
26023    case 0x1C1: // bcdsr.  Decimal Shift and Round VX-form
26024       {
26025          IRExpr *shift_dir;
26026          IRExpr *shift_mask, *result, *new_sign_val, *sign;
26027          IRExpr *not_excess_shift, *not_excess_shift_mask;
26028          IRTemp shift_dir_mask = newTemp( Ity_I64 );
26029          IRTemp shift_by = newTemp( Ity_I64 );
26030          IRTemp shift_field = newTemp( Ity_I64 );
26031          IRTemp shifted_out = newTemp( Ity_V128 );
26032          IRTemp value_shl = newTemp( Ity_V128 );
26033          IRTemp value_shr = newTemp( Ity_V128 );
26034          IRTemp round = newTemp( Ity_I32);
26035 
26036          ULong value_mask_low = 0;
26037          UInt max_shift = 0;
26038 
26039          if (opc2 == 0x0C1) {
26040             DIP("bcds. v%d,v%d,v%d,%d\n", vRT_addr, vRA_addr, vRB_addr, ps);
26041             value_mask_low = 0xFFFFFFFFFFFFFFF0;
26042             max_shift = 30 * 4; /* maximum without shifting all digits out */
26043 
26044          }  else if (opc2 == 0x1C1) {
26045             DIP("bcdsr. v%d,v%d,v%d,%d\n", vRT_addr, vRA_addr, vRB_addr, ps);
26046 
26047             value_mask_low = 0xFFFFFFFFFFFFFFF0;
26048             max_shift = 30 * 4; /* maximum without shifting all digits out */
26049 
26050          } else {
26051             DIP("bcdus. v%d,v%d,v%d,%d\n", vRT_addr, vRA_addr,
26052                 vRB_addr, ps);
26053             value_mask_low = 0xFFFFFFFFFFFFFFFF;
26054             max_shift = 31 * 4; /* maximum without shifting all digits out */
26055          }
26056 
26057          value = binop( Iop_AndV128,
26058                         binop( Iop_64HLtoV128,
26059                                mkU64( 0xFFFFFFFFFFFFFFFF ),
26060                                mkU64( value_mask_low ) ),
26061                         mkexpr( vB ) );
26062 
26063          zero = BCDstring_zero( value );
26064 
26065          /* Shift field is 2's complement value */
26066          assign( shift_field, unop( Iop_V128to64,
26067                                     binop( Iop_ShrV128,
26068                                            binop( Iop_AndV128,
26069                                                   binop( Iop_64HLtoV128,
26070                                                          mkU64( 0xFF ),
26071                                                          mkU64( 0x0) ),
26072                                                   mkexpr( vA ) ),
26073                                            mkU8( 64 ) ) ) );
26074 
26075          /* if shift_dir = 0 shift left, otherwise shift right */
26076          shift_dir = binop( Iop_CmpEQ64,
26077                             binop( Iop_Shr64,
26078                                    mkexpr( shift_field ),
26079                                    mkU8( 7 ) ),
26080                             mkU64( 1 ) );
26081 
26082          assign( shift_dir_mask, unop( Iop_1Sto64, shift_dir ) );
26083 
26084          /* Shift field is stored in 2's complement form */
26085          assign(shift_by,
26086                 binop( Iop_Mul64,
26087                        binop( Iop_Or64,
26088                               binop( Iop_And64,
26089                                      unop( Iop_Not64,
26090                                            mkexpr( shift_dir_mask ) ),
26091                                      mkexpr( shift_field ) ),
26092                               binop( Iop_And64,
26093                                      mkexpr( shift_dir_mask ),
26094                                      binop( Iop_And64,
26095                                             binop( Iop_Add64,
26096                                                    mkU64( 1 ),
26097                                                    unop( Iop_Not64,
26098                                                          mkexpr( shift_field ) ) ),
26099                                             mkU64( 0xFF ) ) ) ),
26100                        mkU64( 4 ) ) );
26101 
26102          /* If the shift exceeds 128 bits, we need to force the result
26103           * to zero because Valgrind shift amount is only 7-bits. Otherwise,
26104           * we get a shift amount of mod(shift_by, 127)
26105           */
26106          not_excess_shift = unop( Iop_1Sto64,
26107                                   binop( Iop_CmpLE64U,
26108                                          mkexpr( shift_by ),
26109                                          mkU64( max_shift ) ) );
26110 
26111          not_excess_shift_mask = binop( Iop_64HLtoV128,
26112                                         not_excess_shift,
26113                                         not_excess_shift );
26114 
26115          assign( value_shl,
26116                  binop( Iop_ShlV128, value, unop( Iop_64to8,
26117                                                   mkexpr( shift_by) ) ) );
26118          assign( value_shr,
26119                  binop( Iop_AndV128,
26120                         binop( Iop_64HLtoV128,
26121                                mkU64( 0xFFFFFFFFFFFFFFFF ),
26122                                mkU64( value_mask_low) ),
26123                         binop( Iop_ShrV128,
26124                                value,
26125                                unop( Iop_64to8,
26126                                      mkexpr( shift_by ) )  ) ) );
26127 
26128          /* Overflow occurs if the shift amount is greater than zero, the
26129           * operation is a left shift and any non-zero digits are left
26130           * shifted out.
26131           */
26132          assign( shifted_out,
26133                  binop( Iop_OrV128,
26134                         binop( Iop_ShrV128,
26135                                value,
26136                                unop( Iop_64to8,
26137                                      binop( Iop_Sub64,
26138                                             mkU64( 32*4 ),
26139                                             mkexpr( shift_by ) ) ) ),
26140                         binop( Iop_AndV128,
26141                                unop( Iop_NotV128,
26142                                      not_excess_shift_mask ),
26143                                value ) ) );
26144 
26145          overflow = mkAND1( mkNOT1( BCDstring_zero( mkexpr( shifted_out ) ) ),
26146                             mkAND1( mkNOT1( shift_dir ),
26147                                     binop( Iop_CmpNE64,
26148                                            mkexpr( shift_by ),
26149                                            mkU64( 0 ) ) ) );
26150 
26151          if ((opc2 == 0xC1) || (opc2 == 0x1C1)) {
26152             /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
26153              * codes 0xB and 0xD are negative.
26154              */
26155             sign_digit = binop( Iop_And64, mkU64( 0xF ),
26156                                 unop( Iop_V128to64, mkexpr( vB ) ) );
26157 
26158             sign = mkOR1( binop( Iop_CmpEQ64,
26159                                  sign_digit,
26160                                  mkU64 ( 0xB ) ),
26161                           binop( Iop_CmpEQ64,
26162                                  sign_digit,
26163                                  mkU64 ( 0xD ) ) );
26164             neg = mkAND1( sign, mkNOT1( zero ) );
26165 
26166             /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */
26167             pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) );
26168 
26169             valid =
26170                unop( Iop_64to32,
26171                      is_BCDstring128( vbi, /* Signed */True, mkexpr( vB ) ) );
26172 
26173          } else {
26174             /* string is an unsigned BCD value */
26175             pos = mkU1( 1 );
26176             neg = mkU1( 0 );
26177             sign = mkU1( 0 );
26178 
26179             valid =
26180                unop( Iop_64to32,
26181                      is_BCDstring128( vbi, /* Unsigned */False,
26182                                       mkexpr( vB ) ) );
26183          }
26184 
26185          /* if PS = 0
26186                   vB positive, sign is C
26187                   vB negative, sign is D
26188             if PS = 1
26189                   vB positive, sign is F
26190                   vB negative, sign is D
26191             Note can't use pos or neg here since they are ANDed with zero,
26192             use sign instead.
26193          */
26194          if (ps == 0) {
26195             new_sign_val = binop( Iop_Or64,
26196                                   unop( Iop_1Uto64, sign ),
26197                                   mkU64( 0xC ) );
26198 
26199          } else {
26200             new_sign_val = binop( Iop_Xor64,
26201                                   binop( Iop_Shl64,
26202                                          unop( Iop_1Uto64, sign ),
26203                                          mkU8( 1 ) ),
26204                                   mkU64( 0xF ) );
26205          }
26206 
26207          shift_mask = binop( Iop_64HLtoV128,
26208                              unop( Iop_1Sto64, shift_dir ),
26209                              unop( Iop_1Sto64, shift_dir ) );
26210 
26211          result = binop( Iop_OrV128,
26212                          binop( Iop_AndV128, mkexpr( value_shr ), shift_mask ),
26213                          binop( Iop_AndV128,
26214                                 mkexpr( value_shl ),
26215                                 unop( Iop_NotV128, shift_mask ) ) );
26216 
26217          if (opc2 == 0xC1) {    // bcds.
26218             putVReg( vRT_addr, binop( Iop_OrV128,
26219                                       binop( Iop_64HLtoV128,
26220                                              mkU64( 0 ),
26221                                              new_sign_val ),
26222                                       binop( Iop_AndV128,
26223                                              not_excess_shift_mask,
26224                                              result ) ) );
26225          } else if (opc2 == 0x1C1) {  //bcdsr.
26226             /* If shifting right, need to round up if needed */
26227             assign( round, unop( Iop_1Uto32,
26228                                  mkAND1( shift_dir,
26229                                          check_BCD_round( value,
26230                                                           shift_by ) ) ) );
26231 
26232             putVReg( vRT_addr,
26233                      binop( Iop_OrV128,
26234                             binop( Iop_64HLtoV128,
26235                                    mkU64( 0 ),
26236                                    new_sign_val ),
26237                             binop( Iop_AndV128,
26238                                    not_excess_shift_mask,
26239                                    mkexpr( increment_BCDstring( vbi, result,
26240                                                                 mkexpr( round)
26241                                                                 ) ) ) ) );
26242          } else {  // bcdus.
26243             putVReg( vRT_addr, binop( Iop_AndV128,
26244                                       not_excess_shift_mask,
26245                                       result ) );
26246          }
26247       }
26248       break;
26249 
26250    case 0x101:  // bcdtrunc.   Decimal Truncate VX-form
26251    case 0x141:  // bcdutrunc.  Decimal Unsigned Truncate VX-form
26252       {
26253          IRTemp length = newTemp( Ity_I64 );
26254          IRTemp masked_out = newTemp( Ity_V128 );
26255          IRExpr *new_sign_val, *result, *shift;
26256          IRExpr *length_neq_128, *sign;
26257          ULong value_mask_low;
26258          Int max_digits;
26259 
26260          if ( opc2 == 0x101) {     // bcdtrunc.
26261             value_mask_low = 0xFFFFFFFFFFFFFFF0;
26262             max_digits = 31;
26263          } else {
26264             value_mask_low = 0xFFFFFFFFFFFFFFFF;
26265             max_digits = 32;
26266          }
26267 
26268          assign( length, binop( Iop_And64,
26269                                      unop( Iop_V128HIto64,
26270                                            mkexpr( vA ) ),
26271                                      mkU64( 0xFFFF ) ) );
26272          shift = unop( Iop_64to8,
26273                        binop( Iop_Mul64,
26274                               binop( Iop_Sub64,
26275                                      mkU64( max_digits ),
26276                                      mkexpr( length ) ),
26277                               mkU64( 4 ) ) );
26278 
26279          /* Note ShrV128 gets masked by 127 so a shift of 128 results in
26280           * the value not being shifted.  A shift of 128 sets the register
26281           * zero.  So if length+1 = 128, just set the value to 0.
26282          */
26283          length_neq_128 = mkNOT1( binop( Iop_CmpEQ64,
26284                                          mkexpr( length),
26285                                          mkU64( 0x1F ) ) );
26286 
26287          assign( masked_out,
26288                  binop( Iop_AndV128,
26289                         binop( Iop_64HLtoV128,
26290                                unop( Iop_1Sto64, length_neq_128 ),
26291                                unop( Iop_1Sto64, length_neq_128 ) ),
26292                         binop( Iop_ShrV128,
26293                                mkexpr( vB ),
26294                                unop( Iop_64to8,
26295                                      binop( Iop_Mul64,
26296                                             mkU64( 4 ),
26297                                             binop( Iop_Add64,
26298                                                    mkU64( 1 ),
26299                                                    mkexpr( length ) ) ) ) )
26300                         ) );
26301 
26302          /* Overflow occurs if any of the left most 31-length digits of vB
26303           * are non-zero.
26304           */
26305          overflow = mkNOT1( BCDstring_zero( mkexpr( masked_out ) ) );
26306 
26307          value = binop( Iop_AndV128,
26308                         binop( Iop_64HLtoV128,
26309                                mkU64( 0xFFFFFFFFFFFFFFFF ),
26310                                mkU64( value_mask_low ) ),
26311                         mkexpr( vB ) );
26312 
26313 
26314          if ( opc2 == 0x101 ) {     // bcdtrunc.
26315             /* Check if all of the non-sign digits are zero */
26316             zero = BCDstring_zero( binop( Iop_AndV128,
26317                                           binop( Iop_64HLtoV128,
26318                                                  mkU64( 0xFFFFFFFFFFFFFFFF ),
26319                                                  mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
26320                                           value ) );
26321 
26322             /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
26323              * codes 0xB and 0xD are negative.
26324              */
26325             sign_digit = binop( Iop_And64, mkU64( 0xF ),
26326                                 unop( Iop_V128to64, mkexpr( vB ) ) );
26327 
26328             sign = mkOR1( binop( Iop_CmpEQ64,
26329                                  sign_digit,
26330                                  mkU64 ( 0xB ) ),
26331                           binop( Iop_CmpEQ64,
26332                                  sign_digit,
26333                                  mkU64 ( 0xD ) ) );
26334             neg = mkAND1( sign, mkNOT1( zero ) );
26335 
26336             /* Pos position AKA gt = 1 if ((not neg) & (not eq zero)) */
26337             pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) );
26338 
26339             /* Note can't use pos or neg here since they are ANDed with zero,
26340                use sign instead.
26341             */
26342             if (ps == 0) {
26343                new_sign_val = binop( Iop_Or64,
26344                                      unop( Iop_1Uto64, sign ),
26345                                      mkU64( 0xC ) );
26346             } else {
26347                new_sign_val = binop( Iop_Xor64,
26348                                      binop( Iop_Shl64,
26349                                             unop( Iop_1Uto64, sign ),
26350                                             mkU8 ( 1 ) ),
26351                                      mkU64( 0xF ) );
26352             }
26353             valid =
26354                unop( Iop_64to32,
26355                      is_BCDstring128( vbi, /* Signed */True, mkexpr( vB ) ) );
26356 
26357          } else {   // bcdutrunc.
26358             /* Check if all of the digits are zero */
26359             zero = BCDstring_zero( value );
26360 
26361             /* unsigned value, need to make CC code happy */
26362             neg = mkU1( 0 );
26363 
26364             /* Pos position AKA gt = 1 if (not eq zero) */
26365             pos = mkNOT1( zero );
26366             valid =
26367                unop( Iop_64to32,
26368                      is_BCDstring128( vbi, /* Unsigned */False,
26369                                       mkexpr( vB ) ) );
26370          }
26371 
26372          /* If vB is not valid, the result is undefined, but we need to
26373           * match the hardware so the output of the test suite will match.
26374           * Hardware sets result to 0x0.
26375           */
26376          result = binop( Iop_AndV128,
26377                          mkV128( 0xFFFF ),
26378                          binop( Iop_ShrV128,
26379                                 binop( Iop_ShlV128, value, shift ),
26380                                 shift ) );
26381 
26382          if ( opc2 == 0x101) {     // bcdtrunc.
26383             putVReg( vRT_addr, binop( Iop_OrV128,
26384                                       binop( Iop_64HLtoV128,
26385                                              mkU64( 0 ),
26386                                              new_sign_val ),
26387                                       result ) );
26388          } else {
26389             putVReg( vRT_addr, result );
26390          }
26391       }
26392       break;
26393 
26394    case 0x181:   // bcdctz., bcdctn., bcdcfz., bcdcfn., bcdsetsgn.,
26395                  // bcdcfsq., bcdctsq.
26396       {
26397          UInt inst_select = IFIELD( theInstr, 16, 5);
26398 
26399          switch (inst_select) {
26400          case 0:  // bcdctsq.  (Decimal Convert to Signed Quadword VX-form)
26401             {
26402                IRExpr *sign;
26403 
26404                /* The instruction takes a 32-bit integer in a vector source
26405                 * register and returns the signed packed decimal number
26406                 * in a vector register.  The source integer needs to be moved
26407                 * from the V128 to an I32 for the Iop.
26408                 */
26409 
26410                DIP("bcdctsq v%d, v%d\n", vRT_addr, vRB_addr);
26411 
26412                putVReg( vRT_addr, unop( Iop_BCD128toI128S, mkexpr( vB ) ) );
26413 
26414                sign =  binop( Iop_And64,
26415                               unop( Iop_V128to64, mkexpr( vB ) ),
26416                               mkU64( 0xF ) );
26417                zero = mkAND1( binop( Iop_CmpEQ64,
26418                                      unop( Iop_V128HIto64, mkexpr( vB ) ),
26419                                      mkU64( 0x0 ) ),
26420                               binop( Iop_CmpEQ64,
26421                                      binop( Iop_And64,
26422                                             unop( Iop_V128to64, mkexpr( vB ) ),
26423                                             mkU64( 0xFFFFFFF0 ) ),
26424                                      mkU64( 0x0 ) ) );
26425                pos = mkAND1( mkNOT1( zero ),
26426                              mkOR1( mkOR1( binop( Iop_CmpEQ64,
26427                                                   sign, mkU64( 0xA ) ),
26428                                            binop( Iop_CmpEQ64,
26429                                                   sign, mkU64( 0xC ) ) ),
26430                                     mkOR1( binop( Iop_CmpEQ64,
26431                                                   sign, mkU64( 0xE ) ),
26432                                            binop( Iop_CmpEQ64,
26433                                                   sign, mkU64( 0xF ) ) ) ) );
26434                neg = mkAND1( mkNOT1( zero ),
26435                              mkOR1( binop( Iop_CmpEQ64, sign, mkU64( 0xB ) ),
26436                                     binop( Iop_CmpEQ64, sign, mkU64( 0xD ) ) ) );
26437 
26438                /* Check each of the nibbles for a valid digit 0 to 9 */
26439                valid =
26440                   unop( Iop_64to32,
26441                         is_BCDstring128( vbi, /* Signed */True,
26442                                          mkexpr( vB ) ) );
26443                overflow = mkU1( 0 );  // not used
26444             }
26445             break;
26446 
26447          case 2:  // bcdcfsq. (Decimal Convert from Signed Quadword VX-form)
26448             {
26449                IRExpr *pos_upper_gt, *pos_upper_eq, *pos_lower_gt;
26450                IRExpr *neg_upper_lt, *neg_upper_eq, *neg_lower_lt;
26451 
26452                DIP("bcdcfsq v%d, v%d, %d\n", vRT_addr, vRB_addr, ps);
26453 
26454                /* The instruction takes a signed packed decimal number and
26455                 * returns the integer value in the vector register.  The Iop
26456                 * returns an I32 which needs to be moved to the destination
26457                 * vector register.
26458                 */
26459                putVReg( vRT_addr,
26460                         binop( Iop_I128StoBCD128, mkexpr( vB ), mkU8( ps ) ) );
26461 
26462                zero = mkAND1( binop( Iop_CmpEQ64, mkU64( 0 ),
26463                                      unop( Iop_V128to64, mkexpr( vB ) ) ),
26464                               binop( Iop_CmpEQ64, mkU64( 0 ),
26465                                      unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
26466                pos = mkAND1( mkNOT1 ( zero ),
26467                              binop( Iop_CmpEQ64, mkU64( 0 ),
26468                                     binop( Iop_And64,
26469                                            unop( Iop_V128HIto64,
26470                                                  mkexpr( vB ) ),
26471                                            mkU64( 0x8000000000000000UL ) ) ) );
26472                neg = mkAND1( mkNOT1 ( zero ),
26473                              binop( Iop_CmpEQ64, mkU64( 0x8000000000000000UL ),
26474                                     binop( Iop_And64,
26475                                            unop( Iop_V128HIto64,
26476                                                  mkexpr( vB ) ),
26477                                            mkU64( 0x8000000000000000UL ) ) ) );
26478 
26479                /* Overflow occurs if: vB > 10^31-1 OR vB < -10^31-1
26480                 * do not have a 128 bit compare.  Will have to compare the
26481                 * upper 64 bit and athe lower 64 bits.  If the upper 64-bits
26482                 * are equal then overflow if the lower 64 bits of vB is greater
26483                 * otherwise if the upper bits of vB is greater then the max
26484                 * for the upper 64-bits then overflow
26485                 *
26486                 *     10^31-1 = 0x7E37BE2022C0914B267FFFFFFF
26487                 */
26488                pos_upper_gt = binop( Iop_CmpLT64U,
26489                                      mkU64( 0x7E37BE2022 ),
26490                                      unop( Iop_V128HIto64, mkexpr( vB ) ) );
26491                pos_upper_eq = binop( Iop_CmpEQ64,
26492                                      unop( Iop_V128HIto64, mkexpr( vB ) ),
26493                                      mkU64( 0x7E37BE2022 ) );
26494                pos_lower_gt = binop( Iop_CmpLT64U,
26495                                      mkU64( 0x0914B267FFFFFFF ),
26496                                      unop( Iop_V128to64, mkexpr( vB ) ) );
26497                /* -10^31-1 =  0X81C841DFDD3F6EB4D97FFFFFFF */
26498                neg_upper_lt = binop( Iop_CmpLT64U,
26499                                      mkU64( 0X81C841DFDD ),
26500                                      unop( Iop_V128HIto64, mkexpr( vB ) ) );
26501                neg_upper_eq = binop( Iop_CmpEQ64,
26502                                      unop( Iop_V128HIto64, mkexpr( vB ) ),
26503                                      mkU64( 0X81C841DFDD ) );
26504                neg_lower_lt = binop( Iop_CmpLT64U,
26505                                      mkU64( 0x3F6EB4D97FFFFFFF ),
26506                                      unop( Iop_V128to64, mkexpr( vB ) ) );
26507 
26508                /* calculate overflow, masking for positive and negative */
26509                overflow = mkOR1( mkAND1( pos,
26510                                          mkOR1( pos_upper_gt,
26511                                                 mkAND1( pos_upper_eq,
26512                                                         pos_lower_gt ) ) ),
26513                                  mkAND1( neg,
26514                                          mkOR1( neg_upper_lt,
26515                                                 mkAND1( neg_upper_eq,
26516                                                         neg_lower_lt )
26517                                                 ) ) );
26518                valid = mkU32( 1 );
26519             }
26520             break;
26521 
26522          case 4:  // bcdctz. (Decimal Convert to Zoned VX-form)
26523             {
26524                IRExpr *ox_flag, *sign, *vrb_nibble30;
26525                int neg_bit_shift;
26526                unsigned int upper_byte, sign_byte;
26527                IRTemp tmp = newTemp( Ity_V128 );
26528 
26529                DIP("bcdctz. v%d,v%d,%d\n", vRT_addr, vRB_addr, ps);
26530 
26531                if (ps == 0) {
26532                   upper_byte = 0x30;
26533                   sign_byte = 0x30;
26534                   neg_bit_shift = 4+2;  /* sign byte is in bits [7:4] */
26535                } else {
26536                   upper_byte = 0xF0;
26537                   sign_byte = 0xC0;
26538                   neg_bit_shift = 4+0;
26539                }
26540 
26541                /* Grab vB bits[7:4].  It goes into bits [3:0] of the
26542                 * result.
26543                 */
26544                vrb_nibble30 = binop( Iop_Shr64,
26545                                      binop( Iop_And64,
26546                                             unop( Iop_V128to64, mkexpr( vB ) ),
26547                                             mkU64( 0xF0 ) ),
26548                                      mkU8( 4 ) );
26549 
26550                /* Upper 24 hex digits of VB, i.e. hex digits vB[0:23],
26551                 * must be zero for the value to be zero.  This goes
26552                 * in the overflow position of the condition code register.
26553                 */
26554                ox_flag = binop( Iop_CmpEQ64,
26555                                      binop( Iop_And64,
26556                                             unop( Iop_V128to64, mkexpr( vB ) ),
26557                                             mkU64( 0xFFFFFFFFFFFFFFFF ) ),
26558                                 mkU64( 0 ) );
26559 
26560                /* zero is the same as eq_flag */
26561                zero = mkAND1( binop( Iop_CmpEQ64,
26562                                      binop( Iop_And64,
26563                                             unop( Iop_V128HIto64, mkexpr( vB ) ),
26564                                             mkU64( 0xFFFFFFFFFFFFFFFF ) ),
26565                                      mkU64( 0 ) ),
26566                               binop( Iop_CmpEQ64,
26567                                      binop( Iop_And64,
26568                                             unop( Iop_V128to64, mkexpr( vB ) ),
26569                                             mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
26570                                      mkU64( 0 ) ) );
26571 
26572                /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
26573                 * codes 0xB and 0xD are negative.
26574                 */
26575                sign_digit = binop( Iop_And64, mkU64( 0xF ),
26576                                    unop( Iop_V128to64, mkexpr( vB ) ) );
26577 
26578                /* The negative value goes in the LT bit position of the
26579                 * condition code register. Set neg if the sign of vB
26580                 * is negative and zero is true.
26581                 */
26582                sign = mkOR1( binop( Iop_CmpEQ64,
26583                                     sign_digit,
26584                                     mkU64 ( 0xB ) ),
26585                              binop( Iop_CmpEQ64,
26586                                     sign_digit,
26587                                     mkU64 ( 0xD ) ) );
26588                neg = mkAND1( sign, mkNOT1( zero ) );
26589 
26590                /* The positive value goes in the LT bit position of the
26591                 * condition code register. Set positive if the sign of the
26592                 * value is not negative.
26593                 */
26594                pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) );
26595 
26596                assign( tmp,
26597                        convert_to_zoned( vbi, mkexpr( vB ),
26598                                          mkU64( upper_byte ) ) );
26599 
26600                /* Insert the sign based on ps and sign of vB
26601                 * in the lower byte.
26602                 */
26603                putVReg( vRT_addr,
26604                         binop( Iop_OrV128,
26605                                binop( Iop_64HLtoV128,
26606                                       mkU64( 0 ),
26607                                       vrb_nibble30 ),
26608                                binop( Iop_OrV128,
26609                                       mkexpr( tmp ),
26610                                       binop( Iop_64HLtoV128,
26611                                              mkU64( 0 ),
26612                                              binop( Iop_Or64,
26613                                                     mkU64( sign_byte ),
26614                                                     binop( Iop_Shl64,
26615                                                            unop( Iop_1Uto64,
26616                                                                  sign ),
26617                                                            mkU8( neg_bit_shift)
26618                                ) ) ) ) ) );
26619 
26620                /* A valid number must have a value that is less then or
26621                 * equal to 10^16 - 1.  This is checked by making sure
26622                 * bytes [31:16] of vB are zero.
26623                 */
26624                in_range = binop( Iop_CmpEQ64,
26625                                  binop( Iop_And64,
26626                                         mkU64( 0xFFFFFFFFFFFFFFF0 ),
26627                                         unop( Iop_V128HIto64, mkexpr( vB ) ) ),
26628                                  mkU64( 0 ) );
26629 
26630                /* overflow is set if ox_flag or not in_inrange.  Setting is
26631                 * ORed with the other condition code values.
26632                 */
26633                overflow = mkOR1( ox_flag, mkNOT1( in_range ) );
26634 
26635                /* The sign code must be between 0xA and 0xF and all digits are
26636                 * between 0x0 and 0x9. The vB must be in range to be valid.
26637                 * If not valid, condition code set to 0x0001.
26638                 */
26639                valid =
26640                   unop( Iop_64to32,
26641                         is_BCDstring128( vbi, /* Signed */True,
26642                                          mkexpr( vB ) ) );
26643             }
26644             break;
26645 
26646          case 5:  // bcdctn. (Decimal Convert to National VX-form)
26647             {
26648                IRExpr *ox_flag, *sign;
26649                IRTemp tmp = newTemp( Ity_V128 );;
26650 
26651                DIP("bcdctn. v%d,v%d\n", vRT_addr, vRB_addr);
26652 
26653                value = binop( Iop_And64,
26654                               mkU64( 0xFFFFFFFF ),
26655                               unop( Iop_V128to64, mkexpr( vB ) ) );
26656 
26657                /* A valid number must have a value that is less then or
26658                 * equal to 10^7 - 1.  This is checked by making sure
26659                 * bytes [31:8] of vB are zero.
26660                 */
26661                in_range = mkAND1( binop( Iop_CmpEQ64,
26662                                          unop( Iop_V128HIto64, mkexpr( vB ) ),
26663                                          mkU64( 0 ) ),
26664                                   binop( Iop_CmpEQ64,
26665                                          binop( Iop_Shr64,
26666                                                 unop( Iop_V128to64,
26667                                                       mkexpr( vB ) ),
26668                                                 mkU8( 32 ) ),
26669                                          mkU64( 0 ) ) );
26670 
26671                /* The sign code must be between 0xA and 0xF and all digits are
26672                 *  between 0x0 and 0x9.
26673                 */
26674                valid =
26675                   unop( Iop_64to32,
26676                         is_BCDstring128( vbi, /* Signed */True,
26677                                          mkexpr( vB ) ) );
26678 
26679                /* Upper 24 hex digits of VB, i.e. hex ditgits vB[0:23],
26680                 * must be zero for the ox_flag to be zero.  This goes
26681                 * in the LSB position (variable overflow) of the
26682                 * condition code register.
26683                 */
26684                ox_flag =
26685                   mkNOT1( mkAND1( binop( Iop_CmpEQ64,
26686                                          binop( Iop_And64,
26687                                                 unop( Iop_V128HIto64,
26688                                                       mkexpr( vB ) ),
26689                                                 mkU64( 0xFFFFFFFFFFFFFFFF ) ),
26690                                          mkU64( 0 ) ),
26691                                   binop( Iop_CmpEQ64,
26692                                          binop( Iop_And64,
26693                                                 unop( Iop_V128to64,
26694                                                       mkexpr( vB ) ),
26695                                                 mkU64( 0xFFFFFFFF00000000 ) ),
26696                                          mkU64( 0 ) ) ) );
26697 
26698                /* Set zero to 1 if all of the bytes in vB are zero.  This is
26699                 * used when setting the lt_flag (variable neg) and the gt_flag
26700                 * (variable pos).
26701                 */
26702                zero = mkAND1( binop( Iop_CmpEQ64,
26703                                      binop( Iop_And64,
26704                                             unop( Iop_V128HIto64,
26705                                                   mkexpr( vB ) ),
26706                                             mkU64( 0xFFFFFFFFFFFFFFFF ) ),
26707                                          mkU64( 0 ) ),
26708                               binop( Iop_CmpEQ64,
26709                                       binop( Iop_And64,
26710                                              unop( Iop_V128to64, mkexpr( vB ) ),
26711                                              mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
26712                                       mkU64( 0 ) ) );
26713 
26714                /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
26715                 * codes 0xB and 0xD are negative.
26716                 */
26717                sign_digit = binop( Iop_And64, mkU64( 0xF ), value );
26718 
26719                /* The negative value goes in the LT bit position of the
26720                 * condition code register. Set neg if the sign of the
26721                 * value is negative and the value is zero.
26722                 */
26723                sign = mkOR1( binop( Iop_CmpEQ64,
26724                                     sign_digit,
26725                                     mkU64 ( 0xB ) ),
26726                              binop( Iop_CmpEQ64,
26727                                     sign_digit,
26728                                     mkU64 ( 0xD ) ) );
26729                neg = mkAND1( sign, mkNOT1( zero ) );
26730 
26731                /* The positive value goes in the LT bit position of the
26732                 * condition code register. Set neg if the sign of the
26733                 * value is not negative and the value is zero.
26734                 */
26735                pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) );
26736 
26737                assign( tmp,
26738                        convert_to_national( vbi, mkexpr( vB ) ) );
26739 
26740                /* If vB is positive insert sign value 0x002B, otherwise
26741                 * insert 0x002D for negative. Have to use sign not neg
26742                 * because neg has been ANDed with zero.  This is 0x29
26743                 * OR'd with (sign << 1 | NOT sign) << 1.
26744                 * sign = 1 if vB is negative.
26745                 */
26746                putVReg( vRT_addr,
26747                         binop( Iop_OrV128,
26748                                mkexpr( tmp ),
26749                                binop( Iop_64HLtoV128,
26750                                       mkU64( 0 ),
26751                                       binop( Iop_Or64,
26752                                              mkU64( 0x29 ),
26753                                              binop( Iop_Or64,
26754                                                     binop( Iop_Shl64,
26755                                                            unop( Iop_1Uto64,
26756                                                                  sign ),
26757                                                            mkU8( 2 ) ),
26758                                                     binop( Iop_Shl64,
26759                                                            unop( Iop_1Uto64,
26760                                                                  mkNOT1(sign)),
26761                                                            mkU8( 1 ) )
26762                                                     ) ) ) ) );
26763 
26764 
26765                /* The sign code must be between 0xA and 0xF and all digits are
26766                 *  between 0x0 and 0x9. The vB must be in range to be valid.
26767                 */
26768                valid =
26769                   unop( Iop_64to32,
26770                         is_BCDstring128( vbi, /* Signed */True,
26771                                          mkexpr( vB ) ) );
26772 
26773                overflow = ox_flag;
26774             }
26775             break;
26776 
26777          case 6:  // bcdcfz. (Decimal Convert From Zoned VX-form)
26778             {
26779                IRExpr *sign;
26780                IRTemp tmp = newTemp( Ity_V128 );;
26781 
26782                DIP("bcdcfz. v%d,v%d,%d\n", vRT_addr, vRB_addr, ps);
26783 
26784                valid = unop( Iop_1Uto32, is_Zoned_decimal( vB, ps ) );
26785 
26786                assign( tmp,
26787                        convert_from_zoned( vbi, mkexpr( vB ) ) );
26788 
26789                /* If the result of checking the lower 4 bits of each 8-bit
26790                 * value is zero, then the "number" was zero.
26791                 */
26792                zero =
26793                   binop( Iop_CmpEQ64,
26794                   binop( Iop_Or64,
26795                      binop( Iop_And64,
26796                                           unop( Iop_V128to64, mkexpr( vB ) ),
26797                                           mkU64( 0x0F0F0F0F0F0F0F0FULL ) ),
26798                                    binop( Iop_And64,
26799                                           unop( Iop_V128to64, mkexpr( vB ) ),
26800                   mkU64( 0x0F0F0F0F0F0F0F0FULL ) ) ),
26801                   mkU64( 0 ) );
26802 
26803                /* Sign bit is in bit 6 of vB. */
26804                sign_digit = binop( Iop_And64, mkU64( 0xF0 ),
26805                                    unop( Iop_V128to64,  mkexpr( vB ) ) );
26806 
26807                if ( ps == 0 ) {
26808                   /* sign will be equal to 0 for positive number */
26809                   sign = binop( Iop_CmpEQ64,
26810                                 binop( Iop_And64,
26811                                        sign_digit,
26812                                        mkU64( 0x40 ) ),
26813                                 mkU64( 0x40 ) );
26814                } else {
26815                   sign = mkOR1(
26816                                binop( Iop_CmpEQ64, sign_digit, mkU64( 0xB0 ) ),
26817                                binop( Iop_CmpEQ64, sign_digit, mkU64( 0xD0 ) ) );
26818                }
26819 
26820                /* The negative value goes in the LT bit position of the
26821                 * condition code register. Set neg if the sign of the
26822                 * value is negative and the value is zero.
26823                 */
26824                neg = mkAND1( sign, mkNOT1( zero ) );
26825 
26826                /* The positive value goes in the GT bit position of the
26827                 * condition code register. Set neg if the sign of the
26828                 * value is not negative and the value is zero.
26829                 */
26830                pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) );
26831 
26832                /* sign of the result is 0xC for positive, 0xD for negative */
26833                putVReg( vRT_addr,
26834                                binop( Iop_OrV128,
26835                                       mkexpr( tmp ),
26836                                       binop( Iop_64HLtoV128,
26837                                              mkU64( 0 ),
26838                                              binop( Iop_Or64,
26839                                                     mkU64( 0xC ),
26840                                                     unop( Iop_1Uto64, sign )
26841                                                     ) ) ) );
26842                /* For this instructions the LSB position in the CC
26843                 * field, the overflow position in the other instructions,
26844                 * is given by 0.  There is nothing to or with LT, EQ or GT.
26845                 */
26846                overflow = mkU1( 0 );
26847             }
26848             break;
26849 
26850          case 7:  // bcdcfn. (Decimal Convert From National VX-form)
26851             {
26852                IRTemp hword_7 = newTemp( Ity_I64 );
26853                IRExpr *sign;
26854                IRTemp tmp = newTemp( Ity_I64 );;
26855 
26856                DIP("bcdcfn. v%d,v%d,%d\n", vRT_addr, vRB_addr, ps);
26857 
26858                /* check that the value is valid */
26859                valid = unop( Iop_1Uto32, is_National_decimal( vB ) );
26860 
26861                assign( hword_7, binop( Iop_And64,
26862                                        unop( Iop_V128to64, mkexpr( vB ) ),
26863                                        mkU64( 0xFFF ) ) );
26864                /* sign = 1 if vB is negative */
26865                sign = binop( Iop_CmpEQ64, mkexpr( hword_7 ), mkU64( 0x002D ) );
26866 
26867                assign( tmp, convert_from_national( vbi, mkexpr( vB ) ) );
26868 
26869                /* If the result of checking the lower 4 bits of each 16-bit
26870                 * value is zero, then the "number" was zero.
26871                 */
26872                zero =
26873                   binop( Iop_CmpEQ64,
26874                          binop( Iop_Or64,
26875                                 binop( Iop_And64,
26876                                        unop( Iop_V128HIto64, mkexpr( vB ) ),
26877                                        mkU64( 0x000F000F000F000FULL ) ),
26878                                 binop( Iop_And64,
26879                                        unop( Iop_V128to64, mkexpr( vB ) ),
26880                                        mkU64( 0x000F000F000F0000ULL ) ) ),
26881                          mkU64( 0 ) );
26882 
26883 
26884                /* The negative value goes in the LT bit position of the
26885                 * condition code register. Set neg if the sign of the
26886                * value is negative and the value is zero.
26887                 */
26888                neg = mkAND1( sign, mkNOT1( zero ) );
26889 
26890                /* The positive value goes in the GT bit position of the
26891                 * condition code register. Set neg if the sign of the
26892                 * value is not negative and the value is zero.
26893                 */
26894                pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) );
26895 
26896                /* For this instructions the LSB position in the CC
26897                 * field, the overflow position in the other instructions,
26898                 * is given by invalid.  There is nothing to OR with the valid
26899                 * flag.
26900                 */
26901                overflow = mkU1( 0 );
26902 
26903                /* sign of the result is:
26904                   ( 0b1100 OR neg) OR (ps OR  (ps AND pos) << 1 )
26905                */
26906 
26907                putVReg( vRT_addr,
26908                         binop( Iop_64HLtoV128,
26909                                mkU64( 0 ),
26910                                binop( Iop_Or64,
26911                                       binop( Iop_Or64,
26912                                              binop( Iop_Shl64,
26913                                                     binop( Iop_And64,
26914                                                            mkU64( ps ),
26915                                                            unop( Iop_1Uto64,
26916                                                                  mkNOT1(sign))),
26917                                                     mkU8( 1 ) ),
26918                                              mkU64( ps ) ),
26919                                       binop( Iop_Or64,
26920                                              binop( Iop_Or64,
26921                                                     mkU64( 0xC ),
26922                                                     unop( Iop_1Uto64, sign ) ),
26923                                              mkexpr( tmp ) ) ) ) );
26924 
26925             }
26926             break;
26927 
26928          case 31:  // bcdsetsgn. (BCD set sign)
26929             {
26930                IRExpr *new_sign_val, *sign;
26931 
26932                DIP("bcdsetsgn. v%d,v%d,%d\n", vRT_addr, vRB_addr, ps);
26933 
26934                value = binop( Iop_AndV128,
26935                               binop( Iop_64HLtoV128,
26936                                      mkU64( 0xFFFFFFFFFFFFFFFF ),
26937                                      mkU64( 0xFFFFFFFFFFFFFFF0 ) ),
26938                               mkexpr( vB ) );
26939                zero = BCDstring_zero( value );
26940 
26941                /* Sign codes of 0xA, 0xC, 0xE or 0xF are positive, sign
26942                 * codes 0xB and 0xD are negative.
26943                 */
26944                sign_digit = binop( Iop_And64, mkU64( 0xF ),
26945                                    unop( Iop_V128to64, mkexpr( vB ) ) );
26946 
26947                sign = mkOR1( binop( Iop_CmpEQ64,
26948                                     sign_digit,
26949                                     mkU64 ( 0xB ) ),
26950                              binop( Iop_CmpEQ64,
26951                                     sign_digit,
26952                                     mkU64 ( 0xD ) ) );
26953                neg = mkAND1( sign, mkNOT1( zero ) );
26954 
26955                pos = mkAND1( mkNOT1( sign ), mkNOT1( zero ) );
26956 
26957                valid =
26958                   unop( Iop_64to32,
26959                         is_BCDstring128( vbi, /* Signed */True,
26960                                          mkexpr( vB ) ) );
26961 
26962                /* if PS = 0
26963                      vB positive, sign is C
26964                      vB negative, sign is D
26965                   if PS = 1
26966                      vB positive, sign is F
26967                      vB negative, sign is D
26968                   Note can't use pos or neg here since they are ANDed with
26969                   zero, use sign instead.
26970                */
26971                if (ps == 0) {
26972                   new_sign_val = binop( Iop_Or64,
26973                                         unop( Iop_1Uto64, sign ),
26974                                         mkU64( 0xC ) );
26975 
26976                } else {
26977                   new_sign_val = binop( Iop_Xor64,
26978                                         binop( Iop_Shl64,
26979                                                unop( Iop_1Uto64, sign ),
26980                                                mkU8( 1 ) ),
26981                                         mkU64( 0xF ) );
26982                }
26983 
26984                putVReg( vRT_addr, binop( Iop_OrV128,
26985                                          binop( Iop_64HLtoV128,
26986                                                 mkU64( 0 ),
26987                                                 new_sign_val ),
26988                                          value ) );
26989                /* For this instructions the LSB position in the CC
26990                 * field, the overflow position in the other instructions,
26991                 * is given by invalid.
26992                 */
26993                overflow = unop( Iop_32to1, unop( Iop_Not32, valid ) );
26994             }
26995             break;
26996 
26997          default:
26998             vex_printf("dis_av_bcd(ppc)(invalid inst_select)\n");
26999             return False;
27000          }
27001       }
27002       break;
27003 
27004    default:
27005       vex_printf("dis_av_bcd(ppc)(opc2)\n");
27006       return False;
27007    }
27008 
27009    IRTemp valid_mask = newTemp( Ity_I32 );
27010 
27011    assign( valid_mask, unop( Iop_1Sto32, unop( Iop_32to1, valid ) ) );
27012 
27013    /* set CR field 6 to:
27014     *    0b1000  if vB less then 0, i.e. vB is neg and not zero,
27015     *    0b0100  if vB greter then 0,  i.e. vB is pos and not zero,
27016     *    0b0010  if vB equals 0,
27017     *    0b0001  if vB is invalid  over rules lt, gt, eq
27018     */
27019    assign( eq_lt_gt,
27020            binop( Iop_Or32,
27021                   binop( Iop_Shl32,
27022                          unop( Iop_1Uto32, neg ),
27023                          mkU8( 3 ) ),
27024                   binop( Iop_Or32,
27025                          binop( Iop_Shl32,
27026                                 unop( Iop_1Uto32, pos ),
27027                                 mkU8( 2 ) ),
27028                          binop( Iop_Shl32,
27029                                unop( Iop_1Uto32, zero ),
27030                                 mkU8( 1 ) ) ) ) );
27031    /* valid is 1 if it is a valid number, complement and put in the
27032     * invalid bit location, overriding ls, eq, gt, overflow.
27033     */
27034    putGST_field( PPC_GST_CR,
27035                  binop( Iop_Or32,
27036                         binop( Iop_And32,
27037                                mkexpr( valid_mask ),
27038                                binop( Iop_Or32,
27039                                       mkexpr( eq_lt_gt ),
27040                                       unop( Iop_1Uto32, overflow ) ) ),
27041                         binop( Iop_And32,
27042                                unop( Iop_Not32, mkexpr( valid_mask ) ),
27043                                mkU32( 1 ) ) ),
27044                  6 );
27045    return True;
27046 }
27047 
27048 /*
27049   AltiVec Floating Point Arithmetic Instructions
27050 */
dis_av_fp_arith(UInt theInstr)27051 static Bool dis_av_fp_arith ( UInt theInstr )
27052 {
27053    /* VA-Form */
27054    UChar opc1     = ifieldOPC(theInstr);
27055    UChar vD_addr  = ifieldRegDS(theInstr);
27056    UChar vA_addr  = ifieldRegA(theInstr);
27057    UChar vB_addr  = ifieldRegB(theInstr);
27058    UChar vC_addr  = ifieldRegC(theInstr);
27059    UInt  opc2=0;
27060 
27061    IRTemp vA = newTemp(Ity_V128);
27062    IRTemp vB = newTemp(Ity_V128);
27063    IRTemp vC = newTemp(Ity_V128);
27064    assign( vA, getVReg(vA_addr));
27065    assign( vB, getVReg(vB_addr));
27066    assign( vC, getVReg(vC_addr));
27067 
27068    if (opc1 != 0x4) {
27069       vex_printf("dis_av_fp_arith(ppc)(instr)\n");
27070       return False;
27071    }
27072 
27073    IRTemp rm = newTemp(Ity_I32);
27074    assign(rm, get_IR_roundingmode());
27075 
27076    opc2 = IFIELD( theInstr, 0, 6 );
27077    switch (opc2) {
27078    case 0x2E: // vmaddfp (Multiply Add FP, AV p177)
27079       DIP("vmaddfp v%d,v%d,v%d,v%d\n",
27080           vD_addr, vA_addr, vC_addr, vB_addr);
27081       putVReg( vD_addr,
27082                triop(Iop_Add32Fx4, mkU32(Irrm_NEAREST),
27083                      mkexpr(vB),
27084                      triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
27085                            mkexpr(vA), mkexpr(vC))) );
27086       return True;
27087 
27088    case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215)
27089       DIP("vnmsubfp v%d,v%d,v%d,v%d\n",
27090           vD_addr, vA_addr, vC_addr, vB_addr);
27091       putVReg( vD_addr,
27092                triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST),
27093                      mkexpr(vB),
27094                      triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
27095                            mkexpr(vA), mkexpr(vC))) );
27096       return True;
27097    }
27098 
27099    default:
27100      break; // Fall through...
27101    }
27102 
27103    opc2 = IFIELD( theInstr, 0, 11 );
27104    switch (opc2) {
27105    case 0x00A: // vaddfp (Add FP, AV p137)
27106       DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
27107       putVReg( vD_addr, triop(Iop_Add32Fx4,
27108                               mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) );
27109       return True;
27110 
27111   case 0x04A: // vsubfp (Subtract FP, AV p261)
27112       DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
27113       putVReg( vD_addr, triop(Iop_Sub32Fx4,
27114                               mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) );
27115       return True;
27116 
27117    case 0x40A: // vmaxfp (Maximum FP, AV p178)
27118       DIP("vmaxfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
27119       putVReg( vD_addr, binop(Iop_Max32Fx4, mkexpr(vA), mkexpr(vB)) );
27120       return True;
27121 
27122    case 0x44A: // vminfp (Minimum FP, AV p187)
27123       DIP("vminfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
27124       putVReg( vD_addr, binop(Iop_Min32Fx4, mkexpr(vA), mkexpr(vB)) );
27125       return True;
27126 
27127    default:
27128       break; // Fall through...
27129    }
27130 
27131 
27132    if (vA_addr != 0) {
27133       vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n");
27134       return False;
27135    }
27136 
27137    switch (opc2) {
27138    case 0x10A: // vrefp (Reciprocal Esimate FP, AV p228)
27139       DIP("vrefp v%d,v%d\n", vD_addr, vB_addr);
27140       putVReg( vD_addr, unop(Iop_RecipEst32Fx4, mkexpr(vB)) );
27141       return True;
27142 
27143    case 0x14A: // vrsqrtefp (Reciprocal Sqrt Estimate FP, AV p237)
27144       DIP("vrsqrtefp v%d,v%d\n", vD_addr, vB_addr);
27145       putVReg( vD_addr, unop(Iop_RSqrtEst32Fx4, mkexpr(vB)) );
27146       return True;
27147 
27148    case 0x18A: // vexptefp (2 Raised to the Exp Est FP, AV p173)
27149       DIP("vexptefp v%d,v%d\n", vD_addr, vB_addr);
27150       DIP(" => not implemented\n");
27151       return False;
27152 
27153    case 0x1CA: // vlogefp (Log2 Estimate FP, AV p175)
27154       DIP("vlogefp v%d,v%d\n", vD_addr, vB_addr);
27155       DIP(" => not implemented\n");
27156       return False;
27157 
27158    default:
27159       vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2);
27160       return False;
27161    }
27162    return True;
27163 }
27164 
27165 /*
27166   AltiVec Floating Point Compare Instructions
27167 */
dis_av_fp_cmp(UInt theInstr)27168 static Bool dis_av_fp_cmp ( UInt theInstr )
27169 {
27170    /* VXR-Form */
27171    UChar opc1     = ifieldOPC(theInstr);
27172    UChar vD_addr  = ifieldRegDS(theInstr);
27173    UChar vA_addr  = ifieldRegA(theInstr);
27174    UChar vB_addr  = ifieldRegB(theInstr);
27175    UChar flag_rC  = ifieldBIT10(theInstr);
27176    UInt  opc2     = IFIELD( theInstr, 0, 10 );
27177 
27178    Bool cmp_bounds = False;
27179 
27180    IRTemp vA = newTemp(Ity_V128);
27181    IRTemp vB = newTemp(Ity_V128);
27182    IRTemp vD = newTemp(Ity_V128);
27183    assign( vA, getVReg(vA_addr));
27184    assign( vB, getVReg(vB_addr));
27185 
27186    if (opc1 != 0x4) {
27187       vex_printf("dis_av_fp_cmp(ppc)(instr)\n");
27188       return False;
27189    }
27190 
27191    switch (opc2) {
27192    case 0x0C6: // vcmpeqfp (Compare Equal-to FP, AV p159)
27193       DIP("vcmpeqfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
27194                                       vD_addr, vA_addr, vB_addr);
27195       assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
27196       break;
27197 
27198    case 0x1C6: // vcmpgefp (Compare Greater-than-or-Equal-to, AV p163)
27199       DIP("vcmpgefp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
27200                                       vD_addr, vA_addr, vB_addr);
27201       assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
27202       break;
27203 
27204    case 0x2C6: // vcmpgtfp (Compare Greater-than FP, AV p164)
27205       DIP("vcmpgtfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
27206                                       vD_addr, vA_addr, vB_addr);
27207       assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
27208       break;
27209 
27210    case 0x3C6: { // vcmpbfp (Compare Bounds FP, AV p157)
27211       IRTemp gt      = newTemp(Ity_V128);
27212       IRTemp lt      = newTemp(Ity_V128);
27213       IRTemp zeros   = newTemp(Ity_V128);
27214       DIP("vcmpbfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
27215                                      vD_addr, vA_addr, vB_addr);
27216       cmp_bounds = True;
27217       assign( zeros,   unop(Iop_Dup32x4, mkU32(0)) );
27218 
27219       /* Note: making use of fact that the ppc backend for compare insns
27220          return zero'd lanes if either of the corresponding arg lanes is
27221          a nan.
27222 
27223          Perhaps better to have an irop Iop_isNan32Fx4, but then we'd
27224          need this for the other compares too (vcmpeqfp etc)...
27225          Better still, tighten down the spec for compare irops.
27226        */
27227       assign( gt, unop(Iop_NotV128,
27228                        binop(Iop_CmpLE32Fx4, mkexpr(vA), mkexpr(vB))) );
27229       assign( lt, unop(Iop_NotV128,
27230                        binop(Iop_CmpGE32Fx4, mkexpr(vA),
27231                              triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST),
27232                                    mkexpr(zeros),
27233                                    mkexpr(vB)))) );
27234 
27235       // finally, just shift gt,lt to correct position
27236       assign( vD, binop(Iop_ShlN32x4,
27237                         binop(Iop_OrV128,
27238                               binop(Iop_AndV128, mkexpr(gt),
27239                                     unop(Iop_Dup32x4, mkU32(0x2))),
27240                               binop(Iop_AndV128, mkexpr(lt),
27241                                     unop(Iop_Dup32x4, mkU32(0x1)))),
27242                         mkU8(30)) );
27243       break;
27244    }
27245 
27246    default:
27247       vex_printf("dis_av_fp_cmp(ppc)(opc2)\n");
27248       return False;
27249    }
27250 
27251    putVReg( vD_addr, mkexpr(vD) );
27252 
27253    if (flag_rC) {
27254       set_AV_CR6( mkexpr(vD), !cmp_bounds );
27255    }
27256    return True;
27257 }
27258 
27259 /*
27260   AltiVec Floating Point Convert/Round Instructions
27261 */
dis_av_fp_convert(UInt theInstr)27262 static Bool dis_av_fp_convert ( UInt theInstr )
27263 {
27264    /* VX-Form */
27265    UChar opc1     = ifieldOPC(theInstr);
27266    UChar vD_addr  = ifieldRegDS(theInstr);
27267    UChar UIMM_5   = ifieldRegA(theInstr);
27268    UChar vB_addr  = ifieldRegB(theInstr);
27269    UInt  opc2     = IFIELD( theInstr, 0, 11 );
27270 
27271    IRTemp vB        = newTemp(Ity_V128);
27272    IRTemp vScale    = newTemp(Ity_V128);
27273    IRTemp vInvScale = newTemp(Ity_V128);
27274 
27275    float scale, inv_scale;
27276 
27277    assign( vB, getVReg(vB_addr));
27278 
27279    /* scale = 2^UIMM, cast to float, reinterpreted as uint */
27280    scale = (float)( (unsigned int) 1<<UIMM_5 );
27281    assign( vScale, unop(Iop_Dup32x4, mkU32( float_to_bits(scale) )) );
27282    inv_scale = 1/scale;
27283    assign( vInvScale,
27284            unop(Iop_Dup32x4, mkU32( float_to_bits(inv_scale) )) );
27285 
27286    if (opc1 != 0x4) {
27287       vex_printf("dis_av_fp_convert(ppc)(instr)\n");
27288       return False;
27289    }
27290 
27291    switch (opc2) {
27292    case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156)
27293       DIP("vcfux v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
27294       putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
27295                               unop(Iop_I32UtoFx4, mkexpr(vB)),
27296                               mkexpr(vInvScale)) );
27297       return True;
27298 
27299    case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155)
27300       DIP("vcfsx v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
27301 
27302       putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
27303                               unop(Iop_I32StoFx4, mkexpr(vB)),
27304                               mkexpr(vInvScale)) );
27305       return True;
27306 
27307    case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172)
27308       DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
27309       putVReg( vD_addr,
27310                unop(Iop_QFtoI32Ux4_RZ,
27311                     triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
27312                           mkexpr(vB), mkexpr(vScale))) );
27313       return True;
27314 
27315    case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171)
27316       DIP("vctsxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
27317       putVReg( vD_addr,
27318                unop(Iop_QFtoI32Sx4_RZ,
27319                      triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
27320                            mkexpr(vB), mkexpr(vScale))) );
27321       return True;
27322 
27323    default:
27324      break;    // Fall through...
27325    }
27326 
27327    if (UIMM_5 != 0) {
27328       vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n");
27329       return False;
27330    }
27331 
27332    switch (opc2) {
27333    case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231)
27334       DIP("vrfin v%d,v%d\n", vD_addr, vB_addr);
27335       putVReg( vD_addr, unop(Iop_RoundF32x4_RN, mkexpr(vB)) );
27336       break;
27337 
27338    case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233)
27339       DIP("vrfiz v%d,v%d\n", vD_addr, vB_addr);
27340       putVReg( vD_addr, unop(Iop_RoundF32x4_RZ, mkexpr(vB)) );
27341       break;
27342 
27343    case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232)
27344       DIP("vrfip v%d,v%d\n", vD_addr, vB_addr);
27345       putVReg( vD_addr, unop(Iop_RoundF32x4_RP, mkexpr(vB)) );
27346       break;
27347 
27348    case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230)
27349       DIP("vrfim v%d,v%d\n", vD_addr, vB_addr);
27350       putVReg( vD_addr, unop(Iop_RoundF32x4_RM, mkexpr(vB)) );
27351       break;
27352 
27353    default:
27354       vex_printf("dis_av_fp_convert(ppc)(opc2)\n");
27355       return False;
27356    }
27357    return True;
27358 }
27359 
dis_transactional_memory(UInt theInstr,UInt nextInstr,const VexAbiInfo * vbi,DisResult * dres,Bool (* resteerOkFn)(void *,Addr),void * callback_opaque)27360 static Bool dis_transactional_memory ( UInt theInstr, UInt nextInstr,
27361                                        const VexAbiInfo* vbi,
27362                                        /*OUT*/DisResult* dres,
27363                                        Bool (*resteerOkFn)(void*,Addr),
27364                                        void* callback_opaque )
27365 {
27366    UInt   opc2      = IFIELD( theInstr, 1, 10 );
27367 
27368    switch (opc2) {
27369    case 0x28E: {        //tbegin.
27370       /* The current implementation is to just fail the tbegin and execute
27371        * the failure path.  The failure path is assumed to be functionaly
27372        * equivalent to the transactional path with the needed data locking
27373        * to ensure correctness.  The tend is just a noop and shouldn't
27374        * actually get executed.
27375        *   1) set cr0 to 0x2
27376        *   2) Initialize TFHAR to CIA+4
27377        *   3) Initialize TEXASR
27378        *   4) Initialize TFIAR (probably to CIA, ie, the address of tbegin.)
27379        *   5) Continue executing at the next instruction.
27380        */
27381       UInt R = IFIELD( theInstr, 21, 1 );
27382 
27383       ULong tm_reason;
27384       UInt failure_code = 0;  /* Forcing failure, will not be due to tabort
27385                                * or treclaim.
27386                                */
27387       UInt persistant = 1;    /* set persistant since we are always failing
27388                                * the tbegin.
27389                                */
27390       UInt nest_overflow = 1; /* Alowed nesting depth overflow, we use this
27391                                  as the reason for failing the trasaction */
27392       UInt tm_exact   = 1;    /* have exact address for failure */
27393 
27394       DIP("tbegin. %u\n", R);
27395 
27396       /* Set the CR0 field to indicate the tbegin failed.  Then let
27397        * the code do the branch to the failure path.
27398        *
27399        * 000 || 0  Transaction initiation successful,
27400        *           unnested (Transaction state of
27401        *           Non-transactional prior to tbegin.)
27402        * 010 || 0  Transaction initiation successful, nested
27403        *           (Transaction state of Transactional
27404        *           prior to tbegin.)
27405        * 001 || 0  Transaction initiation unsuccessful,
27406        *           (Transaction state of Suspended prior
27407        *           to tbegin.)
27408        */
27409       putCR321( 0, mkU8( 0x2 ) );
27410 
27411       tm_reason = generate_TMreason( failure_code, persistant,
27412                                      nest_overflow, tm_exact );
27413 
27414       storeTMfailure( guest_CIA_curr_instr, tm_reason,
27415                       guest_CIA_curr_instr+4 );
27416 
27417       return True;
27418 
27419       break;
27420    }
27421 
27422    case 0x2AE: {        //tend.
27423       /* The tend. is just a noop.  Do nothing */
27424       UInt A = IFIELD( theInstr, 25, 1 );
27425 
27426       DIP("tend. %u\n", A);
27427       break;
27428    }
27429 
27430    case 0x2EE: {        //tsr.
27431       /* The tsr. is just a noop.  Do nothing */
27432       UInt L = IFIELD( theInstr, 21, 1 );
27433 
27434       DIP("tsr. %u\n", L);
27435       break;
27436    }
27437 
27438    case 0x2CE: {        //tcheck.
27439       /* The tcheck. is just a noop.  Do nothing */
27440       UInt BF = IFIELD( theInstr, 25, 1 );
27441 
27442       DIP("tcheck. %u\n", BF);
27443       break;
27444    }
27445 
27446    case 0x30E: {        //tbortwc.
27447       /* The tabortwc. is just a noop.  Do nothing */
27448       UInt TO = IFIELD( theInstr, 25, 1 );
27449       UInt RA = IFIELD( theInstr, 16, 5 );
27450       UInt RB = IFIELD( theInstr, 11, 5 );
27451 
27452       DIP("tabortwc. %u,%u,%u\n", TO, RA, RB);
27453       break;
27454    }
27455 
27456    case 0x32E: {        //tbortdc.
27457       /* The tabortdc. is just a noop.  Do nothing */
27458       UInt TO = IFIELD( theInstr, 25, 1 );
27459       UInt RA = IFIELD( theInstr, 16, 5 );
27460       UInt RB = IFIELD( theInstr, 11, 5 );
27461 
27462       DIP("tabortdc. %u,%u,%u\n", TO, RA, RB);
27463       break;
27464    }
27465 
27466    case 0x34E: {        //tbortwci.
27467       /* The tabortwci. is just a noop.  Do nothing */
27468       UInt TO = IFIELD( theInstr, 25, 1 );
27469       UInt RA = IFIELD( theInstr, 16, 5 );
27470       UInt SI = IFIELD( theInstr, 11, 5 );
27471 
27472       DIP("tabortwci. %u,%u,%u\n", TO, RA, SI);
27473       break;
27474    }
27475 
27476    case 0x36E: {        //tbortdci.
27477       /* The tabortdci. is just a noop.  Do nothing */
27478       UInt TO = IFIELD( theInstr, 25, 1 );
27479       UInt RA = IFIELD( theInstr, 16, 5 );
27480       UInt SI = IFIELD( theInstr, 11, 5 );
27481 
27482       DIP("tabortdci. %u,%u,%u\n", TO, RA, SI);
27483       break;
27484    }
27485 
27486    case 0x38E: {        //tbort.
27487       /* The tabort. is just a noop.  Do nothing */
27488       UInt RA = IFIELD( theInstr, 16, 5 );
27489 
27490       DIP("tabort. %u\n", RA);
27491       break;
27492    }
27493 
27494    case 0x3AE: {        //treclaim.
27495       /* The treclaim. is just a noop.  Do nothing */
27496       UInt RA = IFIELD( theInstr, 16, 5 );
27497 
27498       DIP("treclaim. %u\n", RA);
27499       break;
27500    }
27501 
27502    case 0x3EE: {        //trechkpt.
27503       /* The trechkpt. is just a noop.  Do nothing */
27504       DIP("trechkpt.\n");
27505       break;
27506    }
27507 
27508    default:
27509       vex_printf("dis_transactional_memory(ppc): unrecognized instruction\n");
27510       return False;
27511    }
27512 
27513    return True;
27514 }
27515 
27516 
27517 /* The 0x3C primary opcode (VSX category) uses several different forms of
27518  * extended opcodes:
27519  *   o XX2-form:
27520  *      - [10:2] (IBM notation [21:29])
27521  *   o XX3-form variants:
27522  *       - variant 1: [10:3] (IBM notation [21:28])
27523  *       - variant 2: [9:3] (IBM notation [22:28])
27524  *       - variant 3: [7:3] (IBM notation [24:28])
27525  *   o XX-4 form:
27526  *      - [10:6] (IBM notation [21:25])
27527  *
27528  * The XX2-form needs bit 0 masked from the standard extended opcode
27529  * as returned by ifieldOPClo10; the XX3-form needs bits 0 and 1 masked;
27530  * and the XX4-form needs bits 0, 1, and 2 masked.  Additionally, the
27531  * XX4 and XX3 (variants 2 and 3) forms need certain bits masked on the
27532  * front end since their encoding does not begin at bit 21 like the standard
27533  * format.
27534  *
27535  * The get_VSX60_opc2() function uses the vsx_insn array below to obtain the
27536  * secondary opcode for such VSX instructions.
27537  *
27538 */
27539 
27540 
27541 struct vsx_insn {
27542    UInt opcode;
27543    const HChar * name;
27544 };
27545 
27546 //  ATTENTION:  Keep this array sorted on the opcocde!!!
27547 static struct vsx_insn vsx_xx2[] = {
27548       { 0x14, "xsrsqrtesp" },
27549       { 0x16, "xssqrtsp" },
27550       { 0x18, "xxsel" },
27551       { 0x34, "xsresp" },
27552       { 0x90, "xscvdpuxws" },
27553       { 0x92, "xsrdpi" },
27554       { 0x94, "xsrsqrtedp" },
27555       { 0x96, "xssqrtdp" },
27556       { 0xb0, "xscvdpsxws" },
27557       { 0xb2, "xsrdpiz" },
27558       { 0xb4, "xsredp" },
27559       { 0xd2, "xsrdpip" },
27560       { 0xd4, "xstsqrtdp" },
27561       { 0xd6, "xsrdpic" },
27562       { 0xf2, "xsrdpim" },
27563       { 0x112, "xvrspi" },
27564       { 0x116, "xvsqrtsp" },
27565       { 0x130, "xvcvspsxws" },
27566       { 0x132, "xvrspiz" },
27567       { 0x134, "xvresp" },
27568       { 0x148, "xxspltw" },
27569       { 0x14A, "xxextractuw" },
27570       { 0x150, "xvcvuxwsp" },
27571       { 0x152, "xvrspip" },
27572       { 0x154, "xvtsqrtsp" },
27573       { 0x156, "xvrspic" },
27574       { 0x16A, "xxinsertw" },
27575       { 0x170, "xvcvsxwsp" },
27576       { 0x172, "xvrspim" },
27577       { 0x190, "xvcvdpuxws" },
27578       { 0x192, "xvrdpi" },
27579       { 0x194, "xvrsqrtedp" },
27580       { 0x196, "xvsqrtdp" },
27581       { 0x1b0, "xvcvdpsxws" },
27582       { 0x1b2, "xvrdpiz" },
27583       { 0x1b4, "xvredp" },
27584       { 0x1d0, "xvcvuxwdp" },
27585       { 0x1d2, "xvrdpip" },
27586       { 0x1d4, "xvtsqrtdp" },
27587       { 0x1d6, "xvrdpic" },
27588       { 0x1f0, "xvcvsxwdp" },
27589       { 0x1f2, "xvrdpim" },
27590       { 0x212, "xscvdpsp" },
27591       { 0x216, "xscvdpspn" },
27592       { 0x232, "xxrsp" },
27593       { 0x250, "xscvuxdsp" },
27594       { 0x254, "xststdcsp" },
27595       { 0x270, "xscvsxdsp" },
27596       { 0x290, "xscvdpuxds" },
27597       { 0x292, "xscvspdp" },
27598       { 0x296, "xscvspdpn" },
27599       { 0x2b0, "xscvdpsxds" },
27600       { 0x2b2, "xsabsdp" },
27601       { 0x2b6, "xsxexpdp_xsxigdp" },
27602       { 0x2d0, "xscvuxddp" },
27603       { 0x2d2, "xsnabsdp" },
27604       { 0x2d4, "xststdcdp" },
27605       { 0x2e4, "xsnmsubmdp" },
27606       { 0x2f0, "xscvsxddp" },
27607       { 0x2f2, "xsnegdp" },
27608       { 0x310, "xvcvspuxds" },
27609       { 0x312, "xvcvdpsp" },
27610       { 0x330, "xvcvspsxds" },
27611       { 0x332, "xvabssp" },
27612       { 0x350, "xvcvuxdsp" },
27613       { 0x352, "xvnabssp" },
27614       { 0x370, "xvcvsxdsp" },
27615       { 0x372, "xvnegsp" },
27616       { 0x390, "xvcvdpuxds" },
27617       { 0x392, "xvcvspdp" },
27618       { 0x3b0, "xvcvdpsxds" },
27619       { 0x3b2, "xvabsdp" },
27620       { 0x3b6, "xxbr[h|w|d|q]|xvxexpdp|xvxexpsp|xvxsigdp|xvxsigsp|xvcvhpsp|xvcvsphp|xscvdphp|xscvhpdp" },
27621       { 0x3d0, "xvcvuxddp" },
27622       { 0x3d2, "xvnabsdp" },
27623       { 0x3f2, "xvnegdp" }
27624 };
27625 #define VSX_XX2_LEN (sizeof vsx_xx2 / sizeof *vsx_xx2)
27626 
27627 //  ATTENTION:  Keep this array sorted on the opcocde!!!
27628 static struct vsx_insn vsx_xx3[] = {
27629       { 0x0,  "xsaddsp" },
27630       { 0x4,  "xsmaddasp" },
27631       { 0x9,  "xsmaddmsp" },
27632       { 0xC,  "xscmpeqdp" },
27633       { 0x20, "xssubsp" },
27634       { 0x24, "xsmaddmsp" },
27635       { 0x2C, "xscmpgtdp" },
27636       { 0x3A, "xxpermr" },
27637       { 0x40, "xsmulsp" },
27638       { 0x44, "xsmsubasp" },
27639       { 0x48, "xxmrghw" },
27640       { 0x4C, "xscmpgedp" },
27641       { 0x60, "xsdivsp" },
27642       { 0x64, "xsmsubmsp" },
27643       { 0x68, "xxperm" },
27644       { 0x80, "xsadddp" },
27645       { 0x84, "xsmaddadp" },
27646       { 0x8c, "xscmpudp" },
27647       { 0xa0, "xssubdp" },
27648       { 0xa4, "xsmaddmdp" },
27649       { 0xac, "xscmpodp" },
27650       { 0xc0, "xsmuldp" },
27651       { 0xc4, "xsmsubadp" },
27652       { 0xc8, "xxmrglw" },
27653       { 0xd4, "xstsqrtdp" },
27654       { 0xe0, "xsdivdp" },
27655       { 0xe4, "xsmsubmdp" },
27656       { 0xe8, "xxpermr" },
27657       { 0xeC, "xscmpexpdp" },
27658       { 0xf4, "xstdivdp" },
27659       { 0x100, "xvaddsp" },
27660       { 0x104, "xvmaddasp" },
27661       { 0x10C, "xvcmpeqsp" },
27662       { 0x110, "xvcvspuxws" },
27663       { 0x114, "xvrsqrtesp" },
27664       { 0x120, "xvsubsp" },
27665       { 0x124, "xvmaddmsp" },
27666       { 0x130, "xvcvspsxws" },
27667       { 0x140, "xvmulsp" },
27668       { 0x144, "xvmsubasp" },
27669       { 0x14C, "xvcmpgesp", },
27670       { 0x160, "xvdivsp" },
27671       { 0x164, "xvmsubmsp" },
27672       { 0x174, "xvtdivsp" },
27673       { 0x180, "xvadddp" },
27674       { 0x184, "xvmaddadp" },
27675       { 0x18C, "xvcmpeqdp" },
27676       { 0x1a0, "xvsubdp" },
27677       { 0x1a4, "xvmaddmdp" },
27678       { 0x1aC, "xvcmpgtdp" },
27679       { 0x1c0, "xvmuldp" },
27680       { 0x1c4, "xvmsubadp" },
27681       { 0x1cc, "xvcmpgedp" },
27682       { 0x1e0, "xvdivdp" },
27683       { 0x1e4, "xvmsubmdp" },
27684       { 0x1f4, "xvtdivdp" },
27685       { 0x200, "xsmaxcdp" },
27686       { 0x204, "xsnmaddasp" },
27687       { 0x208, "xxland" },
27688       { 0x220, "xsmincdp" },
27689       { 0x224, "xsnmaddmsp" },
27690       { 0x228, "xxlandc" },
27691       { 0x244, "xsnmsubasp" },
27692       { 0x248, "xxlor" },
27693       { 0x264, "xsnmsubmsp" },
27694       { 0x268, "xxlxor" },
27695       { 0x280, "xsmaxdp" },
27696       { 0x284, "xsnmaddadp" },
27697       { 0x288, "xxlnor" },
27698       { 0x2a0, "xsmindp" },
27699       { 0x2a4, "xsnmaddmdp" },
27700       { 0x2a8, "xxlorc" },
27701       { 0x2c0, "xscpsgndp" },
27702       { 0x2c4, "xsnmsubadp" },
27703       { 0x2c8, "xxlnand" },
27704       { 0x2e4, "xsnmsubmdp" },
27705       { 0x2e8, "xxleqv" },
27706       { 0x300, "xvmaxsp" },
27707       { 0x304, "xvnmaddasp" },
27708       { 0x320, "xvminsp" },
27709       { 0x324, "xvnmaddmsp" },
27710       { 0x340, "xvcpsgnsp" },
27711       { 0x344, "xvnmsubasp" },
27712       { 0x360, "xviexpsp" },
27713       { 0x364, "xvnmsubmsp" },
27714       { 0x380, "xvmaxdp" },
27715       { 0x384, "xvnmaddadp" },
27716       { 0x3a0, "xvmindp" },
27717       { 0x3a4, "xvnmaddmdp" },
27718       { 0x3c0, "xvcpsgndp" },
27719       { 0x3c4, "xvnmsubadp" },
27720       { 0x3e0, "xviexpdp" },
27721       { 0x3e4, "xvnmsubmdp" },
27722       { 0x3f0, "xvcvsxddp" },
27723 };
27724 #define VSX_XX3_LEN (sizeof vsx_xx3 / sizeof *vsx_xx3)
27725 
27726 
27727 /* ATTENTION: These search functions assumes vsx_xx2 and vsx_xx3 arrays
27728  * are sorted.
27729  */
findVSXextOpCode_xx2(UInt opcode)27730 static Int findVSXextOpCode_xx2(UInt opcode)
27731 {
27732    Int low, mid, high;
27733    low = 0;
27734    high = VSX_XX2_LEN - 1;
27735    while (low <= high) {
27736       mid = (low + high)/2;
27737       if (opcode < vsx_xx2[mid].opcode)
27738          high = mid - 1;
27739       else if (opcode > vsx_xx2[mid].opcode)
27740          low = mid + 1;
27741       else
27742          return mid;
27743    }
27744    return -1;
27745 }
27746 
findVSXextOpCode_xx3(UInt opcode)27747 static Int findVSXextOpCode_xx3(UInt opcode)
27748 {
27749    Int low, mid, high;
27750    low = 0;
27751    high = VSX_XX3_LEN - 1;
27752    while (low <= high) {
27753       mid = (low + high)/2;
27754       if (opcode < vsx_xx3[mid].opcode)
27755          high = mid - 1;
27756       else if (opcode > vsx_xx3[mid].opcode)
27757          low = mid + 1;
27758       else
27759          return mid;
27760    }
27761    return -1;
27762 }
27763 
27764 
27765 /* The full 10-bit extended opcode retrieved via ifieldOPClo10 is
27766  * passed, and we then try to match it up with one of the VSX forms
27767  * below.
27768  */
get_VSX60_opc2(UInt opc2_full,UInt theInstr)27769 static UInt get_VSX60_opc2(UInt opc2_full, UInt theInstr)
27770 {
27771 #define XX2_1_MASK 0x000003FF    // xsiexpdp specific
27772 #define XX2_2_MASK 0x000003FE
27773 #define XX3_1_MASK 0x000003FC
27774 #define XX3_2_MASK 0x000001FC
27775 #define XX3_4_MASK 0x0000027C
27776 #define XX3_5_MASK 0x000003DC
27777 #define XX4_MASK   0x00000018
27778 
27779    Int ret;
27780    UInt vsxExtOpcode = 0;
27781 
27782    if (( ret = findVSXextOpCode_xx2(opc2_full & XX2_2_MASK)) >= 0)
27783       return vsx_xx2[ret].opcode;
27784    else if ((opc2_full & XX2_1_MASK) == 0x396 )   // xsiexpdp
27785       return 0x396;
27786    else if (( ret = findVSXextOpCode_xx3(opc2_full & XX3_1_MASK)) >= 0)
27787       return vsx_xx3[ret].opcode;
27788    else {
27789 
27790       /* There are only a few codes in each of these cases it is
27791        * probably faster to check for the codes then do the array lookups.
27792        */
27793       vsxExtOpcode = opc2_full & XX3_2_MASK;
27794 
27795       switch (vsxExtOpcode) {
27796       case 0x10C: return vsxExtOpcode;   // xvcmpeqsp
27797       case 0x12C: return vsxExtOpcode;   // xvcmpgtsp, xvcmpgtsp.
27798       case 0x14C: return vsxExtOpcode;   // xvcmpgesp, xvcmpgesp.
27799       case 0x18C: return vsxExtOpcode;   // xvcmpeqdp, xvcmpeqdp.
27800       case 0x1AC: return vsxExtOpcode;   // xvcmpgtdp, xvcmpgtdp.
27801       case 0x1CC: return vsxExtOpcode;   // xvcmpgedp, xvcmpgedp.
27802       default:  break;
27803       }
27804 
27805       vsxExtOpcode = opc2_full & XX3_4_MASK;
27806 
27807       switch (vsxExtOpcode) {
27808       case 0x8:   return vsxExtOpcode;   // xxsldwi
27809       case 0x28:  return vsxExtOpcode;   // xxpermdi
27810       default:  break;
27811       }
27812 
27813       vsxExtOpcode = opc2_full & XX3_5_MASK;
27814 
27815       switch (vsxExtOpcode) {
27816       case 0x354:  return vsxExtOpcode;   // xvtstdcsp
27817       case 0x3D4:  return vsxExtOpcode;   // xvtstdcdp
27818       default:  break;
27819       }
27820 
27821       if (( opc2_full & XX4_MASK ) == XX4_MASK ) {   // xxsel
27822          vsxExtOpcode = 0x18;
27823          return vsxExtOpcode;
27824       }
27825    }
27826 
27827    vex_printf( "Error: undefined opcode 0x %x, the instruction = 0x %x\n",
27828                opc2_full, theInstr );
27829    vpanic( "ERROR: get_VSX60_opc2()\n" );
27830    return 0;
27831 }
27832 
27833 /*------------------------------------------------------------*/
27834 /*--- Disassemble a single instruction                     ---*/
27835 /*------------------------------------------------------------*/
27836 
27837 /* Disassemble a single instruction into IR.  The instruction
27838    is located in host memory at &guest_code[delta]. */
27839 
27840 static
disInstr_PPC_WRK(Bool (* resteerOkFn)(void *,Addr),Bool resteerCisOk,void * callback_opaque,Long delta64,const VexArchInfo * archinfo,const VexAbiInfo * abiinfo,Bool sigill_diag)27841 DisResult disInstr_PPC_WRK (
27842              Bool         (*resteerOkFn) ( /*opaque*/void*, Addr ),
27843              Bool         resteerCisOk,
27844              void*        callback_opaque,
27845              Long         delta64,
27846              const VexArchInfo* archinfo,
27847              const VexAbiInfo*  abiinfo,
27848              Bool         sigill_diag
27849           )
27850 {
27851    UChar     opc1;
27852    UInt      opc2;
27853    DisResult dres;
27854    UInt      theInstr;
27855    IRType    ty = mode64 ? Ity_I64 : Ity_I32;
27856    UInt      hwcaps = archinfo->hwcaps;
27857    Long      delta;
27858    Bool      allow_F  = False;
27859    Bool      allow_V  = False;
27860    Bool      allow_FX = False;
27861    Bool      allow_GX = False;
27862    Bool      allow_VX = False;  // Equates to "supports Power ISA 2.06
27863    Bool      allow_DFP = False;
27864    Bool      allow_isa_2_07 = False;
27865    Bool      allow_isa_3_0  = False;
27866 
27867    /* What insn variants are we supporting today? */
27868    if (mode64) {
27869       allow_F  = True;
27870       allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC64_V));
27871       allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC64_FX));
27872       allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC64_GX));
27873       allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC64_VX));
27874       allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC64_DFP));
27875       allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC64_ISA2_07));
27876       allow_isa_3_0  = (0 != (hwcaps & VEX_HWCAPS_PPC64_ISA3_0));
27877    } else {
27878       allow_F  = (0 != (hwcaps & VEX_HWCAPS_PPC32_F));
27879       allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC32_V));
27880       allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC32_FX));
27881       allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC32_GX));
27882       allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC32_VX));
27883       allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC32_DFP));
27884       allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC32_ISA2_07));
27885       allow_isa_3_0  = (0 != (hwcaps & VEX_HWCAPS_PPC32_ISA3_0));
27886    }
27887 
27888    /* Enable writting the OV32 and CA32 bits added with ISA3.0 */
27889    OV32_CA32_supported = allow_isa_3_0;
27890 
27891    /* The running delta */
27892    delta = (Long)mkSzAddr(ty, (ULong)delta64);
27893 
27894    /* Set result defaults. */
27895    dres.whatNext    = Dis_Continue;
27896    dres.len         = 0;
27897    dres.continueAt  = 0;
27898    dres.jk_StopHere = Ijk_INVALID;
27899    dres.hint        = Dis_HintNone;
27900 
27901    /* At least this is simple on PPC32: insns are all 4 bytes long, and
27902       4-aligned.  So just fish the whole thing out of memory right now
27903       and have done. */
27904    theInstr = getUIntPPCendianly( &guest_code[delta] );
27905 
27906    if (0) vex_printf("insn: 0x%x\n", theInstr);
27907 
27908    DIP("\t0x%llx:  ", (ULong)guest_CIA_curr_instr);
27909 
27910    /* Spot "Special" instructions (see comment at top of file). */
27911    {
27912       const UChar* code = guest_code + delta;
27913       /* Spot the 16-byte preamble:
27914          32-bit mode:
27915             5400183E  rlwinm 0,0,3,0,31
27916             5400683E  rlwinm 0,0,13,0,31
27917             5400E83E  rlwinm 0,0,29,0,31
27918             5400983E  rlwinm 0,0,19,0,31
27919          64-bit mode:
27920             78001800  rotldi 0,0,3
27921             78006800  rotldi 0,0,13
27922             7800E802  rotldi 0,0,61
27923             78009802  rotldi 0,0,51
27924       */
27925       UInt word1 = mode64 ? 0x78001800 : 0x5400183E;
27926       UInt word2 = mode64 ? 0x78006800 : 0x5400683E;
27927       UInt word3 = mode64 ? 0x7800E802 : 0x5400E83E;
27928       UInt word4 = mode64 ? 0x78009802 : 0x5400983E;
27929       Bool is_special_preamble = False;
27930       if (getUIntPPCendianly(code+ 0) == word1 &&
27931           getUIntPPCendianly(code+ 4) == word2 &&
27932           getUIntPPCendianly(code+ 8) == word3 &&
27933           getUIntPPCendianly(code+12) == word4) {
27934          is_special_preamble = True;
27935       } else if (! mode64 &&
27936                  getUIntPPCendianly(code+ 0) == 0x54001800 &&
27937                  getUIntPPCendianly(code+ 4) == 0x54006800 &&
27938                  getUIntPPCendianly(code+ 8) == 0x5400E800 &&
27939                  getUIntPPCendianly(code+12) == 0x54009800) {
27940          static Bool reported = False;
27941          if (!reported) {
27942             vex_printf("disInstr(ppc): old ppc32 instruction magic detected. Code might clobber r0.\n");
27943             vex_printf("disInstr(ppc): source needs to be recompiled against latest valgrind.h.\n");
27944             reported = True;
27945          }
27946          is_special_preamble = True;
27947       }
27948       if (is_special_preamble) {
27949          /* Got a "Special" instruction preamble.  Which one is it? */
27950          if (getUIntPPCendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) {
27951             /* %R3 = client_request ( %R4 ) */
27952             DIP("r3 = client_request ( %%r4 )\n");
27953             delta += 20;
27954             putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta ));
27955             dres.jk_StopHere = Ijk_ClientReq;
27956             dres.whatNext    = Dis_StopHere;
27957             goto decode_success;
27958          }
27959          else
27960          if (getUIntPPCendianly(code+16) == 0x7C421378 /* or 2,2,2 */) {
27961             /* %R3 = guest_NRADDR */
27962             DIP("r3 = guest_NRADDR\n");
27963             delta += 20;
27964             dres.len = 20;
27965             putIReg(3, IRExpr_Get( OFFB_NRADDR, ty ));
27966             goto decode_success;
27967          }
27968          else
27969          if (getUIntPPCendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) {
27970             delta += 20;
27971             if (host_endness == VexEndnessLE) {
27972                 /*  branch-and-link-to-noredir %R12 */
27973                 DIP("branch-and-link-to-noredir r12\n");
27974                 putGST( PPC_GST_LR,
27975                         mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
27976                 putGST( PPC_GST_CIA, getIReg(12));
27977             } else {
27978                 /*  branch-and-link-to-noredir %R11 */
27979                 DIP("branch-and-link-to-noredir r11\n");
27980                 putGST( PPC_GST_LR,
27981                         mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
27982                 putGST( PPC_GST_CIA, getIReg(11));
27983             }
27984             dres.jk_StopHere = Ijk_NoRedir;
27985             dres.whatNext    = Dis_StopHere;
27986             goto decode_success;
27987          }
27988          else
27989          if (getUIntPPCendianly(code+16) == 0x7C842378 /* or 4,4,4 */) {
27990             /* %R3 = guest_NRADDR_GPR2 */
27991             DIP("r3 = guest_NRADDR_GPR2\n");
27992             delta += 20;
27993             dres.len = 20;
27994             putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty ));
27995             goto decode_success;
27996          }
27997          else
27998          if (getUIntPPCendianly(code+16) == 0x7CA52B78 /* or 5,5,5 */) {
27999             DIP("IR injection\n");
28000             if (host_endness == VexEndnessBE)
28001                vex_inject_ir(irsb, Iend_BE);
28002             else
28003                vex_inject_ir(irsb, Iend_LE);
28004 
28005             delta += 20;
28006             dres.len = 20;
28007 
28008             // Invalidate the current insn. The reason is that the IRop we're
28009             // injecting here can change. In which case the translation has to
28010             // be redone. For ease of handling, we simply invalidate all the
28011             // time.
28012 
28013             stmt(IRStmt_Put(OFFB_CMSTART, mkSzImm(ty, guest_CIA_curr_instr)));
28014             stmt(IRStmt_Put(OFFB_CMLEN,   mkSzImm(ty, 20)));
28015 
28016             putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta ));
28017             dres.whatNext    = Dis_StopHere;
28018             dres.jk_StopHere = Ijk_InvalICache;
28019             goto decode_success;
28020          }
28021          /* We don't know what it is.  Set opc1/opc2 so decode_failure
28022             can print the insn following the Special-insn preamble. */
28023          theInstr = getUIntPPCendianly(code+16);
28024          opc1     = ifieldOPC(theInstr);
28025          opc2     = ifieldOPClo10(theInstr);
28026          goto decode_failure;
28027          /*NOTREACHED*/
28028       }
28029    }
28030 
28031    opc1 = ifieldOPC(theInstr);
28032    opc2 = ifieldOPClo10(theInstr);
28033 
28034    // Note: all 'reserved' bits must be cleared, else invalid
28035    switch (opc1) {
28036 
28037    /* Integer Arithmetic Instructions */
28038    case 0x0C: case 0x0D: case 0x0E:  // addic, addic., addi
28039    case 0x0F: case 0x07: case 0x08:  // addis, mulli,  subfic
28040       if (dis_int_arith( theInstr )) goto decode_success;
28041       goto decode_failure;
28042 
28043    /* Integer Compare Instructions */
28044    case 0x0B: case 0x0A: // cmpi, cmpli
28045       if (dis_int_cmp( theInstr )) goto decode_success;
28046       goto decode_failure;
28047 
28048    /* Integer Logical Instructions */
28049    case 0x1C: case 0x1D: case 0x18: // andi., andis., ori
28050    case 0x19: case 0x1A: case 0x1B: // oris,  xori,   xoris
28051       if (dis_int_logic( theInstr )) goto decode_success;
28052       goto decode_failure;
28053 
28054    /* Integer Rotate Instructions */
28055    case 0x14: case 0x15:  case 0x17: // rlwimi, rlwinm, rlwnm
28056       if (dis_int_rot( theInstr )) goto decode_success;
28057       goto decode_failure;
28058 
28059    /* 64bit Integer Rotate Instructions */
28060    case 0x1E: // rldcl, rldcr, rldic, rldicl, rldicr, rldimi
28061       if (!mode64) goto decode_failure;
28062       if (dis_int_rot( theInstr )) goto decode_success;
28063       goto decode_failure;
28064 
28065    /* Integer Load Instructions */
28066    case 0x22: case 0x23: case 0x2A: // lbz,  lbzu, lha
28067    case 0x2B: case 0x28: case 0x29: // lhau, lhz,  lhzu
28068    case 0x20: case 0x21:            // lwz,  lwzu
28069       if (dis_int_load( theInstr )) goto decode_success;
28070       goto decode_failure;
28071 
28072    /* Integer Store Instructions */
28073    case 0x26: case 0x27: case 0x2C: // stb,  stbu, sth
28074    case 0x2D: case 0x24: case 0x25: // sthu, stw,  stwu
28075       if (dis_int_store( theInstr, abiinfo )) goto decode_success;
28076       goto decode_failure;
28077 
28078    /* Integer Load and Store Multiple Instructions */
28079    case 0x2E: case 0x2F: // lmw, stmw
28080       if (dis_int_ldst_mult( theInstr )) goto decode_success;
28081       goto decode_failure;
28082 
28083    /* Branch Instructions */
28084    case 0x12: case 0x10: // b, bc
28085       if (dis_branch(theInstr, abiinfo, &dres,
28086                                resteerOkFn, callback_opaque))
28087          goto decode_success;
28088       goto decode_failure;
28089 
28090    /* System Linkage Instructions */
28091    case 0x11: // sc
28092       if (dis_syslink(theInstr, abiinfo, &dres)) goto decode_success;
28093       goto decode_failure;
28094 
28095    /* Trap Instructions */
28096    case 0x02:    // tdi
28097       if (!mode64) goto decode_failure;
28098       if (dis_trapi(theInstr, &dres)) goto decode_success;
28099       goto decode_failure;
28100 
28101    case 0x03:   // twi
28102       if (dis_trapi(theInstr, &dres)) goto decode_success;
28103       goto decode_failure;
28104 
28105    /* Floating Point Load Instructions */
28106    case 0x30: case 0x31: case 0x32: // lfs, lfsu, lfd
28107    case 0x33:                       // lfdu
28108       if (!allow_F) goto decode_noF;
28109       if (dis_fp_load( theInstr )) goto decode_success;
28110       goto decode_failure;
28111 
28112    /* Floating Point Store Instructions */
28113    case 0x34: case 0x35: case 0x36: // stfsx, stfsux, stfdx
28114    case 0x37:                       // stfdux
28115       if (!allow_F) goto decode_noF;
28116       if (dis_fp_store( theInstr )) goto decode_success;
28117       goto decode_failure;
28118 
28119       /* Floating Point Load Double Pair Instructions */
28120    case 0x39: case 0x3D:    // lfdp, lxsd, lxssp, lxv
28121                             // stfdp, stxsd, stxssp, stxv
28122       if (!allow_F) goto decode_noF;
28123       if (dis_fp_pair( theInstr )) goto decode_success;
28124       goto decode_failure;
28125 
28126    /* 128-bit Integer Load */
28127    case 0x38:  // lq
28128       if (dis_int_load( theInstr )) goto decode_success;
28129       goto decode_failure;
28130 
28131    /* 64bit Integer Loads */
28132    case 0x3A:  // ld, ldu, lwa
28133       if (!mode64) goto decode_failure;
28134       if (dis_int_load( theInstr )) goto decode_success;
28135       goto decode_failure;
28136 
28137    case 0x3B:
28138       if (!allow_F) goto decode_noF;
28139       opc2 = ifieldOPClo10(theInstr);
28140 
28141       switch (opc2) {
28142          case 0x2:    // dadd - DFP Add
28143          case 0x202:  // dsub - DFP Subtract
28144          case 0x22:   // dmul - DFP Mult
28145          case 0x222:  // ddiv - DFP Divide
28146             if (!allow_DFP) goto decode_noDFP;
28147             if (dis_dfp_arith( theInstr ))
28148                goto decode_success;
28149          case 0x82:   // dcmpo, DFP comparison ordered instruction
28150          case 0x282:  // dcmpu, DFP comparison unordered instruction
28151             if (!allow_DFP) goto decode_noDFP;
28152             if (dis_dfp_compare( theInstr ) )
28153                goto decode_success;
28154             goto decode_failure;
28155          case 0x102: // dctdp  - DFP convert to DFP long
28156          case 0x302: // drsp   - DFP round to dfp short
28157          case 0x122: // dctfix - DFP convert to fixed
28158             if (!allow_DFP) goto decode_noDFP;
28159             if (dis_dfp_fmt_conv( theInstr ))
28160                goto decode_success;
28161             goto decode_failure;
28162          case 0x322: // POWER 7 inst, dcffix - DFP convert from fixed
28163             if (!allow_VX)
28164                goto decode_failure;
28165             if (!allow_DFP) goto decode_noDFP;
28166             if (dis_dfp_fmt_conv( theInstr ))
28167                goto decode_success;
28168             goto decode_failure;
28169          case 0x2A2: // dtstsf  - DFP number of significant digits
28170          case 0x2A3: // dtstsfi - DFP number of significant digits Immediate
28171             if (!allow_DFP) goto decode_noDFP;
28172             if (dis_dfp_significant_digits(theInstr))
28173                goto decode_success;
28174             goto decode_failure;
28175          case 0x142: // ddedpd   DFP Decode DPD to BCD
28176          case 0x342: // denbcd   DFP Encode BCD to DPD
28177             if (!allow_DFP) goto decode_noDFP;
28178             if (dis_dfp_bcd(theInstr))
28179                goto decode_success;
28180             goto decode_failure;
28181          case 0x162:  // dxex - Extract exponent
28182          case 0x362:  // diex - Insert exponent
28183             if (!allow_DFP) goto decode_noDFP;
28184             if (dis_dfp_extract_insert( theInstr ) )
28185                goto decode_success;
28186             goto decode_failure;
28187          case 0x3CE: // fcfidus (implemented as native insn)
28188             if (!allow_VX)
28189                goto decode_noVX;
28190             if (dis_fp_round( theInstr ))
28191                goto decode_success;
28192             goto decode_failure;
28193          case 0x34E: // fcfids
28194             if (dis_fp_round( theInstr ))
28195                goto decode_success;
28196             goto decode_failure;
28197       }
28198 
28199       opc2 = ifieldOPClo9( theInstr );
28200       switch (opc2) {
28201       case 0x42: // dscli, DFP shift left
28202       case 0x62: // dscri, DFP shift right
28203          if (!allow_DFP) goto decode_noDFP;
28204          if (dis_dfp_shift( theInstr ))
28205             goto decode_success;
28206          goto decode_failure;
28207       case 0xc2:  // dtstdc, DFP test data class
28208       case 0xe2:  // dtstdg, DFP test data group
28209          if (!allow_DFP) goto decode_noDFP;
28210          if (dis_dfp_class_test( theInstr ))
28211             goto decode_success;
28212          goto decode_failure;
28213       }
28214 
28215       opc2 = ifieldOPClo8( theInstr );
28216       switch (opc2) {
28217       case 0x3:   // dqua  - DFP Quantize
28218       case 0x23:  // drrnd - DFP Reround
28219       case 0x43:  // dquai - DFP Quantize immediate
28220          if (!allow_DFP) goto decode_noDFP;
28221          if (dis_dfp_quantize_sig_rrnd( theInstr ) )
28222             goto decode_success;
28223          goto decode_failure;
28224       case 0xA2: // dtstex - DFP Test exponent
28225          if (!allow_DFP) goto decode_noDFP;
28226          if (dis_dfp_exponent_test( theInstr ) )
28227             goto decode_success;
28228          goto decode_failure;
28229       case 0x63: // drintx - Round to an integer value
28230       case 0xE3: // drintn - Round to an integer value
28231          if (!allow_DFP) goto decode_noDFP;
28232          if (dis_dfp_round( theInstr ) ) {
28233             goto decode_success;
28234          }
28235          goto decode_failure;
28236       default:
28237          break;  /* fall through to next opc2 check */
28238       }
28239 
28240       opc2 = IFIELD(theInstr, 1, 5);
28241       switch (opc2) {
28242       /* Floating Point Arith Instructions */
28243       case 0x12: case 0x14: case 0x15: // fdivs,  fsubs, fadds
28244       case 0x19:                       // fmuls
28245          if (dis_fp_arith(theInstr)) goto decode_success;
28246          goto decode_failure;
28247       case 0x16:                       // fsqrts
28248          if (!allow_FX) goto decode_noFX;
28249          if (dis_fp_arith(theInstr)) goto decode_success;
28250          goto decode_failure;
28251       case 0x18:                       // fres
28252          if (!allow_GX) goto decode_noGX;
28253          if (dis_fp_arith(theInstr)) goto decode_success;
28254          goto decode_failure;
28255 
28256       /* Floating Point Mult-Add Instructions */
28257       case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs
28258       case 0x1F:                       // fnmadds
28259          if (dis_fp_multadd(theInstr)) goto decode_success;
28260          goto decode_failure;
28261 
28262       case 0x1A:                       // frsqrtes
28263          if (!allow_GX) goto decode_noGX;
28264          if (dis_fp_arith(theInstr)) goto decode_success;
28265          goto decode_failure;
28266 
28267       default:
28268          goto decode_failure;
28269       }
28270       break;
28271 
28272    case 0x3C: // VSX instructions (except load/store)
28273    {
28274       // All of these VSX instructions use some VMX facilities, so
28275       // if allow_V is not set, we'll skip trying to decode.
28276       if (!allow_V) goto decode_noVX;
28277       /* The xvtstdcdp and xvtstdcsp instructions do not have a
28278          contiguous opc2 field.  The following vsxOpc2 = get_VSX60_opc2()
28279          doesn't correctly match these instructions for dc != 0.  So,
28280          we will explicitly look for the two instructions. */
28281       opc2 = ifieldOPClo10(theInstr);
28282       UInt opc2hi = IFIELD(theInstr, 7, 4);
28283       UInt opc2lo = IFIELD(theInstr, 3, 3);
28284       UInt vsxOpc2;
28285 
28286       if (( opc2hi == 13 ) && ( opc2lo == 5)) { //xvtstdcsp
28287          if (dis_vxs_misc(theInstr, abiinfo, 0x354, allow_isa_3_0))
28288             goto decode_success;
28289          goto decode_failure;
28290       }
28291 
28292       if (( opc2hi == 15 ) && ( opc2lo == 5)) { //xvtstdcdp
28293          if (dis_vxs_misc(theInstr, abiinfo, 0x3D4, allow_isa_3_0))
28294                goto decode_success;
28295             goto decode_failure;
28296       }
28297 
28298       /* The vsxOpc2 returned is the "normalized" value, representing the
28299        * instructions secondary opcode as taken from the standard secondary
28300        * opcode field [21:30] (IBM notatition), even if the actual field
28301        * is non-standard.  These normalized values are given in the opcode
28302        * appendices of the ISA 2.06 document.
28303        */
28304       if ( ( opc2 == 0x168 ) && ( IFIELD( theInstr, 19, 2 ) == 0 ) )// xxspltib
28305       {
28306          /* This is a special case of the XX1 form where the  RA, RB
28307           * fields hold an immediate value.
28308           */
28309       if (dis_vxs_misc(theInstr, abiinfo, opc2, allow_isa_3_0)) goto decode_success;
28310          goto decode_failure;
28311       }
28312 
28313       vsxOpc2 = get_VSX60_opc2(opc2, theInstr);
28314 
28315       switch (vsxOpc2) {
28316          case 0x8: case 0x28: case 0x48: case 0xc8: // xxsldwi, xxpermdi, xxmrghw, xxmrglw
28317          case 0x068: case 0xE8:  // xxperm, xxpermr
28318          case 0x018: case 0x148: // xxsel, xxspltw
28319             if (dis_vx_permute_misc(theInstr, vsxOpc2 ))
28320 	       goto decode_success;
28321             goto decode_failure;
28322          case 0xC: case 0x2C: case 0x4C: // xscmpeqdp, xscmpgtdp, xscmpgedp
28323          case 0x200: case 0x220:         //xsmaxcdp, xsmincdp
28324             if (dis_vx_misc(theInstr, vsxOpc2)) goto decode_success;
28325             goto decode_failure;
28326          case 0x268: case 0x248: case 0x288: // xxlxor, xxlor, xxlnor,
28327          case 0x208: case 0x228: // xxland, xxlandc
28328          case 0x2A8: case 0x2C8: case 0x2E8: //  xxlorc, xxlnand, xxleqv
28329             if (dis_vx_logic(theInstr, vsxOpc2)) goto decode_success;
28330             goto decode_failure;
28331          case 0x0ec:             // xscmpexpdp
28332          case 0x14A: case 0x16A: // xxextractuw, xxinsertw
28333          case 0x2B2: case 0x2C0: // xsabsdp, xscpsgndp
28334          case 0x2D2: case 0x2F2: // xsnabsdp, xsnegdp
28335          case 0x280: case 0x2A0: // xsmaxdp, xsmindp
28336          case 0x0F2: case 0x0D2: // xsrdpim, xsrdpip
28337          case 0x034: case 0x014: // xsresp, xsrsqrtesp
28338          case 0x0B4: case 0x094: // xsredp, xsrsqrtedp
28339          case 0x0D6: case 0x0B2: // xsrdpic, xsrdpiz
28340          case 0x092: case 0x232: // xsrdpi, xsrsp
28341          case 0x3B6:             // xxbrh, xvxexpdp, xvxexpsp, xvxsigdp
28342                                  // xvxsigsp, xvcvhpsp
28343          case 0x2b6:             // xsxexpdp, xsxsigdp
28344          case 0x254: case 0x2d4: // xststdcsp, xststdcdp
28345          case 0x354:             // xvtstdcsp
28346          case 0x360:case 0x396:  // xviexpsp, xsiexpdp
28347          case 0x3D4: case 0x3E0: // xvtstdcdp, xviexpdp
28348             if (dis_vxs_misc(theInstr, abiinfo, vsxOpc2, allow_isa_3_0))
28349                goto decode_success;
28350             goto decode_failure;
28351          case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
28352             if (dis_vx_cmp(theInstr, vsxOpc2)) goto decode_success;
28353             goto decode_failure;
28354          case 0x0:   case 0x020: // xsaddsp, xssubsp
28355          case 0x080:             // xsadddp
28356          case 0x060: case 0x0E0: // xsdivsp, xsdivdp
28357          case 0x004: case 0x024: // xsmaddasp, xsmaddmsp
28358          case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp
28359          case 0x044: case 0x064: // xsmsubasp, xsmsubmsp
28360          case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp
28361          case 0x204: case 0x224: // xsnmaddasp, xsnmaddmsp
28362          case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp
28363          case 0x244: case 0x264: // xsnmsubasp, xsnmsubmsp
28364          case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp
28365          case 0x040: case 0x0C0: // xsmulsp, xsmuldp
28366          case 0x0A0:             // xssubdp
28367          case 0x016: case 0x096: // xssqrtsp,xssqrtdp
28368          case 0x0F4: case 0x0D4: // xstdivdp, xstsqrtdp
28369             if (dis_vxs_arith(theInstr, vsxOpc2)) goto decode_success;
28370             goto decode_failure;
28371          case 0x180: // xvadddp
28372          case 0x1E0: // xvdivdp
28373          case 0x1C0: // xvmuldp
28374          case 0x1A0: // xvsubdp
28375          case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp
28376          case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp
28377          case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp
28378          case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp
28379          case 0x1D4: case 0x1F4: // xvtsqrtdp, xvtdivdp
28380          case 0x196: // xvsqrtdp
28381             if (dis_vxv_dp_arith(theInstr, vsxOpc2)) goto decode_success;
28382             goto decode_failure;
28383          case 0x100: // xvaddsp
28384          case 0x160: // xvdivsp
28385          case 0x140: // xvmulsp
28386          case 0x120: // xvsubsp
28387          case 0x104: case 0x124: // xvmaddasp, xvmaddmsp
28388          case 0x144: case 0x164: // xvmsubasp, xvmsubmsp
28389          case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp
28390          case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp
28391          case 0x154: case 0x174: // xvtsqrtsp, xvtdivsp
28392          case 0x116: // xvsqrtsp
28393             if (dis_vxv_sp_arith(theInstr, vsxOpc2)) goto decode_success;
28394             goto decode_failure;
28395 
28396          case 0x250:             // xscvuxdsp
28397          case 0x2D0: case 0x3d0: // xscvuxddp, xvcvuxddp
28398          case 0x350: case 0x1d0: // xvcvuxdsp, xvcvuxwdp
28399          case 0x090: // xscvdpuxws
28400             // The above VSX conversion instructions employ some ISA 2.06
28401             // floating point conversion instructions under the covers,
28402             // so if allow_VX (which means "supports ISA 2.06") is not set,
28403             // we'll skip the decode.
28404             if (!allow_VX) goto decode_noVX;
28405             if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
28406             goto decode_failure;
28407 
28408          case 0x2B0: // xscvdpsxds
28409          case 0x270: case 0x2F0: // xscvsxdsp, xscvsxddp
28410          case 0x1b0: case 0x130: // xvcvdpsxws, xvcvspsxws
28411          case 0x0b0: case 0x290: // xscvdpsxws, xscvdpuxds
28412          case 0x212: case 0x216: // xscvdpsp, xscvdpspn
28413          case 0x292: case 0x296: // xscvspdp, xscvspdpn
28414          case 0x312: // xvcvdpsp
28415          case 0x390: case 0x190: // xvcvdpuxds, xvcvdpuxws
28416          case 0x3B0: case 0x310: // xvcvdpsxds, xvcvspuxds
28417          case 0x392: case 0x330: // xvcvspdp, xvcvspsxds
28418          case 0x110: case 0x3f0: // xvcvspuxws, xvcvsxddp
28419          case 0x370: case 0x1f0: // xvcvsxdsp, xvcvsxwdp
28420          case 0x170: case 0x150: // xvcvsxwsp, xvcvuxwsp
28421             if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
28422             goto decode_failure;
28423 
28424          case 0x18C:             // xvcmpeqdp[.]
28425          case 0x10C:             // xvcmpeqsp[.]
28426          case 0x14C:             // xvcmpgesp[.]
28427          case 0x12C:             // xvcmpgtsp[.]
28428          case 0x1CC:             // xvcmpgedp[.]
28429          case 0x1AC:             // xvcmpgtdp[.]
28430              if (dis_vvec_cmp(theInstr, vsxOpc2)) goto decode_success;
28431              goto decode_failure;
28432 
28433          case 0x134:  // xvresp
28434          case 0x1B4:  // xvredp
28435          case 0x194: case 0x114: // xvrsqrtedp, xvrsqrtesp
28436          case 0x372:             // xvnegsp
28437          case 0x380: case 0x3A0: // xvmaxdp, xvmindp
28438          case 0x300: case 0x320: // xvmaxsp, xvminsp
28439          case 0x3C0: case 0x340: // xvcpsgndp, xvcpsgnsp
28440          case 0x3B2: case 0x332: // xvabsdp, xvabssp
28441          case 0x3D2: case 0x352: // xvnabsdp, xvnabssp
28442          case 0x192: case 0x1D6: // xvrdpi, xvrdpic
28443          case 0x1F2: case 0x1D2: // xvrdpim, xvrdpip
28444          case 0x1B2: case 0x3F2: // xvrdpiz, xvnegdp
28445          case 0x112: case 0x156: // xvrspi, xvrspic
28446          case 0x172: case 0x152: // xvrspim, xvrspip
28447          case 0x132: // xvrspiz
28448             if (dis_vxv_misc(theInstr, vsxOpc2)) goto decode_success;
28449             goto decode_failure;
28450 
28451          default:
28452             goto decode_failure;
28453       }
28454       break;
28455    }
28456 
28457    /* 64bit Integer Stores */
28458    case 0x3E:  // std, stdu, stq
28459       if (dis_int_store( theInstr, abiinfo )) goto decode_success;
28460       goto decode_failure;
28461 
28462    case 0x3F:
28463       if (!allow_F) goto decode_noF;
28464       /* Instrs using opc[1:5] never overlap instrs using opc[1:10],
28465          so we can simply fall through the first switch statement */
28466 
28467       opc2 = IFIELD(theInstr, 1, 5);
28468       switch (opc2) {
28469       /* Floating Point Arith Instructions */
28470       case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd
28471       case 0x19:                       // fmul
28472          if (dis_fp_arith(theInstr)) goto decode_success;
28473          goto decode_failure;
28474       case 0x16:                       // fsqrt
28475          if (!allow_FX) goto decode_noFX;
28476          if (dis_fp_arith(theInstr)) goto decode_success;
28477          goto decode_failure;
28478       case 0x17: case 0x1A:            // fsel, frsqrte
28479          if (!allow_GX) goto decode_noGX;
28480          if (dis_fp_arith(theInstr)) goto decode_success;
28481          goto decode_failure;
28482 
28483       /* Floating Point Mult-Add Instructions */
28484       case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub
28485       case 0x1F:                       // fnmadd
28486          if (dis_fp_multadd(theInstr)) goto decode_success;
28487          goto decode_failure;
28488 
28489       case 0x18:                       // fre
28490          if (!allow_GX) goto decode_noGX;
28491          if (dis_fp_arith(theInstr)) goto decode_success;
28492          goto decode_failure;
28493 
28494       default:
28495          break; // Fall through
28496       }
28497 
28498       opc2 = IFIELD(theInstr, 1, 8);
28499       switch (opc2) {
28500       case 0x5: // xsrqpi, xsrqpix
28501       case 0x25: // xsrqpxp
28502          if ( !mode64 || !allow_isa_3_0 ) goto decode_failure;
28503          if ( dis_vx_Scalar_Round_to_quad_integer( theInstr, abiinfo ) )
28504             goto decode_success;
28505          goto decode_failure;
28506       default:
28507          break; // Fall through
28508       }
28509 
28510       opc2 = IFIELD(theInstr, 1, 10);
28511       UInt inst_select = IFIELD( theInstr, 16, 5 );
28512 
28513       switch (opc2) {
28514       /* 128-bit DFP instructions */
28515       case 0x2:    // daddq - DFP Add
28516       case 0x202:  // dsubq - DFP Subtract
28517       case 0x22:   // dmulq - DFP Mult
28518       case 0x222:  // ddivq - DFP Divide
28519          if (!allow_DFP) goto decode_noDFP;
28520          if (dis_dfp_arithq( theInstr ))
28521             goto decode_success;
28522          goto decode_failure;
28523       case 0x162:  // dxexq - DFP Extract exponent
28524       case 0x362:  // diexq - DFP Insert exponent
28525          if (!allow_DFP) goto decode_noDFP;
28526          if (dis_dfp_extract_insertq( theInstr ))
28527             goto decode_success;
28528          goto decode_failure;
28529 
28530       case 0x82:   // dcmpoq, DFP comparison ordered instruction
28531       case 0x282:  // dcmpuq, DFP comparison unordered instruction
28532          if (!allow_DFP) goto decode_noDFP;
28533          if (dis_dfp_compare( theInstr ) )
28534             goto decode_success;
28535          goto decode_failure;
28536 
28537       case 0x102: // dctqpq  - DFP convert to DFP extended
28538       case 0x302: // drdpq   - DFP round to dfp Long
28539       case 0x122: // dctfixq - DFP convert to fixed quad
28540       case 0x322: // dcffixq - DFP convert from fixed quad
28541          if (!allow_DFP) goto decode_noDFP;
28542          if (dis_dfp_fmt_convq( theInstr ))
28543             goto decode_success;
28544          goto decode_failure;
28545 
28546       case 0x2A2: // dtstsfq  - DFP number of significant digits
28547       case 0x2A3: // dtstsfiq - DFP number of significant digits Immediate
28548          if (!allow_DFP) goto decode_noDFP;
28549          if (dis_dfp_significant_digits(theInstr))
28550             goto decode_success;
28551          goto decode_failure;
28552 
28553       case 0x142: // ddedpdq   DFP Decode DPD to BCD
28554       case 0x342: // denbcdq   DFP Encode BCD to DPD
28555          if (!allow_DFP) goto decode_noDFP;
28556          if (dis_dfp_bcdq(theInstr))
28557             goto decode_success;
28558          goto decode_failure;
28559 
28560       /* Floating Point Compare Instructions */
28561       case 0x000: // fcmpu
28562       case 0x020: // fcmpo
28563          if (dis_fp_cmp(theInstr)) goto decode_success;
28564          goto decode_failure;
28565 
28566       case 0x080: // ftdiv
28567       case 0x0A0: // ftsqrt
28568          if (dis_fp_tests(theInstr)) goto decode_success;
28569          goto decode_failure;
28570 
28571       /* Floating Point Rounding/Conversion Instructions */
28572       case 0x00C: // frsp
28573       case 0x00E: // fctiw
28574       case 0x00F: // fctiwz
28575       case 0x32E: // fctid
28576       case 0x32F: // fctidz
28577       case 0x34E: // fcfid
28578          if (dis_fp_round(theInstr)) goto decode_success;
28579          goto decode_failure;
28580       case 0x3CE: case 0x3AE: case 0x3AF: // fcfidu, fctidu[z] (implemented as native insns)
28581       case 0x08F: case 0x08E: // fctiwu[z] (implemented as native insns)
28582          if (!allow_VX) goto decode_noVX;
28583          if (dis_fp_round(theInstr)) goto decode_success;
28584          goto decode_failure;
28585 
28586       /* Power6 rounding stuff */
28587       case 0x1E8: // frim
28588       case 0x1C8: // frip
28589       case 0x188: // frin
28590       case 0x1A8: // friz
28591          /* A hack to check for P6 capability . . . */
28592          if ((allow_F && allow_V && allow_FX && allow_GX) &&
28593              (dis_fp_round(theInstr)))
28594             goto decode_success;
28595          goto decode_failure;
28596 
28597       /* Floating Point Move Instructions */
28598       case 0x008: // fcpsgn
28599       case 0x028: // fneg
28600       case 0x048: // fmr
28601       case 0x088: // fnabs
28602       case 0x108: // fabs
28603          if (dis_fp_move( theInstr )) goto decode_success;
28604          goto decode_failure;
28605 
28606       case 0x3c6: case 0x346:          // fmrgew, fmrgow
28607          if (dis_fp_merge( theInstr )) goto decode_success;
28608          goto decode_failure;
28609 
28610       /* Floating Point Status/Control Register Instructions */
28611       case 0x026: // mtfsb1
28612       case 0x040: // mcrfs
28613       case 0x046: // mtfsb0
28614       case 0x086: // mtfsfi
28615       case 0x247: // mffs, mmfs., mffsce, mffscdrn, mffscdrni,
28616                   // mffscrn, mffscrn, mffscri, mffsl
28617       case 0x2C7: // mtfsf
28618          // Some of the above instructions need to know more about the
28619          // ISA level supported by the host.
28620          if (dis_fp_scr( theInstr, allow_GX )) goto decode_success;
28621          goto decode_failure;
28622 
28623       case 0x324: // xsabsqp, xsxexpqp,xsnabsqp, xsnegqp, xsxsigqp
28624          if ( inst_select == 27 ) {    // xssqrtqp
28625             if ( dis_vx_Floating_Point_Arithmetic_quad_precision( theInstr,
28626 								  abiinfo ) )
28627                goto decode_success;
28628          }
28629 
28630          /* Instructions implemented with Pre ISA 3.0 Iops */
28631          /* VSX Scalar Quad-Precision instructions */
28632       case 0x064: // xscpsgnqp
28633       case 0x0A4: // xscmpexpqp
28634       case 0x084: // xscmpoqp
28635       case 0x284: // xscmpuqp
28636       case 0x2C4: // xststdcqp
28637       case 0x364: // xsiexpqp
28638          if (dis_vx_scalar_quad_precision( theInstr )) goto decode_success;
28639          goto decode_failure;
28640 
28641       /* Instructions implemented using ISA 3.0 instructions */
28642                   // xsaddqpo (VSX Scalar Add Quad-Precision [using round to ODD]
28643       case 0x004: // xsaddqp  (VSX Scalar Add Quad-Precision [using RN mode]
28644                   // xsmulqpo (VSX Scalar Multiply Quad-Precision [using round to ODD]
28645       case 0x024: // xsmulqp  (VSX Scalar Multiply Quad-Precision [using RN mode]
28646                   // xsmaddqpo (VSX Scalar Multiply Add Quad-Precision [using round to ODD]
28647       case 0x184: // xsmaddqp  (VSX Scalar Multiply Add Quad-Precision [using RN mode]
28648                   // xsmsubqpo (VSX Scalar Multiply Sub Quad-Precision [using round to ODD]
28649       case 0x1A4: // xsmsubqp  (VSX Scalar Multiply Sub Quad-Precision [using RN mode]
28650                   // xsnmaddqpo (VSX Scalar Negative Multiply Add Quad-Precision [using round to ODD]
28651       case 0x1C4: // xsnmaddqp  (VSX Scalar Negative Multiply Add Quad-Precision [using RN mode]
28652                   // xsnmsubqpo (VSX Scalar Negative Multiply Sub Quad-Precision [using round to ODD]
28653       case 0x1E4: // xsnmsubqp  (VSX Scalar Negative Multiply Sub Quad-Precision [usin RN mode]
28654                   // xssubqpo (VSX Scalar Subrtact Quad-Precision [using round to ODD]
28655       case 0x204: // xssubqp  (VSX Scalar Subrtact Quad-Precision [using RN mode]
28656                   // xsdivqpo (VSX Scalar Divde Quad-Precision [using round to ODD]
28657       case 0x224: // xsdivqp  (VSX Scalar Divde Quad-Precision [using RN mode]
28658       case 0x344: // xscvudqp, xscvsdqp, xscvqpdp, xscvqpdpo, xsvqpdp
28659                   // xscvqpswz, xscvqpuwz, xscvqpudz, xscvqpsdz
28660          if ( !mode64 || !allow_isa_3_0 ) goto decode_failure;
28661          if ( dis_vx_Floating_Point_Arithmetic_quad_precision( theInstr,
28662 							       abiinfo ) )
28663             goto decode_success;
28664          goto decode_failure;
28665 
28666       default:
28667          break; // Fall through...
28668       }
28669 
28670       opc2 = ifieldOPClo9( theInstr );
28671       switch (opc2) {
28672       case 0x42: // dscli, DFP shift left
28673       case 0x62: // dscri, DFP shift right
28674          if (!allow_DFP) goto decode_noDFP;
28675          if (dis_dfp_shiftq( theInstr ))
28676             goto decode_success;
28677          goto decode_failure;
28678       case 0xc2:  // dtstdc, DFP test data class
28679       case 0xe2:  // dtstdg, DFP test data group
28680          if (!allow_DFP) goto decode_noDFP;
28681          if (dis_dfp_class_test( theInstr ))
28682             goto decode_success;
28683          goto decode_failure;
28684       default:
28685          break;
28686       }
28687 
28688       opc2 = ifieldOPClo8( theInstr );
28689       switch (opc2) {
28690       case 0x3:   // dquaq  - DFP Quantize Quad
28691       case 0x23:  // drrndq - DFP Reround Quad
28692       case 0x43:  // dquaiq - DFP Quantize immediate Quad
28693          if (!allow_DFP) goto decode_noDFP;
28694          if (dis_dfp_quantize_sig_rrndq( theInstr ))
28695             goto decode_success;
28696          goto decode_failure;
28697       case 0xA2: // dtstexq - DFP Test exponent Quad
28698          if (!allow_DFP) goto decode_noDFP;
28699          if (dis_dfp_exponent_test( theInstr ) )
28700             goto decode_success;
28701          goto decode_failure;
28702       case 0x63:  // drintxq - DFP Round to an integer value
28703       case 0xE3:  // drintnq - DFP Round to an integer value
28704          if (!allow_DFP) goto decode_noDFP;
28705          if (dis_dfp_roundq( theInstr ))
28706             goto decode_success;
28707          goto decode_failure;
28708 
28709       default:
28710          goto decode_failure;
28711       }
28712       break;
28713 
28714    case 0x13:
28715 
28716       opc2 = ifieldOPClo5(theInstr);
28717       switch (opc2) {
28718 
28719       /* PC relative load/store */
28720       case 0x002:       // addpcis
28721          if (dis_pc_relative(theInstr)) goto decode_success;
28722          goto decode_failure;
28723 
28724       /* fall through to the next opc2 field size */
28725       }
28726 
28727       opc2 = ifieldOPClo10(theInstr);
28728       switch (opc2) {
28729 
28730       /* Condition Register Logical Instructions */
28731       case 0x101: case 0x081: case 0x121: // crand,  crandc, creqv
28732       case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor,  cror
28733       case 0x1A1: case 0x0C1: case 0x000: // crorc,  crxor,  mcrf
28734          if (dis_cond_logic( theInstr )) goto decode_success;
28735          goto decode_failure;
28736 
28737       /* Branch Instructions */
28738       case 0x210: case 0x010: // bcctr, bclr
28739          if (dis_branch(theInstr, abiinfo, &dres,
28740                                   resteerOkFn, callback_opaque))
28741             goto decode_success;
28742          goto decode_failure;
28743 
28744       /* Memory Synchronization Instructions */
28745       case 0x096: // isync
28746          if (dis_memsync( theInstr )) goto decode_success;
28747          goto decode_failure;
28748 
28749       default:
28750          goto decode_failure;
28751       }
28752       break;
28753 
28754 
28755    case 0x1F:
28756 
28757       /* For arith instns, bit10 is the OE flag (overflow enable) */
28758 
28759       opc2 = IFIELD(theInstr, 1, 9);
28760       switch (opc2) {
28761       /* Integer Arithmetic Instructions */
28762       case 0x10A: case 0x00A: case 0x08A: // add,   addc,  adde
28763       case 0x0AA:                         // addex
28764       case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw
28765       case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu
28766       case 0x0EB: case 0x068: case 0x028: // mullw, neg,   subf
28767       case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme
28768       case 0x0C8: // subfze
28769          if (dis_int_arith( theInstr )) goto decode_success;
28770          goto decode_failure;
28771 
28772       case 0x18B: // divweu (implemented as native insn)
28773       case 0x1AB: // divwe (implemented as native insn)
28774          if (!allow_VX) goto decode_noVX;
28775          if (dis_int_arith( theInstr )) goto decode_success;
28776          goto decode_failure;
28777 
28778       /* 64bit Integer Arithmetic */
28779       case 0x009: case 0x049: case 0x0E9: // mulhdu, mulhd, mulld
28780       case 0x1C9: case 0x1E9: // divdu, divd
28781          if (!mode64) goto decode_failure;
28782          if (dis_int_arith( theInstr )) goto decode_success;
28783          goto decode_failure;
28784 
28785       case 0x1A9: //  divde (implemented as native insn)
28786       case 0x189: //  divdeuo (implemented as native insn)
28787          if (!allow_VX) goto decode_noVX;
28788          if (!mode64) goto decode_failure;
28789          if (dis_int_arith( theInstr )) goto decode_success;
28790          goto decode_failure;
28791 
28792       case 0x1FC:                         // cmpb
28793          if (dis_int_logic( theInstr )) goto decode_success;
28794          goto decode_failure;
28795 
28796       default:
28797          break;  // Fall through...
28798       }
28799 
28800       /* All remaining opcodes use full 10 bits. */
28801 
28802       opc2 = IFIELD(theInstr, 1, 10);
28803       switch (opc2) {
28804 
28805       /* Integer miscellaneous instructions */
28806       case 0x01E:  // wait  RFC 2500
28807          if (dis_int_misc( theInstr )) goto decode_success;
28808          goto decode_failure;
28809 
28810 
28811       /* Integer Compare Instructions  */
28812       case 0x000: case 0x020: case 0x080: // cmp, cmpl, setb
28813          if (dis_int_cmp( theInstr )) goto decode_success;
28814          goto decode_failure;
28815 
28816       case 0x0C0: case 0x0E0:   // cmprb, cmpeqb
28817          if (dis_byte_cmp( theInstr )) goto decode_success;
28818          goto decode_failure;
28819 
28820       case 0x10B: case 0x30B: // moduw, modsw
28821       case 0x109: case 0x309: // modsd, modud
28822       case 0x21A: case 0x23A: // cnttzw, cnttzd
28823          if (dis_modulo_int( theInstr )) goto decode_success;
28824          goto decode_failure;
28825 
28826       /* Integer Logical Instructions */
28827       case 0x01C: case 0x03C: case 0x01A: // and,  andc,  cntlzw
28828       case 0x11C: case 0x3BA: case 0x39A: // eqv,  extsb, extsh
28829       case 0x1DC: case 0x07C: case 0x1BC: // nand, nor,   or
28830       case 0x19C: case 0x13C:             // orc,  xor
28831       case 0x2DF: case 0x25F:            // mftgpr, mffgpr
28832          if (dis_int_logic( theInstr )) goto decode_success;
28833          goto decode_failure;
28834 
28835       case 0x28E: case 0x2AE:             // tbegin., tend.
28836       case 0x2EE: case 0x2CE: case 0x30E: // tsr., tcheck., tabortwc.
28837       case 0x32E: case 0x34E: case 0x36E: // tabortdc., tabortwci., tabortdci.
28838       case 0x38E: case 0x3AE: case 0x3EE: // tabort., treclaim., trechkpt.
28839       if (dis_transactional_memory( theInstr,
28840                                     getUIntPPCendianly( &guest_code[delta + 4]),
28841                                     abiinfo, &dres,
28842                                     resteerOkFn, callback_opaque))
28843             goto decode_success;
28844          goto decode_failure;
28845 
28846       /* 64bit Integer Logical Instructions */
28847       case 0x3DA: case 0x03A: // extsw, cntlzd
28848          if (!mode64) goto decode_failure;
28849          if (dis_int_logic( theInstr )) goto decode_success;
28850          goto decode_failure;
28851 
28852          /* 64bit Integer Parity Instructions */
28853       case 0xba: // prtyd
28854          if (!mode64) goto decode_failure;
28855          if (dis_int_parity( theInstr )) goto decode_success;
28856          goto decode_failure;
28857 
28858       case 0x9a: // prtyw
28859          if (dis_int_parity( theInstr )) goto decode_success;
28860          goto decode_failure;
28861 
28862       /* Integer Shift Instructions */
28863       case 0x018: case 0x318: case 0x338: // slw, sraw, srawi
28864       case 0x218:                         // srw
28865          if (dis_int_shift( theInstr )) goto decode_success;
28866          goto decode_failure;
28867 
28868       /* 64bit Integer Shift Instructions */
28869       case 0x01B: case 0x31A: // sld, srad
28870       case 0x33A: case 0x33B: // sradi
28871       case 0x21B:             // srd
28872          if (!mode64) goto decode_failure;
28873          if (dis_int_shift( theInstr )) goto decode_success;
28874          goto decode_failure;
28875 
28876       /* Integer Load Instructions */
28877       case 0x057: case 0x077: case 0x157: // lbzx,  lbzux, lhax
28878       case 0x177: case 0x117: case 0x137: // lhaux, lhzx,  lhzux
28879       case 0x017: case 0x037:             // lwzx,  lwzux
28880          if (dis_int_load( theInstr )) goto decode_success;
28881          goto decode_failure;
28882 
28883       /* 64bit Integer Load Instructions */
28884       case 0x035: case 0x015:             // ldux,  ldx
28885       case 0x175: case 0x155:             // lwaux, lwax
28886          if (!mode64) goto decode_failure;
28887          if (dis_int_load( theInstr )) goto decode_success;
28888          goto decode_failure;
28889 
28890       /* Integer Store Instructions */
28891       case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx,  sthux
28892       case 0x197: case 0x0B7: case 0x097: // sthx,  stwux, stwx
28893          if (dis_int_store( theInstr, abiinfo )) goto decode_success;
28894          goto decode_failure;
28895 
28896       /* 64bit Integer Store Instructions */
28897       case 0x0B5: case 0x095: // stdux, stdx
28898          if (!mode64) goto decode_failure;
28899          if (dis_int_store( theInstr, abiinfo )) goto decode_success;
28900          goto decode_failure;
28901 
28902       /* Integer Load and Store with Byte Reverse Instructions */
28903       case 0x214: case 0x294: // ldbrx, stdbrx
28904          if (!mode64) goto decode_failure;
28905          if (dis_int_ldst_rev( theInstr )) goto decode_success;
28906          goto decode_failure;
28907 
28908       case 0x216: case 0x316: case 0x296:    // lwbrx, lhbrx, stwbrx
28909       case 0x396:                            // sthbrx
28910          if (dis_int_ldst_rev( theInstr )) goto decode_success;
28911          goto decode_failure;
28912 
28913       /* Integer Load and Store String Instructions */
28914       case 0x255: case 0x215: case 0x2D5: // lswi, lswx, stswi
28915       case 0x295: {                       // stswx
28916          Bool stopHere = False;
28917          Bool ok = dis_int_ldst_str( theInstr, &stopHere );
28918          if (!ok) goto decode_failure;
28919          if (stopHere) {
28920             putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()) );
28921             dres.jk_StopHere = Ijk_Boring;
28922             dres.whatNext    = Dis_StopHere;
28923          }
28924          goto decode_success;
28925       }
28926 
28927       /* Memory Synchronization Instructions */
28928       case 0x034: case 0x074:             // lbarx, lharx
28929       case 0x2B6: case 0x2D6:             // stbcx, sthcx
28930          if (!allow_isa_2_07) goto decode_noP8;
28931          if (dis_memsync( theInstr )) goto decode_success;
28932          goto decode_failure;
28933 
28934       case 0x356: case 0x014: case 0x096: // eieio, lwarx, stwcx.
28935       case 0x256:                         // sync
28936          if (dis_memsync( theInstr )) goto decode_success;
28937          goto decode_failure;
28938 
28939       /* 64bit Memory Synchronization Instructions */
28940       case 0x054: case 0x0D6: // ldarx, stdcx.
28941          if (!mode64) goto decode_failure;
28942          if (dis_memsync( theInstr )) goto decode_success;
28943          goto decode_failure;
28944 
28945       case 0x114: case 0x0B6: // lqarx, stqcx.
28946          if (dis_memsync( theInstr )) goto decode_success;
28947          goto decode_failure;
28948 
28949       /* Processor Control Instructions */
28950       case 0x33:  case 0x73: // mfvsrd, mfvsrwz
28951       case 0xB3:  case 0xD3: case 0xF3: // mtvsrd, mtvsrwa, mtvsrwz
28952       case 0x200: case 0x013: case 0x153: // mcrxr, mfcr,  mfspr
28953       case 0x173: case 0x090: case 0x1D3: // mftb,  mtcrf, mtspr
28954       case 0x220:                         // mcrxrt
28955          if (dis_proc_ctl( abiinfo, theInstr )) goto decode_success;
28956          goto decode_failure;
28957 
28958       /* Cache Management Instructions */
28959       case 0x2F6: case 0x056: case 0x036: // dcba, dcbf,   dcbst
28960       case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz
28961       case 0x3D6:                         // icbi
28962          if (dis_cache_manage( theInstr, &dres, archinfo ))
28963             goto decode_success;
28964          goto decode_failure;
28965 
28966 //zz       /* External Control Instructions */
28967 //zz       case 0x136: case 0x1B6: // eciwx, ecowx
28968 //zz          DIP("external control op => not implemented\n");
28969 //zz          goto decode_failure;
28970 
28971       /* Trap Instructions */
28972       case 0x004:             // tw
28973          if (dis_trap(theInstr, &dres)) goto decode_success;
28974          goto decode_failure;
28975 
28976       case 0x044:             // td
28977          if (!mode64) goto decode_failure;
28978          if (dis_trap(theInstr, &dres)) goto decode_success;
28979          goto decode_failure;
28980 
28981       /* Floating Point Load Instructions */
28982       case 0x217: case 0x237: case 0x257: // lfsx, lfsux, lfdx
28983       case 0x277:                         // lfdux
28984          if (!allow_F) goto decode_noF;
28985          if (dis_fp_load( theInstr )) goto decode_success;
28986          goto decode_failure;
28987 
28988       /* Floating Point Store Instructions */
28989       case 0x297: case 0x2B7: case 0x2D7: // stfs,  stfsu, stfd
28990       case 0x2F7:                         // stfdu, stfiwx
28991          if (!allow_F) goto decode_noF;
28992          if (dis_fp_store( theInstr )) goto decode_success;
28993          goto decode_failure;
28994       case 0x3D7:                         // stfiwx
28995          if (!allow_F) goto decode_noF;
28996          if (!allow_GX) goto decode_noGX;
28997          if (dis_fp_store( theInstr )) goto decode_success;
28998          goto decode_failure;
28999 
29000          /* Floating Point Double Pair Indexed Instructions */
29001       case 0x317: // lfdpx (Power6)
29002       case 0x397: // stfdpx (Power6)
29003          if (!allow_F) goto decode_noF;
29004          if (dis_fp_pair(theInstr)) goto decode_success;
29005          goto decode_failure;
29006 
29007       case 0x357:                         // lfiwax
29008          if (!allow_F) goto decode_noF;
29009          if (dis_fp_load( theInstr )) goto decode_success;
29010          goto decode_failure;
29011 
29012       case 0x377:                         // lfiwzx
29013          if (!allow_F) goto decode_noF;
29014          if (dis_fp_load( theInstr )) goto decode_success;
29015          goto decode_failure;
29016 
29017       /* AltiVec instructions */
29018 
29019       /* AV Cache Control - Data streams */
29020       case 0x156: case 0x176: case 0x336: // dst, dstst, dss
29021          if (!allow_V) goto decode_noV;
29022          if (dis_av_datastream( theInstr )) goto decode_success;
29023          goto decode_failure;
29024 
29025       /* AV Load */
29026       case 0x006: case 0x026:             // lvsl, lvsr
29027       case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx
29028       case 0x067: case 0x167:             // lvx, lvxl
29029          if (!allow_V) goto decode_noV;
29030          if (dis_av_load( abiinfo, theInstr )) goto decode_success;
29031          goto decode_failure;
29032 
29033       /* AV Store */
29034       case 0x087: case 0x0A7: case 0x0C7: // stvebx, stvehx, stvewx
29035       case 0x0E7: case 0x1E7:             // stvx, stvxl
29036          if (!allow_V) goto decode_noV;
29037          if (dis_av_store( theInstr )) goto decode_success;
29038          goto decode_failure;
29039 
29040       /* VSX Load */
29041       case 0x00C: // lxsiwzx
29042       case 0x04C: // lxsiwax
29043       case 0x10C: // lxvx
29044       case 0x10D: // lxvl
29045       case 0x12D: // lxvll
29046       case 0x16C: // lxvwsx
29047       case 0x20C: // lxsspx
29048       case 0x24C: // lxsdx
29049       case 0x32C: // lxvh8x
29050       case 0x30D: // lxsibzx
29051       case 0x32D: // lxsihzx
29052       case 0x34C: // lxvd2x
29053       case 0x36C: // lxvb16x
29054       case 0x14C: // lxvdsx
29055       case 0x30C: // lxvw4x
29056         // All of these VSX load instructions use some VMX facilities, so
29057         // if allow_V is not set, we'll skip trying to decode.
29058         if (!allow_V) goto decode_noV;
29059 
29060 	if (dis_vx_load( theInstr )) goto decode_success;
29061           goto decode_failure;
29062 
29063       /* VSX Store */
29064       case 0x08C: // stxsiwx
29065       case 0x18C: // stxvx
29066       case 0x18D: // stxvl
29067       case 0x1AD: // stxvll
29068       case 0x28C: // stxsspx
29069       case 0x2CC: // stxsdx
29070       case 0x38C: // stxvw4x
29071       case 0x3CC: // stxvd2x
29072       case 0x38D: // stxsibx
29073       case 0x3AD: // stxsihx
29074       case 0x3AC: // stxvh8x
29075       case 0x3EC: // stxvb16x
29076         // All of these VSX store instructions use some VMX facilities, so
29077         // if allow_V is not set, we'll skip trying to decode.
29078         if (!allow_V) goto decode_noV;
29079 
29080 	if (dis_vx_store( theInstr )) goto decode_success;
29081     	  goto decode_failure;
29082 
29083       case 0x133: case 0x193: case 0x1B3:  // mfvsrld, mfvsrdd, mtvsrws
29084         // The move from/to VSX instructions use some VMX facilities, so
29085         // if allow_V is not set, we'll skip trying to decode.
29086         if (!allow_V) goto decode_noV;
29087         if (dis_vx_move( theInstr )) goto decode_success;
29088         goto decode_failure;
29089 
29090       /* Miscellaneous ISA 2.06 instructions */
29091       case 0x1FA: // popcntd
29092          if (!mode64) goto decode_failure;
29093          /* else fallthru */
29094       case 0x17A: // popcntw
29095       case 0x7A:  // popcntb
29096          if (dis_int_logic( theInstr )) goto decode_success;
29097          goto decode_failure;
29098 
29099       case 0x0FC: // bpermd
29100          if (!mode64) goto decode_failure;
29101          if (dis_int_logic( theInstr )) goto decode_success;
29102          goto decode_failure;
29103 
29104       default:
29105          /* Deal with some other cases that we would otherwise have
29106             punted on. */
29107          /* --- ISEL (PowerISA_V2.05.pdf, p74) --- */
29108          /* only decode this insn when reserved bit 0 (31 in IBM's
29109             notation) is zero */
29110          if (IFIELD(theInstr, 0, 6) == (15<<1)) {
29111             UInt rT = ifieldRegDS( theInstr );
29112             UInt rA = ifieldRegA( theInstr );
29113             UInt rB = ifieldRegB( theInstr );
29114             UInt bi = ifieldRegC( theInstr );
29115             putIReg(
29116                rT,
29117                IRExpr_ITE( binop(Iop_CmpNE32, getCRbit( bi ), mkU32(0)),
29118                            rA == 0 ? (mode64 ? mkU64(0) : mkU32(0))
29119                                    : getIReg(rA),
29120                            getIReg(rB))
29121 
29122             );
29123             DIP("isel r%u,r%u,r%u,crb%u\n", rT,rA,rB,bi);
29124             goto decode_success;
29125          }
29126       }
29127 
29128       opc2 = IFIELD(theInstr, 2, 9);
29129       switch (opc2) {
29130       case 0x1BD:
29131          if (!mode64) goto decode_failure;
29132          if (dis_int_logic( theInstr )) goto decode_success;
29133          goto decode_failure;
29134 
29135       default:
29136          goto decode_failure;
29137       }
29138       break;
29139 
29140 
29141    case 0x04:
29142       /* AltiVec instructions */
29143 
29144       opc2 = IFIELD(theInstr, 0, 6);
29145       switch (opc2) {
29146       /* AV Mult-Add, Mult-Sum */
29147       case 0x20: case 0x21: case 0x22: // vmhaddshs, vmhraddshs, vmladduhm
29148       case 0x23:                       // vmsumudm
29149       case 0x24: case 0x25: case 0x26: // vmsumubm, vmsummbm, vmsumuhm
29150       case 0x27: case 0x28: case 0x29: // vmsumuhs, vmsumshm, vmsumshs
29151          if (!allow_V) goto decode_noV;
29152          if (dis_av_multarith( theInstr )) goto decode_success;
29153          goto decode_failure;
29154 
29155       case 0x30: case 0x31: case 0x33: // maddhd, madhdu, maddld
29156          if (!mode64) goto decode_failure;
29157          if (dis_int_mult_add( theInstr )) goto decode_success;
29158          goto decode_failure;
29159 
29160       /* AV Permutations */
29161       case 0x2A:                       // vsel
29162       case 0x2B:                       // vperm
29163       case 0x2C:                       // vsldoi
29164          if (!allow_V) goto decode_noV;
29165          if (dis_av_permute( theInstr )) goto decode_success;
29166          goto decode_failure;
29167 
29168       case 0x2D:                       // vpermxor
29169       case 0x3B:                       // vpermr
29170          if (!allow_isa_2_07) goto decode_noP8;
29171          if (dis_av_permute( theInstr )) goto decode_success;
29172          goto decode_failure;
29173 
29174       /* AV Floating Point Mult-Add/Sub */
29175       case 0x2E: case 0x2F:            // vmaddfp, vnmsubfp
29176          if (!allow_V) goto decode_noV;
29177          if (dis_av_fp_arith( theInstr )) goto decode_success;
29178          goto decode_failure;
29179 
29180       case 0x3D: case 0x3C:            // vaddecuq, vaddeuqm
29181       case 0x3F: case 0x3E:            // vsubecuq, vsubeuqm
29182          if (!allow_V) goto decode_noV;
29183          if (dis_av_quad( theInstr)) goto decode_success;
29184          goto decode_failure;
29185 
29186       default:
29187          break;  // Fall through...
29188       }
29189 
29190       opc2 = IFIELD(theInstr, 0, 9);
29191       if (IFIELD(theInstr, 10, 1) == 1) {
29192          /* The following instructions have bit 21 set and a PS bit (bit 22)
29193           * Bit 21 distinquishes them from instructions with an 11 bit opc2
29194           * field.
29195           */
29196          switch (opc2) {
29197             /* BCD arithmetic */
29198             case 0x001: case 0x041:             // bcdadd, bcdsub
29199             case 0x101: case 0x141:             // bcdtrunc., bcdutrunc.
29200             case 0x081: case 0x0C1: case 0x1C1: // bcdus., bcds., bcdsr.
29201             case 0x181:                         // bcdcfn., bcdcfz.
29202                                                 // bcdctz., bcdcfsq., bcdctsq.
29203                if (!allow_isa_2_07) goto decode_noP8;
29204                if (dis_av_bcd( theInstr, abiinfo )) goto decode_success;
29205               goto decode_failure;
29206          default:
29207               break;  // Fall through...
29208             }
29209       }
29210 
29211       opc2 = IFIELD(theInstr, 0, 11);
29212       switch (opc2) {
29213       /* BCD manipulation */
29214       case 0x341:                  // bcdcpsgn
29215 
29216          if (!allow_isa_2_07) goto decode_noP8;
29217          if (dis_av_bcd_misc( theInstr, abiinfo )) goto decode_success;
29218          goto decode_failure;
29219 
29220 
29221       /* AV Arithmetic */
29222       case 0x180:                         // vaddcuw
29223       case 0x000: case 0x040: case 0x080: // vaddubm, vadduhm, vadduwm
29224       case 0x200: case 0x240: case 0x280: // vaddubs, vadduhs, vadduws
29225       case 0x300: case 0x340: case 0x380: // vaddsbs, vaddshs, vaddsws
29226       case 0x580:                         // vsubcuw
29227       case 0x400: case 0x440: case 0x480: // vsububm, vsubuhm, vsubuwm
29228       case 0x600: case 0x640: case 0x680: // vsububs, vsubuhs, vsubuws
29229       case 0x700: case 0x740: case 0x780: // vsubsbs, vsubshs, vsubsws
29230       case 0x402: case 0x442: case 0x482: // vavgub, vavguh, vavguw
29231       case 0x502: case 0x542: case 0x582: // vavgsb, vavgsh, vavgsw
29232       case 0x002: case 0x042: case 0x082: // vmaxub, vmaxuh, vmaxuw
29233       case 0x102: case 0x142: case 0x182: // vmaxsb, vmaxsh, vmaxsw
29234       case 0x202: case 0x242: case 0x282: // vminub, vminuh, vminuw
29235       case 0x302: case 0x342: case 0x382: // vminsb, vminsh, vminsw
29236       case 0x008: case 0x048:             // vmuloub, vmulouh
29237       case 0x108: case 0x148:             // vmulosb, vmulosh
29238       case 0x208: case 0x248:             // vmuleub, vmuleuh
29239       case 0x308: case 0x348:             // vmulesb, vmulesh
29240       case 0x608: case 0x708: case 0x648: // vsum4ubs, vsum4sbs, vsum4shs
29241       case 0x688: case 0x788:             // vsum2sws, vsumsws
29242          if (!allow_V) goto decode_noV;
29243          if (dis_av_arith( theInstr )) goto decode_success;
29244          goto decode_failure;
29245 
29246       case 0x088: case 0x089:             // vmulouw, vmuluwm
29247       case 0x0C0: case 0x0C2:             // vaddudm, vmaxud
29248       case 0x1C2: case 0x2C2: case 0x3C2: // vnaxsd, vminud, vminsd
29249       case 0x188: case 0x288: case 0x388: // vmulosw, vmuleuw, vmulesw
29250       case 0x4C0:                         // vsubudm
29251          if (!allow_isa_2_07) goto decode_noP8;
29252          if (dis_av_arith( theInstr )) goto decode_success;
29253          goto decode_failure;
29254 
29255       /* AV Polynomial Vector Multiply Add */
29256       case 0x408: case 0x448:            // vpmsumb, vpmsumd
29257       case 0x488: case 0x4C8:            // vpmsumw, vpmsumh
29258          if (!allow_isa_2_07) goto decode_noP8;
29259          if (dis_av_polymultarith( theInstr )) goto decode_success;
29260          goto decode_failure;
29261 
29262       /* AV Rotate, Shift */
29263       case 0x004: case 0x044: case 0x084: // vrlb, vrlh, vrlw
29264       case 0x104: case 0x144: case 0x184: // vslb, vslh, vslw
29265       case 0x204: case 0x244: case 0x284: // vsrb, vsrh, vsrw
29266       case 0x304: case 0x344: case 0x384: // vsrab, vsrah, vsraw
29267       case 0x1C4: case 0x2C4:             // vsl, vsr
29268       case 0x40C: case 0x44C:             // vslo, vsro
29269          if (!allow_V) goto decode_noV;
29270          if (dis_av_shift( theInstr )) goto decode_success;
29271          goto decode_failure;
29272 
29273       case 0x0C4:                         // vrld
29274       case 0x3C4: case 0x5C4: case 0x6C4: // vsrad, vsld, vsrd
29275           if (!allow_isa_2_07) goto decode_noP8;
29276           if (dis_av_shift( theInstr )) goto decode_success;
29277           goto decode_failure;
29278 
29279       /* AV Logic */
29280       case 0x404: case 0x444: case 0x484: // vand, vandc, vor
29281       case 0x4C4: case 0x504:             // vxor, vnor
29282          if (!allow_V) goto decode_noV;
29283          if (dis_av_logic( theInstr )) goto decode_success;
29284          goto decode_failure;
29285 
29286       case 0x544:                         // vorc
29287       case 0x584: case 0x684:             // vnand, veqv
29288          if (!allow_isa_2_07) goto decode_noP8;
29289          if (dis_av_logic( theInstr )) goto decode_success;
29290          goto decode_failure;
29291 
29292       /* AV Rotate */
29293       case 0x085: case 0x185:             // vrlwmi, vrlwnm
29294       case 0x0C5: case 0x1C5:             // vrldmi, vrldnm
29295          if (!allow_V) goto decode_noV;
29296          if (dis_av_rotate( theInstr )) goto decode_success;
29297          goto decode_failure;
29298 
29299       /* AV Processor Control */
29300       case 0x604: case 0x644:             // mfvscr, mtvscr
29301          if (!allow_V) goto decode_noV;
29302          if (dis_av_procctl( theInstr )) goto decode_success;
29303          goto decode_failure;
29304 
29305       /* AV Vector Extract Element instructions */
29306       case 0x60D: case 0x64D: case 0x68D:   // vextublx, vextuhlx, vextuwlx
29307       case 0x70D: case 0x74D: case 0x78D:   // vextubrx, vextuhrx, vextuwrx
29308          if (!allow_V) goto decode_noV;
29309          if (dis_av_extract_element( theInstr )) goto decode_success;
29310          goto decode_failure;
29311 
29312 
29313       /* AV Floating Point Arithmetic */
29314       case 0x00A: case 0x04A:             // vaddfp, vsubfp
29315       case 0x10A: case 0x14A: case 0x18A: // vrefp, vrsqrtefp, vexptefp
29316       case 0x1CA:                         // vlogefp
29317       case 0x40A: case 0x44A:             // vmaxfp, vminfp
29318          if (!allow_V) goto decode_noV;
29319          if (dis_av_fp_arith( theInstr )) goto decode_success;
29320          goto decode_failure;
29321 
29322       /* AV Floating Point Round/Convert */
29323       case 0x20A: case 0x24A: case 0x28A: // vrfin, vrfiz, vrfip
29324       case 0x2CA:                         // vrfim
29325       case 0x30A: case 0x34A: case 0x38A: // vcfux, vcfsx, vctuxs
29326       case 0x3CA:                         // vctsxs
29327          if (!allow_V) goto decode_noV;
29328          if (dis_av_fp_convert( theInstr )) goto decode_success;
29329          goto decode_failure;
29330 
29331       /* AV Merge, Splat, Extract, Insert */
29332       case 0x00C: case 0x04C: case 0x08C: // vmrghb, vmrghh, vmrghw
29333       case 0x10C: case 0x14C: case 0x18C: // vmrglb, vmrglh, vmrglw
29334       case 0x20C: case 0x24C: case 0x28C: // vspltb, vsplth, vspltw
29335       case 0x20D: case 0x24D:             // vextractub, vextractuh,
29336       case 0x28D: case 0x2CD:             // vextractuw, vextractd,
29337       case 0x30D: case 0x34D:             // vinsertb, vinserth
29338       case 0x38D: case 0x3CD:             // vinsertw, vinsertd
29339       case 0x30C: case 0x34C: case 0x38C: // vspltisb, vspltish, vspltisw
29340          if (!allow_V) goto decode_noV;
29341          if (dis_av_permute( theInstr )) goto decode_success;
29342          goto decode_failure;
29343 
29344       case 0x68C: case 0x78C:             // vmrgow, vmrgew
29345           if (!allow_isa_2_07) goto decode_noP8;
29346           if (dis_av_permute( theInstr )) goto decode_success;
29347           goto decode_failure;
29348 
29349       /* AltiVec 128 bit integer multiply by 10 Instructions */
29350       case 0x201: case 0x001:               //vmul10uq, vmul10cuq
29351       case 0x241: case 0x041:               //vmul10euq, vmul10ceuq
29352           if (!allow_V) goto decode_noV;
29353           if (!allow_isa_3_0) goto decode_noP9;
29354           if (dis_av_mult10( theInstr )) goto decode_success;
29355           goto decode_failure;
29356 
29357       /* AV Pack, Unpack */
29358       case 0x00E: case 0x04E: case 0x08E: // vpkuhum, vpkuwum, vpkuhus
29359       case 0x0CE:                         // vpkuwus
29360       case 0x10E: case 0x14E: case 0x18E: // vpkshus, vpkswus, vpkshss
29361       case 0x1CE:                         // vpkswss
29362       case 0x20E: case 0x24E: case 0x28E: // vupkhsb, vupkhsh, vupklsb
29363       case 0x2CE:                         // vupklsh
29364       case 0x30E: case 0x34E: case 0x3CE: // vpkpx, vupkhpx, vupklpx
29365           if (!allow_V) goto decode_noV;
29366           if (dis_av_pack( theInstr )) goto decode_success;
29367           goto decode_failure;
29368 
29369       case 0x403: case 0x443: case 0x483:  // vabsdub, vabsduh, vabsduw
29370           if (!allow_V) goto decode_noV;
29371           if (dis_abs_diff( theInstr )) goto decode_success;
29372           goto decode_failure;
29373 
29374       case 0x44E: case 0x4CE: case 0x54E: // vpkudum, vpkudus, vpksdus
29375       case 0x5CE: case 0x64E: case 0x6cE: // vpksdss, vupkhsw, vupklsw
29376          if (!allow_isa_2_07) goto decode_noP8;
29377          if (dis_av_pack( theInstr )) goto decode_success;
29378          goto decode_failure;
29379 
29380       case 0x508: case 0x509:             // vcipher, vcipherlast
29381       case 0x548: case 0x549:             // vncipher, vncipherlast
29382       case 0x5C8:                         // vsbox
29383          if (!allow_isa_2_07) goto decode_noP8;
29384          if (dis_av_cipher( theInstr )) goto decode_success;
29385          goto decode_failure;
29386 
29387      /* AV Vector Extend Sign Instructions and
29388       * Vector Count Leading/Trailing zero Least-Significant bits Byte.
29389       * Vector Integer Negate Instructions
29390       */
29391       case 0x602:   // vextsb2w, vextsh2w, vextsb2d, vextsh2d, vextsw2d
29392                     // vclzlsbb and vctzlsbb
29393                     // vnegw, vnegd
29394                     // vprtybw, vprtybd, vprtybq
29395                     // vctzb, vctzh, vctzw, vctzd
29396          if (!allow_V) goto decode_noV;
29397          if (dis_av_extend_sign_count_zero( theInstr, allow_isa_3_0 ))
29398             goto decode_success;
29399          goto decode_failure;
29400 
29401       case 0x6C2: case 0x682:             // vshasigmaw, vshasigmad
29402          if (!allow_isa_2_07) goto decode_noP8;
29403          if (dis_av_hash( theInstr )) goto decode_success;
29404          goto decode_failure;
29405 
29406       case 0x702: case 0x742:             // vclzb, vclzh
29407       case 0x782: case 0x7c2:             // vclzw, vclzd
29408          if (!allow_isa_2_07) goto decode_noP8;
29409          if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
29410          goto decode_failure;
29411 
29412       case 0x703: case 0x743:             // vpopcntb, vpopcnth
29413       case 0x783: case 0x7c3:             // vpopcntw, vpopcntd
29414          if (!allow_isa_2_07) goto decode_noP8;
29415          if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
29416          goto decode_failure;
29417 
29418       case 0x50c:                         // vgbbd
29419       case 0x5cc:                         // vbpermd
29420          if (!allow_isa_2_07) goto decode_noP8;
29421          if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
29422          goto decode_failure;
29423 
29424       case 0x140: case 0x100:             // vaddcuq, vadduqm
29425       case 0x540: case 0x500:             // vsubcuq, vsubuqm
29426       case 0x54C:                         // vbpermq
29427          if (!allow_V) goto decode_noV;
29428          if (dis_av_quad( theInstr)) goto decode_success;
29429          goto decode_failure;
29430 
29431       default:
29432          break;  // Fall through...
29433       }
29434 
29435       opc2 = IFIELD(theInstr, 0, 10);
29436       switch (opc2) {
29437 
29438       /* AV Compare */
29439       case 0x006: case 0x007: case 0x107: // vcmpequb, vcmpneb, vcmpnezb
29440       case 0x046: case 0x047: case 0x147: // vcmpequh, vcmpneh, vcmpnezh
29441       case 0x086: case 0x087: case 0x187: // vcmpequw, vcmpnew, vcmpnezw
29442       case 0x206: case 0x246: case 0x286: // vcmpgtub, vcmpgtuh, vcmpgtuw
29443       case 0x306: case 0x346: case 0x386: // vcmpgtsb, vcmpgtsh, vcmpgtsw
29444          if (!allow_V) goto decode_noV;
29445          if (dis_av_cmp( theInstr )) goto decode_success;
29446          goto decode_failure;
29447 
29448       case 0x0C7:                         // vcmpequd
29449       case 0x2C7:                         // vcmpgtud
29450       case 0x3C7:                         // vcmpgtsd
29451           if (!allow_isa_2_07) goto decode_noP8;
29452           if (dis_av_cmp( theInstr )) goto decode_success;
29453           goto decode_failure;
29454 
29455       /* AV Floating Point Compare */
29456       case 0x0C6: case 0x1C6: case 0x2C6: // vcmpeqfp, vcmpgefp, vcmpgtfp
29457       case 0x3C6:                         // vcmpbfp
29458          if (!allow_V) goto decode_noV;
29459          if (dis_av_fp_cmp( theInstr )) goto decode_success;
29460          goto decode_failure;
29461 
29462       default:
29463          goto decode_failure;
29464       }
29465       break;
29466 
29467    default:
29468       goto decode_failure;
29469 
29470    decode_noF:
29471       vassert(!allow_F);
29472       if (sigill_diag)
29473          vex_printf("disInstr(ppc): found the Floating Point instruction 0x%x that\n"
29474 		    "can't be handled by Valgrind on this host.  This instruction\n"
29475 		    "requires a host that supports Floating Point instructions.\n",
29476 		    theInstr);
29477       goto not_supported;
29478    decode_noV:
29479       vassert(!allow_V);
29480       if (sigill_diag)
29481          vex_printf("disInstr(ppc): found an AltiVec or an e500 instruction 0x%x\n"
29482 		    "that can't be handled by Valgrind.  If this instruction is an\n"
29483 		    "Altivec instruction, Valgrind must be run on a host that supports"
29484 		    "AltiVec instructions.  If the application was compiled for e500, then\n"
29485 		    "unfortunately Valgrind does not yet support e500 instructions.\n",
29486 		    theInstr);
29487       goto not_supported;
29488    decode_noVX:
29489       vassert(!allow_VX);
29490       if (sigill_diag)
29491          vex_printf("disInstr(ppc): found the instruction 0x%x that is defined in the\n"
29492 		    "Power ISA 2.06 ABI but can't be handled by Valgrind on this host.\n"
29493 		    "This instruction \nrequires a host that supports the ISA 2.06 ABI.\n",
29494 		    theInstr);
29495       goto not_supported;
29496    decode_noFX:
29497       vassert(!allow_FX);
29498       if (sigill_diag)
29499          vex_printf("disInstr(ppc): found the General Purpose-Optional instruction 0x%x\n"
29500 		    "that can't be handled by Valgrind on this host. This instruction\n"
29501 		    "requires a host that supports the General Purpose-Optional instructions.\n",
29502 		    theInstr);
29503       goto not_supported;
29504    decode_noGX:
29505       vassert(!allow_GX);
29506       if (sigill_diag)
29507          vex_printf("disInstr(ppc): found the Graphics-Optional instruction 0x%x\n"
29508 		    "that can't be handled by Valgrind on this host. This instruction\n"
29509 		    "requires a host that supports the Graphic-Optional instructions.\n",
29510 		    theInstr);
29511       goto not_supported;
29512    decode_noDFP:
29513       vassert(!allow_DFP);
29514       if (sigill_diag)
29515          vex_printf("disInstr(ppc): found the decimal floating point (DFP) instruction 0x%x\n"
29516 		    "that can't be handled by Valgrind on this host.  This instruction\n"
29517 		    "requires a host that supports DFP instructions.\n",
29518 		    theInstr);
29519       goto not_supported;
29520    decode_noP8:
29521       vassert(!allow_isa_2_07);
29522       if (sigill_diag)
29523          vex_printf("disInstr(ppc): found the Power 8 instruction 0x%x that can't be handled\n"
29524 		    "by Valgrind on this host.  This instruction requires a host that\n"
29525 		    "supports Power 8 instructions.\n",
29526 		    theInstr);
29527       goto not_supported;
29528 
29529    decode_noP9:
29530       vassert(!allow_isa_3_0);
29531       if (sigill_diag)
29532          vex_printf("disInstr(ppc): found the Power 9 instruction 0x%x that can't be handled\n"
29533                     "by Valgrind on this host.  This instruction requires a host that\n"
29534 		    "supports Power 9 instructions.\n",
29535 		    theInstr);
29536       goto not_supported;
29537 
29538    decode_failure:
29539    /* All decode failures end up here. */
29540    opc2 = (theInstr) & 0x7FF;
29541    if (sigill_diag) {
29542       vex_printf("disInstr(ppc): unhandled instruction: "
29543                  "0x%x\n", theInstr);
29544       vex_printf("                 primary %d(0x%x), secondary %u(0x%x)\n",
29545                  opc1, opc1, opc2, opc2);
29546    }
29547 
29548    not_supported:
29549    /* Tell the dispatcher that this insn cannot be decoded, and so has
29550       not been executed, and (is currently) the next to be executed.
29551       CIA should be up-to-date since it made so at the start of each
29552       insn, but nevertheless be paranoid and update it again right
29553       now. */
29554    putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) );
29555    dres.len         = 0;
29556    dres.whatNext    = Dis_StopHere;
29557    dres.jk_StopHere = Ijk_NoDecode;
29558    dres.continueAt  = 0;
29559    return dres;
29560    } /* switch (opc) for the main (primary) opcode switch. */
29561 
29562   decode_success:
29563    /* All decode successes end up here. */
29564    switch (dres.whatNext) {
29565       case Dis_Continue:
29566          putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr + 4));
29567          break;
29568       case Dis_ResteerU:
29569       case Dis_ResteerC:
29570          putGST( PPC_GST_CIA, mkSzImm(ty, dres.continueAt));
29571          break;
29572       case Dis_StopHere:
29573          break;
29574       default:
29575          vassert(0);
29576    }
29577    DIP("\n");
29578 
29579    if (dres.len == 0) {
29580       dres.len = 4;
29581    } else {
29582       vassert(dres.len == 20);
29583    }
29584    return dres;
29585 }
29586 
29587 #undef DIP
29588 #undef DIS
29589 
29590 
29591 /*------------------------------------------------------------*/
29592 /*--- Top-level fn                                         ---*/
29593 /*------------------------------------------------------------*/
29594 
29595 /* Disassemble a single instruction into IR.  The instruction
29596    is located in host memory at &guest_code[delta]. */
29597 
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)29598 DisResult disInstr_PPC ( IRSB*        irsb_IN,
29599                          Bool         (*resteerOkFn) ( void*, Addr ),
29600                          Bool         resteerCisOk,
29601                          void*        callback_opaque,
29602                          const UChar* guest_code_IN,
29603                          Long         delta,
29604                          Addr         guest_IP,
29605                          VexArch      guest_arch,
29606                          const VexArchInfo* archinfo,
29607                          const VexAbiInfo*  abiinfo,
29608                          VexEndness   host_endness_IN,
29609                          Bool         sigill_diag_IN )
29610 {
29611    IRType     ty;
29612    DisResult  dres;
29613    UInt       mask32, mask64;
29614    UInt hwcaps_guest = archinfo->hwcaps;
29615 
29616    vassert(guest_arch == VexArchPPC32 || guest_arch == VexArchPPC64);
29617 
29618    /* global -- ick */
29619    mode64 = guest_arch == VexArchPPC64;
29620    ty = mode64 ? Ity_I64 : Ity_I32;
29621    if (!mode64 && (host_endness_IN == VexEndnessLE)) {
29622       vex_printf("disInstr(ppc): Little Endian 32-bit mode is not supported\n");
29623       dres.len         = 0;
29624       dres.whatNext    = Dis_StopHere;
29625       dres.jk_StopHere = Ijk_NoDecode;
29626       dres.continueAt   = 0;
29627       dres.hint        = Dis_HintNone;
29628       return dres;
29629    }
29630 
29631    /* do some sanity checks */
29632    mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V
29633             | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX
29634             | VEX_HWCAPS_PPC32_DFP | VEX_HWCAPS_PPC32_ISA2_07;
29635 
29636    mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX
29637             | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX | VEX_HWCAPS_PPC64_DFP
29638             | VEX_HWCAPS_PPC64_ISA2_07 | VEX_HWCAPS_PPC64_ISA3_0;
29639 
29640    if (mode64) {
29641       vassert((hwcaps_guest & mask32) == 0);
29642    } else {
29643       vassert((hwcaps_guest & mask64) == 0);
29644    }
29645 
29646    /* Set globals (see top of this file) */
29647    guest_code           = guest_code_IN;
29648    irsb                 = irsb_IN;
29649    host_endness         = host_endness_IN;
29650 
29651    guest_CIA_curr_instr = mkSzAddr(ty, guest_IP);
29652    guest_CIA_bbstart    = mkSzAddr(ty, guest_IP - delta);
29653 
29654    dres = disInstr_PPC_WRK ( resteerOkFn, resteerCisOk, callback_opaque,
29655                              delta, archinfo, abiinfo, sigill_diag_IN);
29656 
29657    return dres;
29658 }
29659 
29660 /*--------------------------------------------------------------------*/
29661 /*--- end                                         guest_ppc_toIR.c ---*/
29662 /*--------------------------------------------------------------------*/
29663