• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*--------------------------------------------------------------------*/
3 /*--- begin                                       guest_ppc_toIR.c ---*/
4 /*--------------------------------------------------------------------*/
5 
6 /*
7    This file is part of Valgrind, a dynamic binary instrumentation
8    framework.
9 
10    Copyright (C) 2004-2015 OpenWorks LLP
11       info@open-works.net
12 
13    This program is free software; you can redistribute it and/or
14    modify it under the terms of the GNU General Public License as
15    published by the Free Software Foundation; either version 2 of the
16    License, or (at your option) any later version.
17 
18    This program is distributed in the hope that it will be useful, but
19    WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21    General Public License for more details.
22 
23    You should have received a copy of the GNU General Public License
24    along with this program; if not, write to the Free Software
25    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26    02110-1301, USA.
27 
28    The GNU General Public License is contained in the file COPYING.
29 
30    Neither the names of the U.S. Department of Energy nor the
31    University of California nor the names of its contributors may be
32    used to endorse or promote products derived from this software
33    without prior written permission.
34 */
35 
36 /* TODO 18/Nov/05:
37 
38    Spot rld... cases which are simply left/right shifts and emit
39    Shl64/Shr64 accordingly.
40 
41    Altivec
42    - datastream insns
43    - lvxl,stvxl: load/store with 'least recently used' hint
44    - vexptefp, vlogefp
45 
46    LIMITATIONS:
47 
48    Various, including:
49 
50    - Some invalid forms of lswi and lswx are accepted when they should
51      not be.
52 
53    - Floating Point:
54      - All exceptions disabled in FPSCR
55      - condition codes not set in FPSCR
56 
57    - Altivec floating point:
58      - vmaddfp, vnmsubfp
59        Because we're using Java/IEEE mode (FPSCR[NJ]), rather than the
60        system default of Non-Java mode, we get some small errors
61        (lowest bit only).
62        This is because Non-Java mode brutally hacks denormalised results
63        to zero, whereas we keep maximum accuracy.  However, using
64        Non-Java mode would give us more inaccuracy, as our intermediate
65        results would then be zeroed, too.
66 
67    - AbiHints for the stack red zone are only emitted for
68        unconditional calls and returns (bl, blr).  They should also be
69        emitted for conditional calls and returns, but we don't have a
70        way to express that right now.  Ah well.
71 
72    - Uses of Iop_{Add,Sub,Mul}32Fx4: the backend (host_ppc_isel.c)
73        ignores the rounding mode, and generates code that assumes
74        round-to-nearest.  This means V will compute incorrect results
75        for uses of these IROps when the rounding mode (first) arg is
76        not mkU32(Irrm_NEAREST).
77 */
78 
79 /* "Special" instructions.
80 
81    This instruction decoder can decode four special instructions
82    which mean nothing natively (are no-ops as far as regs/mem are
83    concerned) but have meaning for supporting Valgrind.  A special
84    instruction is flagged by a 16-byte preamble:
85 
86       32-bit mode: 5400183E 5400683E 5400E83E 5400983E
87                    (rlwinm 0,0,3,0,31; rlwinm 0,0,13,0,31;
88                     rlwinm 0,0,29,0,31; rlwinm 0,0,19,0,31)
89 
90       64-bit mode: 78001800 78006800 7800E802 78009802
91                    (rotldi 0,0,3; rotldi 0,0,13;
92                     rotldi 0,0,61; rotldi 0,0,51)
93 
94    Following that, one of the following 3 are allowed
95    (standard interpretation in parentheses):
96 
97       7C210B78 (or 1,1,1)   %R3 = client_request ( %R4 )
98       7C421378 (or 2,2,2)   %R3 = guest_NRADDR
99       7C631B78 (or 3,3,3)   branch-and-link-to-noredir %R11  Big endian
100       7C631B78 (or 3,3,3)   branch-and-link-to-noredir %R12  Little endian
101       7C842378 (or 4,4,4)   %R3 = guest_NRADDR_GPR2
102       7CA52B78 (or 5,5,5)   IR injection
103 
104    Any other bytes following the 16-byte preamble are illegal and
105    constitute a failure in instruction decoding.  This all assumes
106    that the preamble will never occur except in specific code
107    fragments designed for Valgrind to catch.
108 */
109 
110 /*  Little Endian notes  */
111 /*
112  * Vector operations in little Endian mode behave in non-obvious ways at times.
113  * Below is an attempt at explaining this.
114  *
115  * LE/BE vector example
116  *   With a vector of unsigned ints declared as follows:
117  *     vector unsigned int vec_inA =
118                             { 0x11111111, 0x22222222, 0x33333333, 0x44444444 };
119  *   The '0x11111111' word is word zero in both LE and BE format.  But the
120  *   loaded vector register will have word zero on the far left in BE mode and
121  *   on the far right in LE mode. The lvx and stvx instructions work naturally
122  *   for whatever endianness is in effect.  For example, in LE mode, the stvx
123  *   stores word zero (far right word) of the vector at the lowest memory
124  *   address of the EA; in BE mode, stvx still stores word zero at the lowest
125  *   memory address, but with word zero interpreted as the one at the far left
126  *   of the register.
127  *
128  *   The lxvd2x and stxvd2x instructions are not so well suited for LE mode.
129  *   When the compiler generates an lxvd2x instruction to load the
130  *   above-declared vector of unsigned integers, it loads the vector as two
131  *   double words, but they are in BE word-wise format.  To put the vector in
132  *   the right order for LE, the compiler also generates an xxswapd after the
133  *   load, which puts it in proper LE format.  Similarly, the stxvd2x
134  *   instruction has a BE bias, storing the vector in BE word-wise format. But
135  *   the compiler also generates an xxswapd prior to the store, thus ensuring
136  *   the vector is stored in memory in the correct LE order.
137  *
138  *   Vector-flavored Iops, such Iop_V128Hito64, reference the hi and lo parts
139  *   of a double words and words within a vector.  Because of the reverse order
140  *   of numbering for LE as described above, the high part refers to word 1 in
141  *   LE format. When input data is saved to a guest state vector register
142  *   (e.g., via Iop_64HLtoV128), it is first saved to memory and then the
143  *   register is loaded via PPCInstr_AvLdSt, which does an lvx instruction.
144  *   The saving of the data to memory must be done in proper LE order.  For the
145  *   inverse operation of extracting data from a vector register (e.g.,
146  *   Iop_V128Hito64), the register is first saved (by PPCInstr_AvLdSt resulting
147  *   in stvx), and then integer registers are loaded from the memory location
148  *   from where the vector register was saved.  Again, this must be done in
149  *   proper LE order.  So for these various vector Iops, we have LE-specific
150  *   code in host_ppc_isel.c
151  *
152  *   Another unique behavior of vectors in LE mode is with the vector scalar
153  *   (VSX) operations that operate on "double word 0" of the source register,
154  *   storing the result in "double word 0" of the output vector register.  For
155  *   these operations, "double word 0" is interpreted as "high half of the
156  *   register" (i.e, the part on the left side).
157  *
158  */
159 /* Translates PPC32/64 code to IR. */
160 
161 /* References
162 
163 #define PPC32
164    "PowerPC Microprocessor Family:
165     The Programming Environments Manual for 32-Bit Microprocessors"
166     02/21/2000
167     http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2
168 
169 #define PPC64
170    "PowerPC Microprocessor Family:
171     Programming Environments Manual for 64-Bit Microprocessors"
172     06/10/2003
173    http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/F7E732FF811F783187256FDD004D3797
174 
175 #define AV
176    "PowerPC Microprocessor Family:
177     AltiVec(TM) Technology Programming Environments Manual"
178     07/10/2003
179    http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/FBFA164F824370F987256D6A006F424D
180 */
181 
182 #include "libvex_basictypes.h"
183 #include "libvex_ir.h"
184 #include "libvex.h"
185 #include "libvex_emnote.h"
186 #include "libvex_guest_ppc32.h"
187 #include "libvex_guest_ppc64.h"
188 
189 #include "main_util.h"
190 #include "main_globals.h"
191 #include "guest_generic_bb_to_IR.h"
192 #include "guest_ppc_defs.h"
193 
194 /*------------------------------------------------------------*/
195 /*--- Globals                                              ---*/
196 /*------------------------------------------------------------*/
197 
198 /* These are set at the start of the translation of an insn, right
199    down in disInstr_PPC, so that we don't have to pass them around
200    endlessly.  They are all constant during the translation of any
201    given insn. */
202 
203 /* We need to know this to do sub-register accesses correctly. */
204 static VexEndness host_endness;
205 
206 /* Pointer to the guest code area. */
207 static const UChar* guest_code;
208 
209 /* The guest address corresponding to guest_code[0]. */
210 static Addr64 guest_CIA_bbstart;
211 
212 /* The guest address for the instruction currently being
213    translated. */
214 static Addr64 guest_CIA_curr_instr;
215 
216 /* The IRSB* into which we're generating code. */
217 static IRSB* irsb;
218 
219 /* Is our guest binary 32 or 64bit?  Set at each call to
220    disInstr_PPC below. */
221 static Bool mode64 = False;
222 
223 // Given a pointer to a function as obtained by "& functionname" in C,
224 // produce a pointer to the actual entry point for the function.  For
225 // most platforms it's the identity function.  Unfortunately, on
226 // ppc64-linux it isn't (sigh)
fnptr_to_fnentry(const VexAbiInfo * vbi,void * f)227 static void* fnptr_to_fnentry( const VexAbiInfo* vbi, void* f )
228 {
229    if (vbi->host_ppc_calls_use_fndescrs) {
230       /* f is a pointer to a 3-word function descriptor, of which the
231          first word is the entry address. */
232       /* note, this is correct even with cross-jitting, since this is
233          purely a host issue, not a guest one. */
234       HWord* fdescr = (HWord*)f;
235       return (void*)(fdescr[0]);
236    } else {
237       /* Simple; "& f" points directly at the code for f. */
238       return f;
239    }
240 }
241 
242 #define SIGN_BIT  0x8000000000000000ULL
243 #define SIGN_MASK 0x7fffffffffffffffULL
244 #define SIGN_BIT32  0x80000000
245 #define SIGN_MASK32 0x7fffffff
246 
247 
248 /*------------------------------------------------------------*/
249 /*--- Debugging output                                     ---*/
250 /*------------------------------------------------------------*/
251 
252 #define DIP(format, args...)           \
253    if (vex_traceflags & VEX_TRACE_FE)  \
254       vex_printf(format, ## args)
255 
256 #define DIS(buf, format, args...)      \
257    if (vex_traceflags & VEX_TRACE_FE)  \
258       vex_sprintf(buf, format, ## args)
259 
260 
261 /*------------------------------------------------------------*/
262 /*--- Offsets of various parts of the ppc32/64 guest state ---*/
263 /*------------------------------------------------------------*/
264 
265 #define offsetofPPCGuestState(_x) \
266    (mode64 ? offsetof(VexGuestPPC64State, _x) : \
267              offsetof(VexGuestPPC32State, _x))
268 
269 #define OFFB_CIA         offsetofPPCGuestState(guest_CIA)
270 #define OFFB_IP_AT_SYSCALL offsetofPPCGuestState(guest_IP_AT_SYSCALL)
271 #define OFFB_SPRG3_RO    offsetofPPCGuestState(guest_SPRG3_RO)
272 #define OFFB_LR          offsetofPPCGuestState(guest_LR)
273 #define OFFB_CTR         offsetofPPCGuestState(guest_CTR)
274 #define OFFB_XER_SO      offsetofPPCGuestState(guest_XER_SO)
275 #define OFFB_XER_OV      offsetofPPCGuestState(guest_XER_OV)
276 #define OFFB_XER_CA      offsetofPPCGuestState(guest_XER_CA)
277 #define OFFB_XER_BC      offsetofPPCGuestState(guest_XER_BC)
278 #define OFFB_FPROUND     offsetofPPCGuestState(guest_FPROUND)
279 #define OFFB_DFPROUND    offsetofPPCGuestState(guest_DFPROUND)
280 #define OFFB_VRSAVE      offsetofPPCGuestState(guest_VRSAVE)
281 #define OFFB_VSCR        offsetofPPCGuestState(guest_VSCR)
282 #define OFFB_EMNOTE      offsetofPPCGuestState(guest_EMNOTE)
283 #define OFFB_CMSTART     offsetofPPCGuestState(guest_CMSTART)
284 #define OFFB_CMLEN       offsetofPPCGuestState(guest_CMLEN)
285 #define OFFB_NRADDR      offsetofPPCGuestState(guest_NRADDR)
286 #define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2)
287 #define OFFB_TFHAR       offsetofPPCGuestState(guest_TFHAR)
288 #define OFFB_TEXASR      offsetofPPCGuestState(guest_TEXASR)
289 #define OFFB_TEXASRU     offsetofPPCGuestState(guest_TEXASRU)
290 #define OFFB_TFIAR       offsetofPPCGuestState(guest_TFIAR)
291 #define OFFB_PPR         offsetofPPCGuestState(guest_PPR)
292 #define OFFB_PSPB        offsetofPPCGuestState(guest_PSPB)
293 
294 
295 /*------------------------------------------------------------*/
296 /*--- Extract instruction fields                          --- */
297 /*------------------------------------------------------------*/
298 
299 /* Extract field from insn, given idx (zero = lsb) and field length */
300 #define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1))
301 
302 /* Extract primary opcode, instr[31:26] */
ifieldOPC(UInt instr)303 static UChar ifieldOPC( UInt instr ) {
304    return toUChar( IFIELD( instr, 26, 6 ) );
305 }
306 
307 /* Extract 10-bit secondary opcode, instr[10:1] */
ifieldOPClo10(UInt instr)308 static UInt ifieldOPClo10 ( UInt instr) {
309    return IFIELD( instr, 1, 10 );
310 }
311 
312 /* Extract 9-bit secondary opcode, instr[9:1] */
ifieldOPClo9(UInt instr)313 static UInt ifieldOPClo9 ( UInt instr) {
314    return IFIELD( instr, 1, 9 );
315 }
316 
317 /* Extract 8-bit secondary opcode, instr[8:1] */
ifieldOPClo8(UInt instr)318 static UInt ifieldOPClo8 ( UInt instr) {
319    return IFIELD( instr, 1, 8 );
320 }
321 
322 /* Extract 5-bit secondary opcode, instr[5:1] */
ifieldOPClo5(UInt instr)323 static UInt ifieldOPClo5 ( UInt instr) {
324    return IFIELD( instr, 1, 5 );
325 }
326 
327 /* Extract RD (destination register) field, instr[25:21] */
ifieldRegDS(UInt instr)328 static UChar ifieldRegDS( UInt instr ) {
329    return toUChar( IFIELD( instr, 21, 5 ) );
330 }
331 
332 /* Extract XT (destination register) field, instr[0,25:21] */
ifieldRegXT(UInt instr)333 static UChar ifieldRegXT ( UInt instr )
334 {
335   UChar upper_bit = toUChar (IFIELD (instr, 0, 1));
336   UChar lower_bits = toUChar (IFIELD (instr, 21, 5));
337   return (upper_bit << 5) | lower_bits;
338 }
339 
340 /* Extract XS (store source register) field, instr[0,25:21] */
ifieldRegXS(UInt instr)341 static inline UChar ifieldRegXS ( UInt instr )
342 {
343   return ifieldRegXT ( instr );
344 }
345 
346 /* Extract RA (1st source register) field, instr[20:16] */
ifieldRegA(UInt instr)347 static UChar ifieldRegA ( UInt instr ) {
348    return toUChar( IFIELD( instr, 16, 5 ) );
349 }
350 
351 /* Extract XA (1st source register) field, instr[2,20:16] */
ifieldRegXA(UInt instr)352 static UChar ifieldRegXA ( UInt instr )
353 {
354   UChar upper_bit = toUChar (IFIELD (instr, 2, 1));
355   UChar lower_bits = toUChar (IFIELD (instr, 16, 5));
356   return (upper_bit << 5) | lower_bits;
357 }
358 
359 /* Extract RB (2nd source register) field, instr[15:11] */
ifieldRegB(UInt instr)360 static UChar ifieldRegB ( UInt instr ) {
361    return toUChar( IFIELD( instr, 11, 5 ) );
362 }
363 
364 /* Extract XB (2nd source register) field, instr[1,15:11] */
ifieldRegXB(UInt instr)365 static UChar ifieldRegXB ( UInt instr )
366 {
367   UChar upper_bit = toUChar (IFIELD (instr, 1, 1));
368   UChar lower_bits = toUChar (IFIELD (instr, 11, 5));
369   return (upper_bit << 5) | lower_bits;
370 }
371 
372 /* Extract RC (3rd source register) field, instr[10:6] */
ifieldRegC(UInt instr)373 static UChar ifieldRegC ( UInt instr ) {
374    return toUChar( IFIELD( instr, 6, 5 ) );
375 }
376 
377 /* Extract XC (3rd source register) field, instr[3,10:6] */
ifieldRegXC(UInt instr)378 static UChar ifieldRegXC ( UInt instr )
379 {
380   UChar upper_bit = toUChar (IFIELD (instr, 3, 1));
381   UChar lower_bits = toUChar (IFIELD (instr, 6, 5));
382   return (upper_bit << 5) | lower_bits;
383 }
384 
385 /* Extract bit 10, instr[10] */
ifieldBIT10(UInt instr)386 static UChar ifieldBIT10 ( UInt instr ) {
387    return toUChar( IFIELD( instr, 10, 1 ) );
388 }
389 
390 /* Extract 2nd lowest bit, instr[1] */
ifieldBIT1(UInt instr)391 static UChar ifieldBIT1 ( UInt instr ) {
392    return toUChar( IFIELD( instr, 1, 1 ) );
393 }
394 
395 /* Extract lowest bit, instr[0] */
ifieldBIT0(UInt instr)396 static UChar ifieldBIT0 ( UInt instr ) {
397    return toUChar( instr & 0x1 );
398 }
399 
400 /* Extract unsigned bottom half, instr[15:0] */
ifieldUIMM16(UInt instr)401 static UInt ifieldUIMM16 ( UInt instr ) {
402    return instr & 0xFFFF;
403 }
404 
405 /* Extract unsigned bottom 26 bits, instr[25:0] */
ifieldUIMM26(UInt instr)406 static UInt ifieldUIMM26 ( UInt instr ) {
407    return instr & 0x3FFFFFF;
408 }
409 
410 /* Extract DM field, instr[9:8] */
ifieldDM(UInt instr)411 static UChar ifieldDM ( UInt instr ) {
412    return toUChar( IFIELD( instr, 8, 2 ) );
413 }
414 
415 /* Extract SHW field, instr[9:8] */
ifieldSHW(UInt instr)416 static inline UChar ifieldSHW ( UInt instr )
417 {
418   return ifieldDM ( instr );
419 }
420 
421 /*------------------------------------------------------------*/
422 /*--- Guest-state identifiers                              ---*/
423 /*------------------------------------------------------------*/
424 
425 typedef enum {
426     PPC_GST_CIA,    // Current Instruction Address
427     PPC_GST_LR,     // Link Register
428     PPC_GST_CTR,    // Count Register
429     PPC_GST_XER,    // Overflow, carry flags, byte count
430     PPC_GST_CR,     // Condition Register
431     PPC_GST_FPSCR,  // Floating Point Status/Control Register
432     PPC_GST_VRSAVE, // Vector Save/Restore Register
433     PPC_GST_VSCR,   // Vector Status and Control Register
434     PPC_GST_EMWARN, // Emulation warnings
435     PPC_GST_CMSTART,// For icbi: start of area to invalidate
436     PPC_GST_CMLEN,  // For icbi: length of area to invalidate
437     PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn
438     PPC_GST_SPRG3_RO, // SPRG3
439     PPC_GST_TFHAR,  // Transactional Failure Handler Address Register
440     PPC_GST_TFIAR,  // Transactional Failure Instruction Address Register
441     PPC_GST_TEXASR, // Transactional EXception And Summary Register
442     PPC_GST_TEXASRU, // Transactional EXception And Summary Register Upper
443     PPC_GST_PPR,     // Program Priority register
444     PPC_GST_PPR32,   // Upper 32-bits of Program Priority register
445     PPC_GST_PSPB,    /* Problem State Priority Boost register, Note, the
446                       * register is initialized to a non-zero value.  Currently
447                       * Valgrind is not supporting the register value to
448                       * automatically decrement. Could be added later if
449                       * needed.
450                       */
451     PPC_GST_MAX
452 } PPC_GST;
453 
454 #define MASK_FPSCR_RN   0x3ULL  // Binary floating point rounding mode
455 #define MASK_FPSCR_DRN  0x700000000ULL // Decimal floating point rounding mode
456 #define MASK_VSCR_VALID 0x00010001
457 
458 
459 /*------------------------------------------------------------*/
460 /*---  FP Helpers                                          ---*/
461 /*------------------------------------------------------------*/
462 
463 /* Produce the 32-bit pattern corresponding to the supplied
464    float. */
float_to_bits(Float f)465 static UInt float_to_bits ( Float f )
466 {
467    union { UInt i; Float f; } u;
468    vassert(4 == sizeof(UInt));
469    vassert(4 == sizeof(Float));
470    vassert(4 == sizeof(u));
471    u.f = f;
472    return u.i;
473 }
474 
475 
476 /*------------------------------------------------------------*/
477 /*--- Misc Helpers                                         ---*/
478 /*------------------------------------------------------------*/
479 
480 /* Generate mask with 1's from 'begin' through 'end',
481    wrapping if begin > end.
482    begin->end works from right to left, 0=lsb
483 */
MASK32(UInt begin,UInt end)484 static UInt MASK32( UInt begin, UInt end )
485 {
486    UInt m1, m2, mask;
487    vassert(begin < 32);
488    vassert(end < 32);
489    m1   = ((UInt)(-1)) << begin;
490    m2   = ((UInt)(-1)) << end << 1;
491    mask = m1 ^ m2;
492    if (begin > end) mask = ~mask;  // wrap mask
493    return mask;
494 }
495 
MASK64(UInt begin,UInt end)496 static ULong MASK64( UInt begin, UInt end )
497 {
498    ULong m1, m2, mask;
499    vassert(begin < 64);
500    vassert(end < 64);
501    m1   = ((ULong)(-1)) << begin;
502    m2   = ((ULong)(-1)) << end << 1;
503    mask = m1 ^ m2;
504    if (begin > end) mask = ~mask;  // wrap mask
505    return mask;
506 }
507 
nextInsnAddr(void)508 static Addr64 nextInsnAddr( void )
509 {
510    return guest_CIA_curr_instr + 4;
511 }
512 
513 
514 /*------------------------------------------------------------*/
515 /*--- Helper bits and pieces for deconstructing the        ---*/
516 /*--- ppc32/64 insn stream.                                ---*/
517 /*------------------------------------------------------------*/
518 
519 /* Add a statement to the list held by "irsb". */
stmt(IRStmt * st)520 static void stmt ( IRStmt* st )
521 {
522    addStmtToIRSB( irsb, st );
523 }
524 
525 /* Generate a new temporary of the given type. */
newTemp(IRType ty)526 static IRTemp newTemp ( IRType ty )
527 {
528    vassert(isPlausibleIRType(ty));
529    return newIRTemp( irsb->tyenv, ty );
530 }
531 
532 /* Various simple conversions */
533 
extend_s_5to8(UChar x)534 static UChar extend_s_5to8 ( UChar x )
535 {
536    return toUChar((((Int)x) << 27) >> 27);
537 }
538 
extend_s_8to32(UChar x)539 static UInt extend_s_8to32( UChar x )
540 {
541    return (UInt)((((Int)x) << 24) >> 24);
542 }
543 
extend_s_16to32(UInt x)544 static UInt extend_s_16to32 ( UInt x )
545 {
546    return (UInt)((((Int)x) << 16) >> 16);
547 }
548 
extend_s_16to64(UInt x)549 static ULong extend_s_16to64 ( UInt x )
550 {
551    return (ULong)((((Long)x) << 48) >> 48);
552 }
553 
extend_s_26to64(UInt x)554 static ULong extend_s_26to64 ( UInt x )
555 {
556    return (ULong)((((Long)x) << 38) >> 38);
557 }
558 
extend_s_32to64(UInt x)559 static ULong extend_s_32to64 ( UInt x )
560 {
561    return (ULong)((((Long)x) << 32) >> 32);
562 }
563 
564 /* Do a proper-endian load of a 32-bit word, regardless of the endianness
565    of the underlying host. */
getUIntPPCendianly(const UChar * p)566 static UInt getUIntPPCendianly ( const UChar* p )
567 {
568    UInt w = 0;
569    if (host_endness == VexEndnessBE) {
570        w = (w << 8) | p[0];
571        w = (w << 8) | p[1];
572        w = (w << 8) | p[2];
573        w = (w << 8) | p[3];
574    } else {
575        w = (w << 8) | p[3];
576        w = (w << 8) | p[2];
577        w = (w << 8) | p[1];
578        w = (w << 8) | p[0];
579    }
580    return w;
581 }
582 
583 
584 /*------------------------------------------------------------*/
585 /*--- Helpers for constructing IR.                         ---*/
586 /*------------------------------------------------------------*/
587 
assign(IRTemp dst,IRExpr * e)588 static void assign ( IRTemp dst, IRExpr* e )
589 {
590    stmt( IRStmt_WrTmp(dst, e) );
591 }
592 
593 /* This generates a normal (non store-conditional) store. */
store(IRExpr * addr,IRExpr * data)594 static void store ( IRExpr* addr, IRExpr* data )
595 {
596    IRType tyA = typeOfIRExpr(irsb->tyenv, addr);
597    vassert(tyA == Ity_I32 || tyA == Ity_I64);
598 
599    if (host_endness == VexEndnessBE)
600       stmt( IRStmt_Store(Iend_BE, addr, data) );
601    else
602       stmt( IRStmt_Store(Iend_LE, addr, data) );
603 }
604 
unop(IROp op,IRExpr * a)605 static IRExpr* unop ( IROp op, IRExpr* a )
606 {
607    return IRExpr_Unop(op, a);
608 }
609 
binop(IROp op,IRExpr * a1,IRExpr * a2)610 static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
611 {
612    return IRExpr_Binop(op, a1, a2);
613 }
614 
triop(IROp op,IRExpr * a1,IRExpr * a2,IRExpr * a3)615 static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 )
616 {
617    return IRExpr_Triop(op, a1, a2, a3);
618 }
619 
qop(IROp op,IRExpr * a1,IRExpr * a2,IRExpr * a3,IRExpr * a4)620 static IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2,
621                               IRExpr* a3, IRExpr* a4 )
622 {
623    return IRExpr_Qop(op, a1, a2, a3, a4);
624 }
625 
mkexpr(IRTemp tmp)626 static IRExpr* mkexpr ( IRTemp tmp )
627 {
628    return IRExpr_RdTmp(tmp);
629 }
630 
mkU8(UChar i)631 static IRExpr* mkU8 ( UChar i )
632 {
633    return IRExpr_Const(IRConst_U8(i));
634 }
635 
mkU16(UInt i)636 static IRExpr* mkU16 ( UInt i )
637 {
638    return IRExpr_Const(IRConst_U16(i));
639 }
640 
mkU32(UInt i)641 static IRExpr* mkU32 ( UInt i )
642 {
643    return IRExpr_Const(IRConst_U32(i));
644 }
645 
mkU64(ULong i)646 static IRExpr* mkU64 ( ULong i )
647 {
648    return IRExpr_Const(IRConst_U64(i));
649 }
650 
mkV128(UShort i)651 static IRExpr* mkV128 ( UShort i )
652 {
653    vassert(i == 0 || i == 0xffff);
654    return IRExpr_Const(IRConst_V128(i));
655 }
656 
657 /* This generates a normal (non load-linked) load. */
load(IRType ty,IRExpr * addr)658 static IRExpr* load ( IRType ty, IRExpr* addr )
659 {
660    if (host_endness == VexEndnessBE)
661       return IRExpr_Load(Iend_BE, ty, addr);
662    else
663       return IRExpr_Load(Iend_LE, ty, addr);
664 }
665 
stmt_load(IRTemp result,IRExpr * addr,IRExpr * storedata)666 static IRStmt* stmt_load ( IRTemp result,
667                            IRExpr* addr, IRExpr* storedata )
668 {
669    if (host_endness == VexEndnessBE)
670       return IRStmt_LLSC(Iend_BE, result, addr, storedata);
671    else
672       return IRStmt_LLSC(Iend_LE, result, addr, storedata);
673 }
674 
mkOR1(IRExpr * arg1,IRExpr * arg2)675 static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 )
676 {
677    vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
678    vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
679    return unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1),
680                                           unop(Iop_1Uto32, arg2)));
681 }
682 
mkAND1(IRExpr * arg1,IRExpr * arg2)683 static IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 )
684 {
685    vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
686    vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
687    return unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1),
688                                            unop(Iop_1Uto32, arg2)));
689 }
690 
691 /* expand V128_8Ux16 to 2x V128_16Ux8's */
expand8Ux16(IRExpr * vIn,IRTemp * vEvn,IRTemp * vOdd)692 static void expand8Ux16( IRExpr* vIn,
693                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
694 {
695    IRTemp ones8x16 = newTemp(Ity_V128);
696 
697    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
698    vassert(vEvn && *vEvn == IRTemp_INVALID);
699    vassert(vOdd && *vOdd == IRTemp_INVALID);
700    *vEvn = newTemp(Ity_V128);
701    *vOdd = newTemp(Ity_V128);
702 
703    assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
704    assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) );
705    assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16),
706                         binop(Iop_ShrV128, vIn, mkU8(8))) );
707 }
708 
709 /* expand V128_8Sx16 to 2x V128_16Sx8's */
expand8Sx16(IRExpr * vIn,IRTemp * vEvn,IRTemp * vOdd)710 static void expand8Sx16( IRExpr* vIn,
711                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
712 {
713    IRTemp ones8x16 = newTemp(Ity_V128);
714 
715    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
716    vassert(vEvn && *vEvn == IRTemp_INVALID);
717    vassert(vOdd && *vOdd == IRTemp_INVALID);
718    *vEvn = newTemp(Ity_V128);
719    *vOdd = newTemp(Ity_V128);
720 
721    assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
722    assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) );
723    assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16),
724                         binop(Iop_ShrV128, vIn, mkU8(8))) );
725 }
726 
727 /* expand V128_16Uto8 to 2x V128_32Ux4's */
expand16Ux8(IRExpr * vIn,IRTemp * vEvn,IRTemp * vOdd)728 static void expand16Ux8( IRExpr* vIn,
729                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
730 {
731    IRTemp ones16x8 = newTemp(Ity_V128);
732 
733    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
734    vassert(vEvn && *vEvn == IRTemp_INVALID);
735    vassert(vOdd && *vOdd == IRTemp_INVALID);
736    *vEvn = newTemp(Ity_V128);
737    *vOdd = newTemp(Ity_V128);
738 
739    assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
740    assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) );
741    assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8),
742                         binop(Iop_ShrV128, vIn, mkU8(16))) );
743 }
744 
745 /* expand V128_16Sto8 to 2x V128_32Sx4's */
expand16Sx8(IRExpr * vIn,IRTemp * vEvn,IRTemp * vOdd)746 static void expand16Sx8( IRExpr* vIn,
747                          /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
748 {
749    IRTemp ones16x8 = newTemp(Ity_V128);
750 
751    vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
752    vassert(vEvn && *vEvn == IRTemp_INVALID);
753    vassert(vOdd && *vOdd == IRTemp_INVALID);
754    *vEvn = newTemp(Ity_V128);
755    *vOdd = newTemp(Ity_V128);
756 
757    assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
758    assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) );
759    assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8),
760                        binop(Iop_ShrV128, vIn, mkU8(16))) );
761 }
762 
763 /* break V128 to 4xF64's*/
breakV128to4xF64(IRExpr * t128,IRTemp * t3,IRTemp * t2,IRTemp * t1,IRTemp * t0)764 static void breakV128to4xF64( IRExpr* t128,
765                               /*OUTs*/
766                               IRTemp* t3, IRTemp* t2,
767                               IRTemp* t1, IRTemp* t0 )
768 {
769    IRTemp hi64 = newTemp(Ity_I64);
770    IRTemp lo64 = newTemp(Ity_I64);
771 
772    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
773    vassert(t0 && *t0 == IRTemp_INVALID);
774    vassert(t1 && *t1 == IRTemp_INVALID);
775    vassert(t2 && *t2 == IRTemp_INVALID);
776    vassert(t3 && *t3 == IRTemp_INVALID);
777    *t0 = newTemp(Ity_F64);
778    *t1 = newTemp(Ity_F64);
779    *t2 = newTemp(Ity_F64);
780    *t3 = newTemp(Ity_F64);
781 
782    assign( hi64, unop(Iop_V128HIto64, t128) );
783    assign( lo64, unop(Iop_V128to64,   t128) );
784    assign( *t3,
785            unop( Iop_F32toF64,
786                  unop( Iop_ReinterpI32asF32,
787                        unop( Iop_64HIto32, mkexpr( hi64 ) ) ) ) );
788    assign( *t2,
789            unop( Iop_F32toF64,
790                  unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( hi64 ) ) ) ) );
791    assign( *t1,
792            unop( Iop_F32toF64,
793                  unop( Iop_ReinterpI32asF32,
794                        unop( Iop_64HIto32, mkexpr( lo64 ) ) ) ) );
795    assign( *t0,
796            unop( Iop_F32toF64,
797                  unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( lo64 ) ) ) ) );
798 }
799 
800 
801 /* break V128 to 4xI32's, then sign-extend to I64's */
breakV128to4x64S(IRExpr * t128,IRTemp * t3,IRTemp * t2,IRTemp * t1,IRTemp * t0)802 static void breakV128to4x64S( IRExpr* t128,
803                               /*OUTs*/
804                               IRTemp* t3, IRTemp* t2,
805                               IRTemp* t1, IRTemp* t0 )
806 {
807    IRTemp hi64 = newTemp(Ity_I64);
808    IRTemp lo64 = newTemp(Ity_I64);
809 
810    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
811    vassert(t0 && *t0 == IRTemp_INVALID);
812    vassert(t1 && *t1 == IRTemp_INVALID);
813    vassert(t2 && *t2 == IRTemp_INVALID);
814    vassert(t3 && *t3 == IRTemp_INVALID);
815    *t0 = newTemp(Ity_I64);
816    *t1 = newTemp(Ity_I64);
817    *t2 = newTemp(Ity_I64);
818    *t3 = newTemp(Ity_I64);
819 
820    assign( hi64, unop(Iop_V128HIto64, t128) );
821    assign( lo64, unop(Iop_V128to64,   t128) );
822    assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) );
823    assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(hi64))) );
824    assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) );
825    assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(lo64))) );
826 }
827 
828 /* break V128 to 4xI32's, then zero-extend to I64's */
breakV128to4x64U(IRExpr * t128,IRTemp * t3,IRTemp * t2,IRTemp * t1,IRTemp * t0)829 static void breakV128to4x64U ( IRExpr* t128,
830                                /*OUTs*/
831                                IRTemp* t3, IRTemp* t2,
832                                IRTemp* t1, IRTemp* t0 )
833 {
834    IRTemp hi64 = newTemp(Ity_I64);
835    IRTemp lo64 = newTemp(Ity_I64);
836 
837    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
838    vassert(t0 && *t0 == IRTemp_INVALID);
839    vassert(t1 && *t1 == IRTemp_INVALID);
840    vassert(t2 && *t2 == IRTemp_INVALID);
841    vassert(t3 && *t3 == IRTemp_INVALID);
842    *t0 = newTemp(Ity_I64);
843    *t1 = newTemp(Ity_I64);
844    *t2 = newTemp(Ity_I64);
845    *t3 = newTemp(Ity_I64);
846 
847    assign( hi64, unop(Iop_V128HIto64, t128) );
848    assign( lo64, unop(Iop_V128to64,   t128) );
849    assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) );
850    assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(hi64))) );
851    assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) );
852    assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(lo64))) );
853 }
854 
breakV128to4x32(IRExpr * t128,IRTemp * t3,IRTemp * t2,IRTemp * t1,IRTemp * t0)855 static void breakV128to4x32( IRExpr* t128,
856                               /*OUTs*/
857                               IRTemp* t3, IRTemp* t2,
858                               IRTemp* t1, IRTemp* t0 )
859 {
860    IRTemp hi64 = newTemp(Ity_I64);
861    IRTemp lo64 = newTemp(Ity_I64);
862 
863    vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
864    vassert(t0 && *t0 == IRTemp_INVALID);
865    vassert(t1 && *t1 == IRTemp_INVALID);
866    vassert(t2 && *t2 == IRTemp_INVALID);
867    vassert(t3 && *t3 == IRTemp_INVALID);
868    *t0 = newTemp(Ity_I32);
869    *t1 = newTemp(Ity_I32);
870    *t2 = newTemp(Ity_I32);
871    *t3 = newTemp(Ity_I32);
872 
873    assign( hi64, unop(Iop_V128HIto64, t128) );
874    assign( lo64, unop(Iop_V128to64,   t128) );
875    assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) );
876    assign( *t2, unop(Iop_64to32,   mkexpr(hi64)) );
877    assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) );
878    assign( *t0, unop(Iop_64to32,   mkexpr(lo64)) );
879 }
880 
mkV128from32(IRTemp t3,IRTemp t2,IRTemp t1,IRTemp t0)881 static IRExpr* mkV128from32( IRTemp t3, IRTemp t2,
882                                IRTemp t1, IRTemp t0 )
883 {
884    return
885       binop( Iop_64HLtoV128,
886              binop(Iop_32HLto64, mkexpr(t3), mkexpr(t2)),
887              binop(Iop_32HLto64, mkexpr(t1), mkexpr(t0))
888    );
889 }
890 
891 
892 /* Signed saturating narrow 64S to 32 */
mkQNarrow64Sto32(IRExpr * t64)893 static IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 )
894 {
895    IRTemp hi32 = newTemp(Ity_I32);
896    IRTemp lo32 = newTemp(Ity_I32);
897 
898    vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
899 
900    assign( hi32, unop(Iop_64HIto32, t64));
901    assign( lo32, unop(Iop_64to32,   t64));
902 
903    return IRExpr_ITE(
904              /* if (hi32 == (lo32 >>s 31)) */
905              binop(Iop_CmpEQ32, mkexpr(hi32),
906                    binop( Iop_Sar32, mkexpr(lo32), mkU8(31))),
907              /* then: within signed-32 range: lo half good enough */
908              mkexpr(lo32),
909              /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */
910              binop(Iop_Add32, mkU32(0x7FFFFFFF),
911                    binop(Iop_Shr32, mkexpr(hi32), mkU8(31))));
912 }
913 
914 /* Unsigned saturating narrow 64S to 32 */
mkQNarrow64Uto32(IRExpr * t64)915 static IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 )
916 {
917    IRTemp hi32 = newTemp(Ity_I32);
918    IRTemp lo32 = newTemp(Ity_I32);
919 
920    vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
921 
922    assign( hi32, unop(Iop_64HIto32, t64));
923    assign( lo32, unop(Iop_64to32,   t64));
924 
925    return IRExpr_ITE(
926             /* if (top 32 bits of t64 are 0) */
927             binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0)),
928             /* then: within unsigned-32 range: lo half good enough */
929             mkexpr(lo32),
930             /* else: positive saturate -> 0xFFFFFFFF */
931             mkU32(0xFFFFFFFF));
932 }
933 
934 /* Signed saturate narrow 64->32, combining to V128 */
mkV128from4x64S(IRExpr * t3,IRExpr * t2,IRExpr * t1,IRExpr * t0)935 static IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2,
936                                  IRExpr* t1, IRExpr* t0 )
937 {
938    vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
939    vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
940    vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
941    vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
942    return binop(Iop_64HLtoV128,
943                 binop(Iop_32HLto64,
944                       mkQNarrow64Sto32( t3 ),
945                       mkQNarrow64Sto32( t2 )),
946                 binop(Iop_32HLto64,
947                       mkQNarrow64Sto32( t1 ),
948                       mkQNarrow64Sto32( t0 )));
949 }
950 
951 /* Unsigned saturate narrow 64->32, combining to V128 */
mkV128from4x64U(IRExpr * t3,IRExpr * t2,IRExpr * t1,IRExpr * t0)952 static IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2,
953                                  IRExpr* t1, IRExpr* t0 )
954 {
955    vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
956    vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
957    vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
958    vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
959    return binop(Iop_64HLtoV128,
960                 binop(Iop_32HLto64,
961                       mkQNarrow64Uto32( t3 ),
962                       mkQNarrow64Uto32( t2 )),
963                 binop(Iop_32HLto64,
964                       mkQNarrow64Uto32( t1 ),
965                       mkQNarrow64Uto32( t0 )));
966 }
967 
968 /* Simulate irops Iop_MullOdd*, since we don't have them  */
969 #define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \
970       binop(Iop_MullEven8Ux16, \
971             binop(Iop_ShrV128, expr_vA, mkU8(8)), \
972             binop(Iop_ShrV128, expr_vB, mkU8(8)))
973 
974 #define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \
975       binop(Iop_MullEven8Sx16, \
976             binop(Iop_ShrV128, expr_vA, mkU8(8)), \
977             binop(Iop_ShrV128, expr_vB, mkU8(8)))
978 
979 #define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \
980       binop(Iop_MullEven16Ux8, \
981             binop(Iop_ShrV128, expr_vA, mkU8(16)), \
982             binop(Iop_ShrV128, expr_vB, mkU8(16)))
983 
984 #define MK_Iop_MullOdd32Ux4( expr_vA, expr_vB ) \
985       binop(Iop_MullEven32Ux4, \
986             binop(Iop_ShrV128, expr_vA, mkU8(32)), \
987             binop(Iop_ShrV128, expr_vB, mkU8(32)))
988 
989 #define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \
990       binop(Iop_MullEven16Sx8, \
991             binop(Iop_ShrV128, expr_vA, mkU8(16)), \
992             binop(Iop_ShrV128, expr_vB, mkU8(16)))
993 
994 #define MK_Iop_MullOdd32Sx4( expr_vA, expr_vB ) \
995       binop(Iop_MullEven32Sx4, \
996             binop(Iop_ShrV128, expr_vA, mkU8(32)), \
997             binop(Iop_ShrV128, expr_vB, mkU8(32)))
998 
999 
mk64lo32Sto64(IRExpr * src)1000 static IRExpr* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr* src )
1001 {
1002    vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
1003    return unop(Iop_32Sto64, unop(Iop_64to32, src));
1004 }
1005 
mk64lo32Uto64(IRExpr * src)1006 static IRExpr* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr* src )
1007 {
1008    vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
1009    return unop(Iop_32Uto64, unop(Iop_64to32, src));
1010 }
1011 
mkSzOp(IRType ty,IROp op8)1012 static IROp mkSzOp ( IRType ty, IROp op8 )
1013 {
1014    Int adj;
1015    vassert(ty == Ity_I8  || ty == Ity_I16 ||
1016            ty == Ity_I32 || ty == Ity_I64);
1017    vassert(op8 == Iop_Add8   || op8 == Iop_Sub8   || op8 == Iop_Mul8 ||
1018            op8 == Iop_Or8    || op8 == Iop_And8   || op8 == Iop_Xor8 ||
1019            op8 == Iop_Shl8   || op8 == Iop_Shr8   || op8 == Iop_Sar8 ||
1020            op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 ||
1021            op8 == Iop_Not8 );
1022    adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3));
1023    return adj + op8;
1024 }
1025 
1026 /* Make sure we get valid 32 and 64bit addresses */
mkSzAddr(IRType ty,Addr64 addr)1027 static Addr64 mkSzAddr ( IRType ty, Addr64 addr )
1028 {
1029    vassert(ty == Ity_I32 || ty == Ity_I64);
1030    return ( ty == Ity_I64 ?
1031             (Addr64)addr :
1032             (Addr64)extend_s_32to64( toUInt(addr) ) );
1033 }
1034 
1035 /* sz, ULong -> IRExpr */
mkSzImm(IRType ty,ULong imm64)1036 static IRExpr* mkSzImm ( IRType ty, ULong imm64 )
1037 {
1038    vassert(ty == Ity_I32 || ty == Ity_I64);
1039    return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64);
1040 }
1041 
1042 /* sz, ULong -> IRConst */
mkSzConst(IRType ty,ULong imm64)1043 static IRConst* mkSzConst ( IRType ty, ULong imm64 )
1044 {
1045    vassert(ty == Ity_I32 || ty == Ity_I64);
1046    return ( ty == Ity_I64 ?
1047             IRConst_U64(imm64) :
1048             IRConst_U32((UInt)imm64) );
1049 }
1050 
1051 /* Sign extend imm16 -> IRExpr* */
mkSzExtendS16(IRType ty,UInt imm16)1052 static IRExpr* mkSzExtendS16 ( IRType ty, UInt imm16 )
1053 {
1054    vassert(ty == Ity_I32 || ty == Ity_I64);
1055    return ( ty == Ity_I64 ?
1056             mkU64(extend_s_16to64(imm16)) :
1057             mkU32(extend_s_16to32(imm16)) );
1058 }
1059 
1060 /* Sign extend imm32 -> IRExpr* */
mkSzExtendS32(IRType ty,UInt imm32)1061 static IRExpr* mkSzExtendS32 ( IRType ty, UInt imm32 )
1062 {
1063    vassert(ty == Ity_I32 || ty == Ity_I64);
1064    return ( ty == Ity_I64 ?
1065             mkU64(extend_s_32to64(imm32)) :
1066             mkU32(imm32) );
1067 }
1068 
1069 /* IR narrows I32/I64 -> I8/I16/I32 */
mkNarrowTo8(IRType ty,IRExpr * src)1070 static IRExpr* mkNarrowTo8 ( IRType ty, IRExpr* src )
1071 {
1072    vassert(ty == Ity_I32 || ty == Ity_I64);
1073    return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src);
1074 }
1075 
mkNarrowTo16(IRType ty,IRExpr * src)1076 static IRExpr* mkNarrowTo16 ( IRType ty, IRExpr* src )
1077 {
1078    vassert(ty == Ity_I32 || ty == Ity_I64);
1079    return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src);
1080 }
1081 
mkNarrowTo32(IRType ty,IRExpr * src)1082 static IRExpr* mkNarrowTo32 ( IRType ty, IRExpr* src )
1083 {
1084    vassert(ty == Ity_I32 || ty == Ity_I64);
1085    return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
1086 }
1087 
1088 /* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */
mkWidenFrom8(IRType ty,IRExpr * src,Bool sined)1089 static IRExpr* mkWidenFrom8 ( IRType ty, IRExpr* src, Bool sined )
1090 {
1091    IROp op;
1092    vassert(ty == Ity_I32 || ty == Ity_I64);
1093    if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64;
1094    else       op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64;
1095    return unop(op, src);
1096 }
1097 
mkWidenFrom16(IRType ty,IRExpr * src,Bool sined)1098 static IRExpr* mkWidenFrom16 ( IRType ty, IRExpr* src, Bool sined )
1099 {
1100    IROp op;
1101    vassert(ty == Ity_I32 || ty == Ity_I64);
1102    if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64;
1103    else       op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64;
1104    return unop(op, src);
1105 }
1106 
mkWidenFrom32(IRType ty,IRExpr * src,Bool sined)1107 static IRExpr* mkWidenFrom32 ( IRType ty, IRExpr* src, Bool sined )
1108 {
1109    vassert(ty == Ity_I32 || ty == Ity_I64);
1110    if (ty == Ity_I32)
1111       return src;
1112    return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
1113 }
1114 
1115 
integerGuestRegOffset(UInt archreg)1116 static Int integerGuestRegOffset ( UInt archreg )
1117 {
1118    vassert(archreg < 32);
1119 
1120    // jrs: probably not necessary; only matters if we reference sub-parts
1121    // of the ppc registers, but that isn't the case
1122    // later: this might affect Altivec though?
1123 
1124    switch (archreg) {
1125    case  0: return offsetofPPCGuestState(guest_GPR0);
1126    case  1: return offsetofPPCGuestState(guest_GPR1);
1127    case  2: return offsetofPPCGuestState(guest_GPR2);
1128    case  3: return offsetofPPCGuestState(guest_GPR3);
1129    case  4: return offsetofPPCGuestState(guest_GPR4);
1130    case  5: return offsetofPPCGuestState(guest_GPR5);
1131    case  6: return offsetofPPCGuestState(guest_GPR6);
1132    case  7: return offsetofPPCGuestState(guest_GPR7);
1133    case  8: return offsetofPPCGuestState(guest_GPR8);
1134    case  9: return offsetofPPCGuestState(guest_GPR9);
1135    case 10: return offsetofPPCGuestState(guest_GPR10);
1136    case 11: return offsetofPPCGuestState(guest_GPR11);
1137    case 12: return offsetofPPCGuestState(guest_GPR12);
1138    case 13: return offsetofPPCGuestState(guest_GPR13);
1139    case 14: return offsetofPPCGuestState(guest_GPR14);
1140    case 15: return offsetofPPCGuestState(guest_GPR15);
1141    case 16: return offsetofPPCGuestState(guest_GPR16);
1142    case 17: return offsetofPPCGuestState(guest_GPR17);
1143    case 18: return offsetofPPCGuestState(guest_GPR18);
1144    case 19: return offsetofPPCGuestState(guest_GPR19);
1145    case 20: return offsetofPPCGuestState(guest_GPR20);
1146    case 21: return offsetofPPCGuestState(guest_GPR21);
1147    case 22: return offsetofPPCGuestState(guest_GPR22);
1148    case 23: return offsetofPPCGuestState(guest_GPR23);
1149    case 24: return offsetofPPCGuestState(guest_GPR24);
1150    case 25: return offsetofPPCGuestState(guest_GPR25);
1151    case 26: return offsetofPPCGuestState(guest_GPR26);
1152    case 27: return offsetofPPCGuestState(guest_GPR27);
1153    case 28: return offsetofPPCGuestState(guest_GPR28);
1154    case 29: return offsetofPPCGuestState(guest_GPR29);
1155    case 30: return offsetofPPCGuestState(guest_GPR30);
1156    case 31: return offsetofPPCGuestState(guest_GPR31);
1157    default: break;
1158    }
1159    vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/
1160 }
1161 
getIReg(UInt archreg)1162 static IRExpr* getIReg ( UInt archreg )
1163 {
1164    IRType ty = mode64 ? Ity_I64 : Ity_I32;
1165    vassert(archreg < 32);
1166    return IRExpr_Get( integerGuestRegOffset(archreg), ty );
1167 }
1168 
1169 /* Ditto, but write to a reg instead. */
putIReg(UInt archreg,IRExpr * e)1170 static void putIReg ( UInt archreg, IRExpr* e )
1171 {
1172    IRType ty = mode64 ? Ity_I64 : Ity_I32;
1173    vassert(archreg < 32);
1174    vassert(typeOfIRExpr(irsb->tyenv, e) == ty );
1175    stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) );
1176 }
1177 
1178 
1179 /* Floating point egisters are mapped to VSX registers[0..31]. */
floatGuestRegOffset(UInt archreg)1180 static Int floatGuestRegOffset ( UInt archreg )
1181 {
1182    vassert(archreg < 32);
1183 
1184    if (host_endness == VexEndnessLE) {
1185       switch (archreg) {
1186          case  0: return offsetofPPCGuestState(guest_VSR0) + 8;
1187          case  1: return offsetofPPCGuestState(guest_VSR1) + 8;
1188          case  2: return offsetofPPCGuestState(guest_VSR2) + 8;
1189          case  3: return offsetofPPCGuestState(guest_VSR3) + 8;
1190          case  4: return offsetofPPCGuestState(guest_VSR4) + 8;
1191          case  5: return offsetofPPCGuestState(guest_VSR5) + 8;
1192          case  6: return offsetofPPCGuestState(guest_VSR6) + 8;
1193          case  7: return offsetofPPCGuestState(guest_VSR7) + 8;
1194          case  8: return offsetofPPCGuestState(guest_VSR8) + 8;
1195          case  9: return offsetofPPCGuestState(guest_VSR9) + 8;
1196          case 10: return offsetofPPCGuestState(guest_VSR10) + 8;
1197          case 11: return offsetofPPCGuestState(guest_VSR11) + 8;
1198          case 12: return offsetofPPCGuestState(guest_VSR12) + 8;
1199          case 13: return offsetofPPCGuestState(guest_VSR13) + 8;
1200          case 14: return offsetofPPCGuestState(guest_VSR14) + 8;
1201          case 15: return offsetofPPCGuestState(guest_VSR15) + 8;
1202          case 16: return offsetofPPCGuestState(guest_VSR16) + 8;
1203          case 17: return offsetofPPCGuestState(guest_VSR17) + 8;
1204          case 18: return offsetofPPCGuestState(guest_VSR18) + 8;
1205          case 19: return offsetofPPCGuestState(guest_VSR19) + 8;
1206          case 20: return offsetofPPCGuestState(guest_VSR20) + 8;
1207          case 21: return offsetofPPCGuestState(guest_VSR21) + 8;
1208          case 22: return offsetofPPCGuestState(guest_VSR22) + 8;
1209          case 23: return offsetofPPCGuestState(guest_VSR23) + 8;
1210          case 24: return offsetofPPCGuestState(guest_VSR24) + 8;
1211          case 25: return offsetofPPCGuestState(guest_VSR25) + 8;
1212          case 26: return offsetofPPCGuestState(guest_VSR26) + 8;
1213          case 27: return offsetofPPCGuestState(guest_VSR27) + 8;
1214          case 28: return offsetofPPCGuestState(guest_VSR28) + 8;
1215          case 29: return offsetofPPCGuestState(guest_VSR29) + 8;
1216          case 30: return offsetofPPCGuestState(guest_VSR30) + 8;
1217          case 31: return offsetofPPCGuestState(guest_VSR31) + 8;
1218          default: break;
1219       }
1220    } else {
1221       switch (archreg) {
1222          case  0: return offsetofPPCGuestState(guest_VSR0);
1223          case  1: return offsetofPPCGuestState(guest_VSR1);
1224          case  2: return offsetofPPCGuestState(guest_VSR2);
1225          case  3: return offsetofPPCGuestState(guest_VSR3);
1226          case  4: return offsetofPPCGuestState(guest_VSR4);
1227          case  5: return offsetofPPCGuestState(guest_VSR5);
1228          case  6: return offsetofPPCGuestState(guest_VSR6);
1229          case  7: return offsetofPPCGuestState(guest_VSR7);
1230          case  8: return offsetofPPCGuestState(guest_VSR8);
1231          case  9: return offsetofPPCGuestState(guest_VSR9);
1232          case 10: return offsetofPPCGuestState(guest_VSR10);
1233          case 11: return offsetofPPCGuestState(guest_VSR11);
1234          case 12: return offsetofPPCGuestState(guest_VSR12);
1235          case 13: return offsetofPPCGuestState(guest_VSR13);
1236          case 14: return offsetofPPCGuestState(guest_VSR14);
1237          case 15: return offsetofPPCGuestState(guest_VSR15);
1238          case 16: return offsetofPPCGuestState(guest_VSR16);
1239          case 17: return offsetofPPCGuestState(guest_VSR17);
1240          case 18: return offsetofPPCGuestState(guest_VSR18);
1241          case 19: return offsetofPPCGuestState(guest_VSR19);
1242          case 20: return offsetofPPCGuestState(guest_VSR20);
1243          case 21: return offsetofPPCGuestState(guest_VSR21);
1244          case 22: return offsetofPPCGuestState(guest_VSR22);
1245          case 23: return offsetofPPCGuestState(guest_VSR23);
1246          case 24: return offsetofPPCGuestState(guest_VSR24);
1247          case 25: return offsetofPPCGuestState(guest_VSR25);
1248          case 26: return offsetofPPCGuestState(guest_VSR26);
1249          case 27: return offsetofPPCGuestState(guest_VSR27);
1250          case 28: return offsetofPPCGuestState(guest_VSR28);
1251          case 29: return offsetofPPCGuestState(guest_VSR29);
1252          case 30: return offsetofPPCGuestState(guest_VSR30);
1253          case 31: return offsetofPPCGuestState(guest_VSR31);
1254          default: break;
1255       }
1256    }
1257    vpanic("floatGuestRegOffset(ppc)"); /*notreached*/
1258 }
1259 
getFReg(UInt archreg)1260 static IRExpr* getFReg ( UInt archreg )
1261 {
1262    vassert(archreg < 32);
1263    return IRExpr_Get( floatGuestRegOffset(archreg), Ity_F64 );
1264 }
1265 
1266 /* Ditto, but write to a reg instead. */
putFReg(UInt archreg,IRExpr * e)1267 static void putFReg ( UInt archreg, IRExpr* e )
1268 {
1269    vassert(archreg < 32);
1270    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
1271    stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) );
1272 }
1273 
1274 /* get Decimal float value.  Note, they share floating point register file. */
getDReg(UInt archreg)1275 static IRExpr* getDReg(UInt archreg) {
1276    IRExpr *e;
1277    vassert( archreg < 32 );
1278    e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D64 );
1279    return e;
1280 }
getDReg32(UInt archreg)1281 static IRExpr* getDReg32(UInt archreg) {
1282    IRExpr *e;
1283    vassert( archreg < 32 );
1284    e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D32 );
1285    return e;
1286 }
1287 
1288 /* Read a floating point register pair and combine their contents into a
1289  128-bit value */
getDReg_pair(UInt archreg)1290 static IRExpr *getDReg_pair(UInt archreg) {
1291    IRExpr *high = getDReg( archreg );
1292    IRExpr *low = getDReg( archreg + 1 );
1293 
1294    return binop( Iop_D64HLtoD128, high, low );
1295 }
1296 
1297 /* Ditto, but write to a reg instead. */
putDReg32(UInt archreg,IRExpr * e)1298 static void putDReg32(UInt archreg, IRExpr* e) {
1299    vassert( archreg < 32 );
1300    vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D32 );
1301    stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) );
1302 }
1303 
putDReg(UInt archreg,IRExpr * e)1304 static void putDReg(UInt archreg, IRExpr* e) {
1305    vassert( archreg < 32 );
1306    vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D64 );
1307    stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) );
1308 }
1309 
1310 /* Write a 128-bit floating point value into a register pair. */
putDReg_pair(UInt archreg,IRExpr * e)1311 static void putDReg_pair(UInt archreg, IRExpr *e) {
1312    IRTemp low = newTemp( Ity_D64 );
1313    IRTemp high = newTemp( Ity_D64 );
1314 
1315    vassert( archreg < 32 );
1316    vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D128 );
1317 
1318    assign( low, unop( Iop_D128LOtoD64, e ) );
1319    assign( high, unop( Iop_D128HItoD64, e ) );
1320 
1321    stmt( IRStmt_Put( floatGuestRegOffset( archreg ), mkexpr( high ) ) );
1322    stmt( IRStmt_Put( floatGuestRegOffset( archreg + 1 ), mkexpr( low ) ) );
1323 }
1324 
vsxGuestRegOffset(UInt archreg)1325 static Int vsxGuestRegOffset ( UInt archreg )
1326 {
1327    vassert(archreg < 64);
1328    switch (archreg) {
1329    case  0: return offsetofPPCGuestState(guest_VSR0);
1330    case  1: return offsetofPPCGuestState(guest_VSR1);
1331    case  2: return offsetofPPCGuestState(guest_VSR2);
1332    case  3: return offsetofPPCGuestState(guest_VSR3);
1333    case  4: return offsetofPPCGuestState(guest_VSR4);
1334    case  5: return offsetofPPCGuestState(guest_VSR5);
1335    case  6: return offsetofPPCGuestState(guest_VSR6);
1336    case  7: return offsetofPPCGuestState(guest_VSR7);
1337    case  8: return offsetofPPCGuestState(guest_VSR8);
1338    case  9: return offsetofPPCGuestState(guest_VSR9);
1339    case 10: return offsetofPPCGuestState(guest_VSR10);
1340    case 11: return offsetofPPCGuestState(guest_VSR11);
1341    case 12: return offsetofPPCGuestState(guest_VSR12);
1342    case 13: return offsetofPPCGuestState(guest_VSR13);
1343    case 14: return offsetofPPCGuestState(guest_VSR14);
1344    case 15: return offsetofPPCGuestState(guest_VSR15);
1345    case 16: return offsetofPPCGuestState(guest_VSR16);
1346    case 17: return offsetofPPCGuestState(guest_VSR17);
1347    case 18: return offsetofPPCGuestState(guest_VSR18);
1348    case 19: return offsetofPPCGuestState(guest_VSR19);
1349    case 20: return offsetofPPCGuestState(guest_VSR20);
1350    case 21: return offsetofPPCGuestState(guest_VSR21);
1351    case 22: return offsetofPPCGuestState(guest_VSR22);
1352    case 23: return offsetofPPCGuestState(guest_VSR23);
1353    case 24: return offsetofPPCGuestState(guest_VSR24);
1354    case 25: return offsetofPPCGuestState(guest_VSR25);
1355    case 26: return offsetofPPCGuestState(guest_VSR26);
1356    case 27: return offsetofPPCGuestState(guest_VSR27);
1357    case 28: return offsetofPPCGuestState(guest_VSR28);
1358    case 29: return offsetofPPCGuestState(guest_VSR29);
1359    case 30: return offsetofPPCGuestState(guest_VSR30);
1360    case 31: return offsetofPPCGuestState(guest_VSR31);
1361    case 32: return offsetofPPCGuestState(guest_VSR32);
1362    case 33: return offsetofPPCGuestState(guest_VSR33);
1363    case 34: return offsetofPPCGuestState(guest_VSR34);
1364    case 35: return offsetofPPCGuestState(guest_VSR35);
1365    case 36: return offsetofPPCGuestState(guest_VSR36);
1366    case 37: return offsetofPPCGuestState(guest_VSR37);
1367    case 38: return offsetofPPCGuestState(guest_VSR38);
1368    case 39: return offsetofPPCGuestState(guest_VSR39);
1369    case 40: return offsetofPPCGuestState(guest_VSR40);
1370    case 41: return offsetofPPCGuestState(guest_VSR41);
1371    case 42: return offsetofPPCGuestState(guest_VSR42);
1372    case 43: return offsetofPPCGuestState(guest_VSR43);
1373    case 44: return offsetofPPCGuestState(guest_VSR44);
1374    case 45: return offsetofPPCGuestState(guest_VSR45);
1375    case 46: return offsetofPPCGuestState(guest_VSR46);
1376    case 47: return offsetofPPCGuestState(guest_VSR47);
1377    case 48: return offsetofPPCGuestState(guest_VSR48);
1378    case 49: return offsetofPPCGuestState(guest_VSR49);
1379    case 50: return offsetofPPCGuestState(guest_VSR50);
1380    case 51: return offsetofPPCGuestState(guest_VSR51);
1381    case 52: return offsetofPPCGuestState(guest_VSR52);
1382    case 53: return offsetofPPCGuestState(guest_VSR53);
1383    case 54: return offsetofPPCGuestState(guest_VSR54);
1384    case 55: return offsetofPPCGuestState(guest_VSR55);
1385    case 56: return offsetofPPCGuestState(guest_VSR56);
1386    case 57: return offsetofPPCGuestState(guest_VSR57);
1387    case 58: return offsetofPPCGuestState(guest_VSR58);
1388    case 59: return offsetofPPCGuestState(guest_VSR59);
1389    case 60: return offsetofPPCGuestState(guest_VSR60);
1390    case 61: return offsetofPPCGuestState(guest_VSR61);
1391    case 62: return offsetofPPCGuestState(guest_VSR62);
1392    case 63: return offsetofPPCGuestState(guest_VSR63);
1393    default: break;
1394    }
1395    vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/
1396 }
1397 
1398 /* Vector registers are mapped to VSX registers[32..63]. */
vectorGuestRegOffset(UInt archreg)1399 static Int vectorGuestRegOffset ( UInt archreg )
1400 {
1401    vassert(archreg < 32);
1402 
1403    switch (archreg) {
1404    case  0: return offsetofPPCGuestState(guest_VSR32);
1405    case  1: return offsetofPPCGuestState(guest_VSR33);
1406    case  2: return offsetofPPCGuestState(guest_VSR34);
1407    case  3: return offsetofPPCGuestState(guest_VSR35);
1408    case  4: return offsetofPPCGuestState(guest_VSR36);
1409    case  5: return offsetofPPCGuestState(guest_VSR37);
1410    case  6: return offsetofPPCGuestState(guest_VSR38);
1411    case  7: return offsetofPPCGuestState(guest_VSR39);
1412    case  8: return offsetofPPCGuestState(guest_VSR40);
1413    case  9: return offsetofPPCGuestState(guest_VSR41);
1414    case 10: return offsetofPPCGuestState(guest_VSR42);
1415    case 11: return offsetofPPCGuestState(guest_VSR43);
1416    case 12: return offsetofPPCGuestState(guest_VSR44);
1417    case 13: return offsetofPPCGuestState(guest_VSR45);
1418    case 14: return offsetofPPCGuestState(guest_VSR46);
1419    case 15: return offsetofPPCGuestState(guest_VSR47);
1420    case 16: return offsetofPPCGuestState(guest_VSR48);
1421    case 17: return offsetofPPCGuestState(guest_VSR49);
1422    case 18: return offsetofPPCGuestState(guest_VSR50);
1423    case 19: return offsetofPPCGuestState(guest_VSR51);
1424    case 20: return offsetofPPCGuestState(guest_VSR52);
1425    case 21: return offsetofPPCGuestState(guest_VSR53);
1426    case 22: return offsetofPPCGuestState(guest_VSR54);
1427    case 23: return offsetofPPCGuestState(guest_VSR55);
1428    case 24: return offsetofPPCGuestState(guest_VSR56);
1429    case 25: return offsetofPPCGuestState(guest_VSR57);
1430    case 26: return offsetofPPCGuestState(guest_VSR58);
1431    case 27: return offsetofPPCGuestState(guest_VSR59);
1432    case 28: return offsetofPPCGuestState(guest_VSR60);
1433    case 29: return offsetofPPCGuestState(guest_VSR61);
1434    case 30: return offsetofPPCGuestState(guest_VSR62);
1435    case 31: return offsetofPPCGuestState(guest_VSR63);
1436    default: break;
1437    }
1438    vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/
1439 }
1440 
getVReg(UInt archreg)1441 static IRExpr* getVReg ( UInt archreg )
1442 {
1443    vassert(archreg < 32);
1444    return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 );
1445 }
1446 
1447 /* Ditto, but write to a reg instead. */
putVReg(UInt archreg,IRExpr * e)1448 static void putVReg ( UInt archreg, IRExpr* e )
1449 {
1450    vassert(archreg < 32);
1451    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
1452    stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) );
1453 }
1454 
1455 /* Get contents of VSX guest register */
getVSReg(UInt archreg)1456 static IRExpr* getVSReg ( UInt archreg )
1457 {
1458    vassert(archreg < 64);
1459    return IRExpr_Get( vsxGuestRegOffset(archreg), Ity_V128 );
1460 }
1461 
1462 /* Ditto, but write to a VSX reg instead. */
putVSReg(UInt archreg,IRExpr * e)1463 static void putVSReg ( UInt archreg, IRExpr* e )
1464 {
1465    vassert(archreg < 64);
1466    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
1467    stmt( IRStmt_Put(vsxGuestRegOffset(archreg), e) );
1468 }
1469 
1470 
guestCR321offset(UInt cr)1471 static Int guestCR321offset ( UInt cr )
1472 {
1473    switch (cr) {
1474    case 0: return offsetofPPCGuestState(guest_CR0_321 );
1475    case 1: return offsetofPPCGuestState(guest_CR1_321 );
1476    case 2: return offsetofPPCGuestState(guest_CR2_321 );
1477    case 3: return offsetofPPCGuestState(guest_CR3_321 );
1478    case 4: return offsetofPPCGuestState(guest_CR4_321 );
1479    case 5: return offsetofPPCGuestState(guest_CR5_321 );
1480    case 6: return offsetofPPCGuestState(guest_CR6_321 );
1481    case 7: return offsetofPPCGuestState(guest_CR7_321 );
1482    default: vpanic("guestCR321offset(ppc)");
1483    }
1484 }
1485 
guestCR0offset(UInt cr)1486 static Int guestCR0offset ( UInt cr )
1487 {
1488    switch (cr) {
1489    case 0: return offsetofPPCGuestState(guest_CR0_0 );
1490    case 1: return offsetofPPCGuestState(guest_CR1_0 );
1491    case 2: return offsetofPPCGuestState(guest_CR2_0 );
1492    case 3: return offsetofPPCGuestState(guest_CR3_0 );
1493    case 4: return offsetofPPCGuestState(guest_CR4_0 );
1494    case 5: return offsetofPPCGuestState(guest_CR5_0 );
1495    case 6: return offsetofPPCGuestState(guest_CR6_0 );
1496    case 7: return offsetofPPCGuestState(guest_CR7_0 );
1497    default: vpanic("guestCR3offset(ppc)");
1498    }
1499 }
1500 
1501 typedef enum {
1502    _placeholder0,
1503    _placeholder1,
1504    _placeholder2,
1505    BYTE,
1506    HWORD,
1507    WORD,
1508    DWORD
1509 } _popcount_data_type;
1510 
1511 /* Generate an IR sequence to do a popcount operation on the supplied
1512    IRTemp, and return a new IRTemp holding the result.  'ty' may be
1513    Ity_I32 or Ity_I64 only. */
gen_POPCOUNT(IRType ty,IRTemp src,_popcount_data_type data_type)1514 static IRTemp gen_POPCOUNT ( IRType ty, IRTemp src, _popcount_data_type data_type )
1515 {
1516   /* Do count across 2^data_type bits,
1517      byte:        data_type = 3
1518      half word:   data_type = 4
1519      word:        data_type = 5
1520      double word: data_type = 6  (not supported for 32-bit type)
1521     */
1522    Int shift[6];
1523    _popcount_data_type idx, i;
1524    IRTemp mask[6];
1525    IRTemp old = IRTemp_INVALID;
1526    IRTemp nyu = IRTemp_INVALID;
1527 
1528    vassert(ty == Ity_I64 || ty == Ity_I32);
1529 
1530    if (ty == Ity_I32) {
1531 
1532       for (idx = 0; idx < WORD; idx++) {
1533          mask[idx]  = newTemp(ty);
1534          shift[idx] = 1 << idx;
1535       }
1536       assign(mask[0], mkU32(0x55555555));
1537       assign(mask[1], mkU32(0x33333333));
1538       assign(mask[2], mkU32(0x0F0F0F0F));
1539       assign(mask[3], mkU32(0x00FF00FF));
1540       assign(mask[4], mkU32(0x0000FFFF));
1541       old = src;
1542       for (i = 0; i < data_type; i++) {
1543          nyu = newTemp(ty);
1544          assign(nyu,
1545                 binop(Iop_Add32,
1546                       binop(Iop_And32,
1547                             mkexpr(old),
1548                             mkexpr(mask[i])),
1549                       binop(Iop_And32,
1550                             binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
1551                             mkexpr(mask[i]))));
1552          old = nyu;
1553       }
1554       return nyu;
1555    }
1556 
1557 // else, ty == Ity_I64
1558    vassert(mode64);
1559 
1560    for (i = 0; i < DWORD; i++) {
1561       mask[i] = newTemp( Ity_I64 );
1562       shift[i] = 1 << i;
1563    }
1564    assign( mask[0], mkU64( 0x5555555555555555ULL ) );
1565    assign( mask[1], mkU64( 0x3333333333333333ULL ) );
1566    assign( mask[2], mkU64( 0x0F0F0F0F0F0F0F0FULL ) );
1567    assign( mask[3], mkU64( 0x00FF00FF00FF00FFULL ) );
1568    assign( mask[4], mkU64( 0x0000FFFF0000FFFFULL ) );
1569    assign( mask[5], mkU64( 0x00000000FFFFFFFFULL ) );
1570    old = src;
1571    for (i = 0; i < data_type; i++) {
1572       nyu = newTemp( Ity_I64 );
1573       assign( nyu,
1574               binop( Iop_Add64,
1575                      binop( Iop_And64, mkexpr( old ), mkexpr( mask[i] ) ),
1576                      binop( Iop_And64,
1577                             binop( Iop_Shr64, mkexpr( old ), mkU8( shift[i] ) ),
1578                             mkexpr( mask[i] ) ) ) );
1579       old = nyu;
1580    }
1581    return nyu;
1582 }
1583 
1584 /* Special purpose population count function for
1585  * vpopcntd in 32-bit mode.
1586  */
gen_vpopcntd_mode32(IRTemp src1,IRTemp src2)1587 static IRTemp gen_vpopcntd_mode32 ( IRTemp src1, IRTemp src2 )
1588 {
1589    Int i, shift[6];
1590    IRTemp mask[6];
1591    IRTemp old = IRTemp_INVALID;
1592    IRTemp nyu1 = IRTemp_INVALID;
1593    IRTemp nyu2 = IRTemp_INVALID;
1594    IRTemp retval = newTemp(Ity_I64);
1595 
1596    vassert(!mode64);
1597 
1598    for (i = 0; i < WORD; i++) {
1599       mask[i]  = newTemp(Ity_I32);
1600       shift[i] = 1 << i;
1601    }
1602    assign(mask[0], mkU32(0x55555555));
1603    assign(mask[1], mkU32(0x33333333));
1604    assign(mask[2], mkU32(0x0F0F0F0F));
1605    assign(mask[3], mkU32(0x00FF00FF));
1606    assign(mask[4], mkU32(0x0000FFFF));
1607    old = src1;
1608    for (i = 0; i < WORD; i++) {
1609       nyu1 = newTemp(Ity_I32);
1610       assign(nyu1,
1611              binop(Iop_Add32,
1612                    binop(Iop_And32,
1613                          mkexpr(old),
1614                          mkexpr(mask[i])),
1615                    binop(Iop_And32,
1616                          binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
1617                          mkexpr(mask[i]))));
1618       old = nyu1;
1619    }
1620 
1621    old = src2;
1622    for (i = 0; i < WORD; i++) {
1623       nyu2 = newTemp(Ity_I32);
1624       assign(nyu2,
1625              binop(Iop_Add32,
1626                    binop(Iop_And32,
1627                          mkexpr(old),
1628                          mkexpr(mask[i])),
1629                    binop(Iop_And32,
1630                          binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
1631                          mkexpr(mask[i]))));
1632       old = nyu2;
1633    }
1634    assign(retval, unop(Iop_32Uto64, binop(Iop_Add32, mkexpr(nyu1), mkexpr(nyu2))));
1635    return retval;
1636 }
1637 
1638 
1639 // ROTL(src32/64, rot_amt5/6)
ROTL(IRExpr * src,IRExpr * rot_amt)1640 static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src,
1641                                           IRExpr* rot_amt )
1642 {
1643    IRExpr *mask, *rot;
1644    vassert(typeOfIRExpr(irsb->tyenv,rot_amt) == Ity_I8);
1645 
1646    if (typeOfIRExpr(irsb->tyenv,src) == Ity_I64) {
1647       // rot = (src << rot_amt) | (src >> (64-rot_amt))
1648       mask = binop(Iop_And8, rot_amt, mkU8(63));
1649       rot  = binop(Iop_Or64,
1650                 binop(Iop_Shl64, src, mask),
1651                 binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask)));
1652    } else {
1653       // rot = (src << rot_amt) | (src >> (32-rot_amt))
1654       mask = binop(Iop_And8, rot_amt, mkU8(31));
1655       rot  = binop(Iop_Or32,
1656                 binop(Iop_Shl32, src, mask),
1657                 binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask)));
1658    }
1659    /* Note: the ITE not merely an optimisation; it's needed
1660       because otherwise the Shr is a shift by the word size when
1661       mask denotes zero.  For rotates by immediates, a lot of
1662       this junk gets folded out. */
1663    return IRExpr_ITE( binop(Iop_CmpNE8, mask, mkU8(0)),
1664                       /* non-zero rotate */ rot,
1665                       /*     zero rotate */ src);
1666 }
1667 
1668 /* Standard effective address calc: (rA + rB) */
ea_rA_idxd(UInt rA,UInt rB)1669 static IRExpr* ea_rA_idxd ( UInt rA, UInt rB )
1670 {
1671    IRType ty = mode64 ? Ity_I64 : Ity_I32;
1672    vassert(rA < 32);
1673    vassert(rB < 32);
1674    return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), getIReg(rB));
1675 }
1676 
1677 /* Standard effective address calc: (rA + simm) */
ea_rA_simm(UInt rA,UInt simm16)1678 static IRExpr* ea_rA_simm ( UInt rA, UInt simm16 )
1679 {
1680    IRType ty = mode64 ? Ity_I64 : Ity_I32;
1681    vassert(rA < 32);
1682    return binop(mkSzOp(ty, Iop_Add8), getIReg(rA),
1683                 mkSzExtendS16(ty, simm16));
1684 }
1685 
1686 /* Standard effective address calc: (rA|0) */
ea_rAor0(UInt rA)1687 static IRExpr* ea_rAor0 ( UInt rA )
1688 {
1689    IRType ty = mode64 ? Ity_I64 : Ity_I32;
1690    vassert(rA < 32);
1691    if (rA == 0) {
1692       return mkSzImm(ty, 0);
1693    } else {
1694       return getIReg(rA);
1695    }
1696 }
1697 
1698 /* Standard effective address calc: (rA|0) + rB */
ea_rAor0_idxd(UInt rA,UInt rB)1699 static IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB )
1700 {
1701    vassert(rA < 32);
1702    vassert(rB < 32);
1703    return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB );
1704 }
1705 
1706 /* Standard effective address calc: (rA|0) + simm16 */
ea_rAor0_simm(UInt rA,UInt simm16)1707 static IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 )
1708 {
1709    IRType ty = mode64 ? Ity_I64 : Ity_I32;
1710    vassert(rA < 32);
1711    if (rA == 0) {
1712       return mkSzExtendS16(ty, simm16);
1713    } else {
1714       return ea_rA_simm( rA, simm16 );
1715    }
1716 }
1717 
1718 
1719 /* Align effective address */
addr_align(IRExpr * addr,UChar align)1720 static IRExpr* addr_align( IRExpr* addr, UChar align )
1721 {
1722    IRType ty = mode64 ? Ity_I64 : Ity_I32;
1723    ULong mask;
1724    switch (align) {
1725    case 1:  return addr;                    // byte aligned
1726    case 2:  mask = ~0ULL << 1; break;       // half-word aligned
1727    case 4:  mask = ~0ULL << 2; break;       // word aligned
1728    case 16: mask = ~0ULL << 4; break;       // quad-word aligned
1729    default:
1730       vex_printf("addr_align: align = %u\n", align);
1731       vpanic("addr_align(ppc)");
1732    }
1733 
1734    vassert(typeOfIRExpr(irsb->tyenv,addr) == ty);
1735    return binop( mkSzOp(ty, Iop_And8), addr, mkSzImm(ty, mask) );
1736 }
1737 
1738 
1739 /* Exit the trace if ADDR (intended to be a guest memory address) is
1740    not ALIGN-aligned, generating a request for a SIGBUS followed by a
1741    restart of the current insn. */
gen_SIGBUS_if_misaligned(IRTemp addr,UChar align)1742 static void gen_SIGBUS_if_misaligned ( IRTemp addr, UChar align )
1743 {
1744    vassert(align == 2 || align == 4 || align == 8 || align == 16);
1745    if (mode64) {
1746       vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64);
1747       stmt(
1748          IRStmt_Exit(
1749             binop(Iop_CmpNE64,
1750                   binop(Iop_And64, mkexpr(addr), mkU64(align-1)),
1751                   mkU64(0)),
1752             Ijk_SigBUS,
1753             IRConst_U64( guest_CIA_curr_instr ), OFFB_CIA
1754          )
1755       );
1756    } else {
1757       vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32);
1758       stmt(
1759          IRStmt_Exit(
1760             binop(Iop_CmpNE32,
1761                   binop(Iop_And32, mkexpr(addr), mkU32(align-1)),
1762                   mkU32(0)),
1763             Ijk_SigBUS,
1764             IRConst_U32( guest_CIA_curr_instr ), OFFB_CIA
1765          )
1766       );
1767    }
1768 }
1769 
1770 
1771 /* Generate AbiHints which mark points at which the ELF or PowerOpen
1772    ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some
1773    N) becomes undefined.  That is at function calls and returns.  ELF
1774    ppc32 doesn't have this "feature" (how fortunate for it).  nia is
1775    the address of the next instruction to be executed.
1776 */
make_redzone_AbiHint(const VexAbiInfo * vbi,IRTemp nia,const HChar * who)1777 static void make_redzone_AbiHint ( const VexAbiInfo* vbi,
1778                                    IRTemp nia, const HChar* who )
1779 {
1780    Int szB = vbi->guest_stack_redzone_size;
1781    if (0) vex_printf("AbiHint: %s\n", who);
1782    vassert(szB >= 0);
1783    if (szB > 0) {
1784       if (mode64) {
1785          vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64);
1786          stmt( IRStmt_AbiHint(
1787                   binop(Iop_Sub64, getIReg(1), mkU64(szB)),
1788                   szB,
1789                   mkexpr(nia)
1790          ));
1791       } else {
1792          vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32);
1793          stmt( IRStmt_AbiHint(
1794                   binop(Iop_Sub32, getIReg(1), mkU32(szB)),
1795                   szB,
1796                   mkexpr(nia)
1797          ));
1798       }
1799    }
1800 }
1801 
1802 
1803 /*------------------------------------------------------------*/
1804 /*--- Helpers for condition codes.                         ---*/
1805 /*------------------------------------------------------------*/
1806 
1807 /* Condition register layout.
1808 
1809    In the hardware, CR is laid out like this.  The leftmost end is the
1810    most significant bit in the register; however the IBM documentation
1811    numbers the bits backwards for some reason.
1812 
1813    CR0      CR1    ..........   CR6       CR7
1814    0 .. 3   .......................  28 .. 31    (IBM bit numbering)
1815    31  28                             3    0     (normal bit numbering)
1816 
1817    Each CR field is 4 bits:  [<,>,==,SO]
1818 
1819    Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc.
1820 
1821    Indexing from BI to guest state:
1822 
1823      let    n = BI / 4
1824           off = BI % 4
1825      this references CR n:
1826 
1827         off==0   ->  guest_CRn_321 >> 3
1828         off==1   ->  guest_CRn_321 >> 2
1829         off==2   ->  guest_CRn_321 >> 1
1830         off==3   ->  guest_CRn_SO
1831 
1832    Bear in mind the only significant bit in guest_CRn_SO is bit 0
1833    (normal notation) and in guest_CRn_321 the significant bits are
1834    3, 2 and 1 (normal notation).
1835 */
1836 
putCR321(UInt cr,IRExpr * e)1837 static void putCR321 ( UInt cr, IRExpr* e )
1838 {
1839    vassert(cr < 8);
1840    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1841    stmt( IRStmt_Put(guestCR321offset(cr), e) );
1842 }
1843 
putCR0(UInt cr,IRExpr * e)1844 static void putCR0 ( UInt cr, IRExpr* e )
1845 {
1846    vassert(cr < 8);
1847    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1848    stmt( IRStmt_Put(guestCR0offset(cr), e) );
1849 }
1850 
getCR0(UInt cr)1851 static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr )
1852 {
1853    vassert(cr < 8);
1854    return IRExpr_Get(guestCR0offset(cr), Ity_I8);
1855 }
1856 
getCR321(UInt cr)1857 static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr )
1858 {
1859    vassert(cr < 8);
1860    return IRExpr_Get(guestCR321offset(cr), Ity_I8);
1861 }
1862 
1863 /* Fetch the specified CR bit (as per IBM/hardware notation) and
1864    return it at the bottom of an I32; the top 31 bits are guaranteed
1865    to be zero. */
getCRbit(UInt bi)1866 static IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi )
1867 {
1868    UInt n   = bi / 4;
1869    UInt off = bi % 4;
1870    vassert(bi < 32);
1871    if (off == 3) {
1872       /* Fetch the SO bit for this CR field */
1873       /* Note: And32 is redundant paranoia iff guest state only has 0
1874          or 1 in that slot. */
1875       return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
1876    } else {
1877       /* Fetch the <, > or == bit for this CR field */
1878       return binop( Iop_And32,
1879                     binop( Iop_Shr32,
1880                            unop(Iop_8Uto32, getCR321(n)),
1881                            mkU8(toUChar(3-off)) ),
1882                     mkU32(1) );
1883    }
1884 }
1885 
1886 /* Dually, write the least significant bit of BIT to the specified CR
1887    bit.  Indexing as per getCRbit. */
putCRbit(UInt bi,IRExpr * bit)1888 static void putCRbit ( UInt bi, IRExpr* bit )
1889 {
1890    UInt    n, off;
1891    IRExpr* safe;
1892    vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32);
1893    safe = binop(Iop_And32, bit, mkU32(1));
1894    n   = bi / 4;
1895    off = bi % 4;
1896    vassert(bi < 32);
1897    if (off == 3) {
1898       /* This is the SO bit for this CR field */
1899       putCR0(n, unop(Iop_32to8, safe));
1900    } else {
1901       off = 3 - off;
1902       vassert(off == 1 || off == 2 || off == 3);
1903       putCR321(
1904          n,
1905          unop( Iop_32to8,
1906                binop( Iop_Or32,
1907                       /* old value with field masked out */
1908                       binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)),
1909                                        mkU32(~(1 << off))),
1910                       /* new value in the right place */
1911                       binop(Iop_Shl32, safe, mkU8(toUChar(off)))
1912                )
1913          )
1914       );
1915    }
1916 }
1917 
1918 /* Fetch the specified CR bit (as per IBM/hardware notation) and
1919    return it somewhere in an I32; it does not matter where, but
1920    whichever bit it is, all other bits are guaranteed to be zero.  In
1921    other words, the I32-typed expression will be zero if the bit is
1922    zero and nonzero if the bit is 1.  Write into *where the index
1923    of where the bit will be. */
1924 
1925 static
getCRbit_anywhere(UInt bi,Int * where)1926 IRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where )
1927 {
1928    UInt n   = bi / 4;
1929    UInt off = bi % 4;
1930    vassert(bi < 32);
1931    if (off == 3) {
1932       /* Fetch the SO bit for this CR field */
1933       /* Note: And32 is redundant paranoia iff guest state only has 0
1934          or 1 in that slot. */
1935       *where = 0;
1936       return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
1937    } else {
1938       /* Fetch the <, > or == bit for this CR field */
1939       *where = 3-off;
1940       return binop( Iop_And32,
1941                     unop(Iop_8Uto32, getCR321(n)),
1942                     mkU32(1 << (3-off)) );
1943    }
1944 }
1945 
1946 /* Set the CR0 flags following an arithmetic operation.
1947    (Condition Register CR0 Field Definition, PPC32 p60)
1948 */
1949 static IRExpr* getXER_SO ( void );
set_CR0(IRExpr * result)1950 static void set_CR0 ( IRExpr* result )
1951 {
1952    vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_I32 ||
1953            typeOfIRExpr(irsb->tyenv,result) == Ity_I64);
1954    if (mode64) {
1955       putCR321( 0, unop(Iop_64to8,
1956                         binop(Iop_CmpORD64S, result, mkU64(0))) );
1957    } else {
1958       putCR321( 0, unop(Iop_32to8,
1959                         binop(Iop_CmpORD32S, result, mkU32(0))) );
1960    }
1961    putCR0( 0, getXER_SO() );
1962 }
1963 
1964 
1965 /* Set the CR6 flags following an AltiVec compare operation.
1966  * NOTE: This also works for VSX single-precision compares.
1967  * */
set_AV_CR6(IRExpr * result,Bool test_all_ones)1968 static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones )
1969 {
1970    /* CR6[0:3] = {all_ones, 0, all_zeros, 0}
1971       all_ones  = (v[0] && v[1] && v[2] && v[3])
1972       all_zeros = ~(v[0] || v[1] || v[2] || v[3])
1973    */
1974    IRTemp v0 = newTemp(Ity_V128);
1975    IRTemp v1 = newTemp(Ity_V128);
1976    IRTemp v2 = newTemp(Ity_V128);
1977    IRTemp v3 = newTemp(Ity_V128);
1978    IRTemp rOnes  = newTemp(Ity_I8);
1979    IRTemp rZeros = newTemp(Ity_I8);
1980 
1981    vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_V128);
1982 
1983    assign( v0, result );
1984    assign( v1, binop(Iop_ShrV128, result, mkU8(32)) );
1985    assign( v2, binop(Iop_ShrV128, result, mkU8(64)) );
1986    assign( v3, binop(Iop_ShrV128, result, mkU8(96)) );
1987 
1988    assign( rZeros, unop(Iop_1Uto8,
1989        binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
1990              unop(Iop_Not32,
1991                   unop(Iop_V128to32,
1992                        binop(Iop_OrV128,
1993                              binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)),
1994                              binop(Iop_OrV128, mkexpr(v2), mkexpr(v3))))
1995                   ))) );
1996 
1997    if (test_all_ones) {
1998       assign( rOnes, unop(Iop_1Uto8,
1999          binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
2000                unop(Iop_V128to32,
2001                     binop(Iop_AndV128,
2002                           binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)),
2003                           binop(Iop_AndV128, mkexpr(v2), mkexpr(v3)))
2004                     ))) );
2005       putCR321( 6, binop(Iop_Or8,
2006                          binop(Iop_Shl8, mkexpr(rOnes),  mkU8(3)),
2007                          binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) );
2008    } else {
2009       putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) );
2010    }
2011    putCR0( 6, mkU8(0) );
2012 }
2013 
2014 
2015 
2016 /*------------------------------------------------------------*/
2017 /*--- Helpers for XER flags.                               ---*/
2018 /*------------------------------------------------------------*/
2019 
putXER_SO(IRExpr * e)2020 static void putXER_SO ( IRExpr* e )
2021 {
2022    IRExpr* so;
2023    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2024    so = binop(Iop_And8, e, mkU8(1));
2025    stmt( IRStmt_Put( OFFB_XER_SO, so ) );
2026 }
2027 
putXER_OV(IRExpr * e)2028 static void putXER_OV ( IRExpr* e )
2029 {
2030    IRExpr* ov;
2031    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2032    ov = binop(Iop_And8, e, mkU8(1));
2033    stmt( IRStmt_Put( OFFB_XER_OV, ov ) );
2034 }
2035 
putXER_CA(IRExpr * e)2036 static void putXER_CA ( IRExpr* e )
2037 {
2038    IRExpr* ca;
2039    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2040    ca = binop(Iop_And8, e, mkU8(1));
2041    stmt( IRStmt_Put( OFFB_XER_CA, ca ) );
2042 }
2043 
putXER_BC(IRExpr * e)2044 static void putXER_BC ( IRExpr* e )
2045 {
2046    IRExpr* bc;
2047    vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2048    bc = binop(Iop_And8, e, mkU8(0x7F));
2049    stmt( IRStmt_Put( OFFB_XER_BC, bc ) );
2050 }
2051 
getXER_SO(void)2052 static IRExpr* /* :: Ity_I8 */ getXER_SO ( void )
2053 {
2054    return IRExpr_Get( OFFB_XER_SO, Ity_I8 );
2055 }
2056 
getXER_SO32(void)2057 static IRExpr* /* :: Ity_I32 */ getXER_SO32 ( void )
2058 {
2059    return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) );
2060 }
2061 
getXER_OV(void)2062 static IRExpr* /* :: Ity_I8 */ getXER_OV ( void )
2063 {
2064    return IRExpr_Get( OFFB_XER_OV, Ity_I8 );
2065 }
2066 
getXER_OV32(void)2067 static IRExpr* /* :: Ity_I32 */ getXER_OV32 ( void )
2068 {
2069    return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) );
2070 }
2071 
getXER_CA32(void)2072 static IRExpr* /* :: Ity_I32 */ getXER_CA32 ( void )
2073 {
2074    IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 );
2075    return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) );
2076 }
2077 
getXER_BC(void)2078 static IRExpr* /* :: Ity_I8 */ getXER_BC ( void )
2079 {
2080    return IRExpr_Get( OFFB_XER_BC, Ity_I8 );
2081 }
2082 
getXER_BC32(void)2083 static IRExpr* /* :: Ity_I32 */ getXER_BC32 ( void )
2084 {
2085    IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 );
2086    return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) );
2087 }
2088 
2089 
2090 /* RES is the result of doing OP on ARGL and ARGR.  Set %XER.OV and
2091    %XER.SO accordingly. */
2092 
set_XER_OV_32(UInt op,IRExpr * res,IRExpr * argL,IRExpr * argR)2093 static void set_XER_OV_32( UInt op, IRExpr* res,
2094                            IRExpr* argL, IRExpr* argR )
2095 {
2096    IRTemp  t64;
2097    IRExpr* xer_ov;
2098    vassert(op < PPCG_FLAG_OP_NUMBER);
2099    vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I32);
2100    vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32);
2101    vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32);
2102 
2103 #  define INT32_MIN 0x80000000
2104 
2105 #  define XOR2(_aa,_bb) \
2106       binop(Iop_Xor32,(_aa),(_bb))
2107 
2108 #  define XOR3(_cc,_dd,_ee) \
2109       binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee))
2110 
2111 #  define AND3(_ff,_gg,_hh) \
2112       binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh))
2113 
2114 #define NOT(_jj) \
2115       unop(Iop_Not32, (_jj))
2116 
2117    switch (op) {
2118    case /* 0  */ PPCG_FLAG_OP_ADD:
2119    case /* 1  */ PPCG_FLAG_OP_ADDE:
2120       /* (argL^argR^-1) & (argL^res) & (1<<31)  ?1:0 */
2121       // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
2122       xer_ov
2123          = AND3( XOR3(argL,argR,mkU32(-1)),
2124                  XOR2(argL,res),
2125                  mkU32(INT32_MIN) );
2126       /* xer_ov can only be 0 or 1<<31 */
2127       xer_ov
2128          = binop(Iop_Shr32, xer_ov, mkU8(31) );
2129       break;
2130 
2131    case /* 2  */ PPCG_FLAG_OP_DIVW:
2132       /* (argL == INT32_MIN && argR == -1) || argR == 0 */
2133       xer_ov
2134          = mkOR1(
2135               mkAND1(
2136                  binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)),
2137                  binop(Iop_CmpEQ32, argR, mkU32(-1))
2138               ),
2139               binop(Iop_CmpEQ32, argR, mkU32(0) )
2140            );
2141       xer_ov
2142          = unop(Iop_1Uto32, xer_ov);
2143       break;
2144 
2145    case /* 3  */ PPCG_FLAG_OP_DIVWU:
2146       /* argR == 0 */
2147       xer_ov
2148          = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0)));
2149       break;
2150 
2151    case /* 4  */ PPCG_FLAG_OP_MULLW:
2152       /* OV true if result can't be represented in 32 bits
2153          i.e sHi != sign extension of sLo */
2154       t64 = newTemp(Ity_I64);
2155       assign( t64, binop(Iop_MullS32, argL, argR) );
2156       xer_ov
2157          = binop( Iop_CmpNE32,
2158                   unop(Iop_64HIto32, mkexpr(t64)),
2159                   binop( Iop_Sar32,
2160                          unop(Iop_64to32, mkexpr(t64)),
2161                          mkU8(31))
2162                   );
2163       xer_ov
2164          = unop(Iop_1Uto32, xer_ov);
2165       break;
2166 
2167    case /* 5  */ PPCG_FLAG_OP_NEG:
2168       /* argL == INT32_MIN */
2169       xer_ov
2170          = unop( Iop_1Uto32,
2171                  binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) );
2172       break;
2173 
2174    case /* 6  */ PPCG_FLAG_OP_SUBF:
2175    case /* 7  */ PPCG_FLAG_OP_SUBFC:
2176    case /* 8  */ PPCG_FLAG_OP_SUBFE:
2177       /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */
2178       xer_ov
2179          = AND3( XOR3(NOT(argL),argR,mkU32(-1)),
2180                  XOR2(NOT(argL),res),
2181                  mkU32(INT32_MIN) );
2182       /* xer_ov can only be 0 or 1<<31 */
2183       xer_ov
2184          = binop(Iop_Shr32, xer_ov, mkU8(31) );
2185       break;
2186 
2187    case PPCG_FLAG_OP_DIVWEU:
2188       xer_ov
2189                = binop( Iop_Or32,
2190                         unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
2191                         unop( Iop_1Uto32, binop( Iop_CmpLT32U, argR, argL ) ) );
2192       break;
2193 
2194    case PPCG_FLAG_OP_DIVWE:
2195 
2196       /* If argR == 0 of if the result cannot fit in the 32-bit destination register,
2197        * then OV <- 1.   If dest reg is 0 AND both dividend and divisor are non-zero,
2198        * an overflow is implied.
2199        */
2200       xer_ov = binop( Iop_Or32,
2201                       unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
2202                       unop( Iop_1Uto32, mkAND1( binop( Iop_CmpEQ32, res, mkU32( 0 ) ),
2203                               mkAND1( binop( Iop_CmpNE32, argL, mkU32( 0 ) ),
2204                                       binop( Iop_CmpNE32, argR, mkU32( 0 ) ) ) ) ) );
2205       break;
2206 
2207 
2208 
2209    default:
2210       vex_printf("set_XER_OV: op = %u\n", op);
2211       vpanic("set_XER_OV(ppc)");
2212    }
2213 
2214    /* xer_ov MUST denote either 0 or 1, no other value allowed */
2215    putXER_OV( unop(Iop_32to8, xer_ov) );
2216 
2217    /* Update the summary overflow */
2218    putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
2219 
2220 #  undef INT32_MIN
2221 #  undef AND3
2222 #  undef XOR3
2223 #  undef XOR2
2224 #  undef NOT
2225 }
2226 
set_XER_OV_64(UInt op,IRExpr * res,IRExpr * argL,IRExpr * argR)2227 static void set_XER_OV_64( UInt op, IRExpr* res,
2228                            IRExpr* argL, IRExpr* argR )
2229 {
2230    IRExpr* xer_ov;
2231    vassert(op < PPCG_FLAG_OP_NUMBER);
2232    vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I64);
2233    vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64);
2234    vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64);
2235 
2236 #  define INT64_MIN 0x8000000000000000ULL
2237 
2238 #  define XOR2(_aa,_bb) \
2239       binop(Iop_Xor64,(_aa),(_bb))
2240 
2241 #  define XOR3(_cc,_dd,_ee) \
2242       binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee))
2243 
2244 #  define AND3(_ff,_gg,_hh) \
2245       binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh))
2246 
2247 #define NOT(_jj) \
2248       unop(Iop_Not64, (_jj))
2249 
2250    switch (op) {
2251    case /* 0  */ PPCG_FLAG_OP_ADD:
2252    case /* 1  */ PPCG_FLAG_OP_ADDE:
2253       /* (argL^argR^-1) & (argL^res) & (1<<63)  ? 1:0 */
2254       // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
2255       xer_ov
2256          = AND3( XOR3(argL,argR,mkU64(-1)),
2257                  XOR2(argL,res),
2258                  mkU64(INT64_MIN) );
2259       /* xer_ov can only be 0 or 1<<63 */
2260       xer_ov
2261          = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
2262       break;
2263 
2264    case /* 2  */ PPCG_FLAG_OP_DIVW:
2265       /* (argL == INT64_MIN && argR == -1) || argR == 0 */
2266       xer_ov
2267          = mkOR1(
2268               mkAND1(
2269                  binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)),
2270                  binop(Iop_CmpEQ64, argR, mkU64(-1))
2271               ),
2272               binop(Iop_CmpEQ64, argR, mkU64(0) )
2273            );
2274       break;
2275 
2276    case /* 3  */ PPCG_FLAG_OP_DIVWU:
2277       /* argR == 0 */
2278       xer_ov
2279          = binop(Iop_CmpEQ64, argR, mkU64(0));
2280       break;
2281 
2282    case /* 4  */ PPCG_FLAG_OP_MULLW: {
2283       /* OV true if result can't be represented in 64 bits
2284          i.e sHi != sign extension of sLo */
2285       xer_ov
2286          = binop( Iop_CmpNE32,
2287                   unop(Iop_64HIto32, res),
2288                   binop( Iop_Sar32,
2289                          unop(Iop_64to32, res),
2290                          mkU8(31))
2291                   );
2292       break;
2293    }
2294 
2295    case /* 5  */ PPCG_FLAG_OP_NEG:
2296       /* argL == INT64_MIN */
2297       xer_ov
2298          = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN));
2299       break;
2300 
2301    case /* 6  */ PPCG_FLAG_OP_SUBF:
2302    case /* 7  */ PPCG_FLAG_OP_SUBFC:
2303    case /* 8  */ PPCG_FLAG_OP_SUBFE:
2304       /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */
2305       xer_ov
2306          = AND3( XOR3(NOT(argL),argR,mkU64(-1)),
2307                  XOR2(NOT(argL),res),
2308                  mkU64(INT64_MIN) );
2309       /* xer_ov can only be 0 or 1<<63 */
2310       xer_ov
2311          = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
2312       break;
2313 
2314    case PPCG_FLAG_OP_DIVDE:
2315 
2316       /* If argR == 0, we must set the OV bit.  But there's another condition
2317        * where we can get overflow set for divde . . . when the
2318        * result cannot fit in the 64-bit destination register.  If dest reg is 0 AND
2319        * both dividend and divisor are non-zero, it implies an overflow.
2320        */
2321       xer_ov
2322                   = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
2323                            mkAND1( binop( Iop_CmpEQ64, res, mkU64( 0 ) ),
2324                                    mkAND1( binop( Iop_CmpNE64, argL, mkU64( 0 ) ),
2325                                            binop( Iop_CmpNE64, argR, mkU64( 0 ) ) ) ) );
2326       break;
2327 
2328    case PPCG_FLAG_OP_DIVDEU:
2329      /* If argR == 0 or if argL >= argR, set OV. */
2330      xer_ov = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
2331                          binop( Iop_CmpLE64U, argR, argL ) );
2332      break;
2333 
2334    case /* 18 */ PPCG_FLAG_OP_MULLD: {
2335       IRTemp  t128;
2336       /* OV true if result can't be represented in 64 bits
2337          i.e sHi != sign extension of sLo */
2338       t128 = newTemp(Ity_I128);
2339       assign( t128, binop(Iop_MullS64, argL, argR) );
2340       xer_ov
2341          = binop( Iop_CmpNE64,
2342                   unop(Iop_128HIto64, mkexpr(t128)),
2343                   binop( Iop_Sar64,
2344                          unop(Iop_128to64, mkexpr(t128)),
2345                          mkU8(63))
2346                   );
2347       break;
2348    }
2349 
2350    default:
2351       vex_printf("set_XER_OV: op = %u\n", op);
2352       vpanic("set_XER_OV(ppc64)");
2353    }
2354 
2355    /* xer_ov MUST denote either 0 or 1, no other value allowed */
2356    putXER_OV( unop(Iop_1Uto8, xer_ov) );
2357 
2358    /* Update the summary overflow */
2359    putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
2360 
2361 #  undef INT64_MIN
2362 #  undef AND3
2363 #  undef XOR3
2364 #  undef XOR2
2365 #  undef NOT
2366 }
2367 
set_XER_OV(IRType ty,UInt op,IRExpr * res,IRExpr * argL,IRExpr * argR)2368 static void set_XER_OV ( IRType ty, UInt op, IRExpr* res,
2369                          IRExpr* argL, IRExpr* argR )
2370 {
2371    if (ty == Ity_I32)
2372       set_XER_OV_32( op, res, argL, argR );
2373    else
2374       set_XER_OV_64( op, res, argL, argR );
2375 }
2376 
2377 
2378 
2379 /* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA
2380    value being OLDCA.  Set %XER.CA accordingly. */
2381 
set_XER_CA_32(UInt op,IRExpr * res,IRExpr * argL,IRExpr * argR,IRExpr * oldca)2382 static void set_XER_CA_32 ( UInt op, IRExpr* res,
2383                             IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2384 {
2385    IRExpr* xer_ca;
2386    vassert(op < PPCG_FLAG_OP_NUMBER);
2387    vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I32);
2388    vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I32);
2389    vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I32);
2390    vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I32);
2391 
2392    /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
2393       seems reasonable given that it's always generated by
2394       getXER_CA32(), which masks it accordingly.  In any case it being
2395       0 or 1 is an invariant of the ppc guest state representation;
2396       if it has any other value, that invariant has been violated. */
2397 
2398    switch (op) {
2399    case /* 0 */ PPCG_FLAG_OP_ADD:
2400       /* res <u argL */
2401       xer_ca
2402          = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL));
2403       break;
2404 
2405    case /* 1 */ PPCG_FLAG_OP_ADDE:
2406       /* res <u argL || (old_ca==1 && res==argL) */
2407       xer_ca
2408          = mkOR1(
2409               binop(Iop_CmpLT32U, res, argL),
2410               mkAND1(
2411                  binop(Iop_CmpEQ32, oldca, mkU32(1)),
2412                  binop(Iop_CmpEQ32, res, argL)
2413               )
2414            );
2415       xer_ca
2416          = unop(Iop_1Uto32, xer_ca);
2417       break;
2418 
2419    case /* 8 */ PPCG_FLAG_OP_SUBFE:
2420       /* res <u argR || (old_ca==1 && res==argR) */
2421       xer_ca
2422          = mkOR1(
2423               binop(Iop_CmpLT32U, res, argR),
2424               mkAND1(
2425                  binop(Iop_CmpEQ32, oldca, mkU32(1)),
2426                  binop(Iop_CmpEQ32, res, argR)
2427               )
2428            );
2429       xer_ca
2430          = unop(Iop_1Uto32, xer_ca);
2431       break;
2432 
2433    case /* 7 */ PPCG_FLAG_OP_SUBFC:
2434    case /* 9 */ PPCG_FLAG_OP_SUBFI:
2435       /* res <=u argR */
2436       xer_ca
2437          = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR));
2438       break;
2439 
2440    case /* 10 */ PPCG_FLAG_OP_SRAW:
2441       /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
2442          If it is <= 31, behave like SRAWI; else XER.CA is the sign
2443          bit of argL. */
2444       /* This term valid for shift amount < 32 only */
2445       xer_ca
2446          = binop(
2447               Iop_And32,
2448               binop(Iop_Sar32, argL, mkU8(31)),
2449               binop( Iop_And32,
2450                      argL,
2451                      binop( Iop_Sub32,
2452                             binop(Iop_Shl32, mkU32(1),
2453                                              unop(Iop_32to8,argR)),
2454                             mkU32(1) )
2455                      )
2456               );
2457       xer_ca
2458          = IRExpr_ITE(
2459               /* shift amt > 31 ? */
2460               binop(Iop_CmpLT32U, mkU32(31), argR),
2461               /* yes -- get sign bit of argL */
2462               binop(Iop_Shr32, argL, mkU8(31)),
2463               /* no -- be like srawi */
2464               unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)))
2465            );
2466       break;
2467 
2468    case /* 11 */ PPCG_FLAG_OP_SRAWI:
2469       /* xer_ca is 1 iff src was negative and bits_shifted_out !=
2470          0.  Since the shift amount is known to be in the range
2471          0 .. 31 inclusive the following seems viable:
2472          xer.ca == 1 iff the following is nonzero:
2473          (argL >>s 31)           -- either all 0s or all 1s
2474          & (argL & (1<<argR)-1)  -- the stuff shifted out */
2475       xer_ca
2476          = binop(
2477               Iop_And32,
2478               binop(Iop_Sar32, argL, mkU8(31)),
2479               binop( Iop_And32,
2480                      argL,
2481                      binop( Iop_Sub32,
2482                             binop(Iop_Shl32, mkU32(1),
2483                                              unop(Iop_32to8,argR)),
2484                             mkU32(1) )
2485                      )
2486               );
2487       xer_ca
2488          = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)));
2489       break;
2490 
2491    default:
2492       vex_printf("set_XER_CA: op = %u\n", op);
2493       vpanic("set_XER_CA(ppc)");
2494    }
2495 
2496    /* xer_ca MUST denote either 0 or 1, no other value allowed */
2497    putXER_CA( unop(Iop_32to8, xer_ca) );
2498 }
2499 
set_XER_CA_64(UInt op,IRExpr * res,IRExpr * argL,IRExpr * argR,IRExpr * oldca)2500 static void set_XER_CA_64 ( UInt op, IRExpr* res,
2501                             IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2502 {
2503    IRExpr* xer_ca;
2504    vassert(op < PPCG_FLAG_OP_NUMBER);
2505    vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I64);
2506    vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I64);
2507    vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I64);
2508    vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I64);
2509 
2510    /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
2511       seems reasonable given that it's always generated by
2512       getXER_CA32(), which masks it accordingly.  In any case it being
2513       0 or 1 is an invariant of the ppc guest state representation;
2514       if it has any other value, that invariant has been violated. */
2515 
2516    switch (op) {
2517    case /* 0 */ PPCG_FLAG_OP_ADD:
2518       /* res <u argL */
2519       xer_ca
2520          = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL));
2521       break;
2522 
2523    case /* 1 */ PPCG_FLAG_OP_ADDE:
2524       /* res <u argL || (old_ca==1 && res==argL) */
2525       xer_ca
2526          = mkOR1(
2527               binop(Iop_CmpLT64U, res, argL),
2528               mkAND1(
2529                  binop(Iop_CmpEQ64, oldca, mkU64(1)),
2530                  binop(Iop_CmpEQ64, res, argL)
2531                  )
2532               );
2533       xer_ca
2534          = unop(Iop_1Uto32, xer_ca);
2535       break;
2536 
2537    case /* 8 */ PPCG_FLAG_OP_SUBFE:
2538       /* res <u argR || (old_ca==1 && res==argR) */
2539       xer_ca
2540          = mkOR1(
2541               binop(Iop_CmpLT64U, res, argR),
2542               mkAND1(
2543                  binop(Iop_CmpEQ64, oldca, mkU64(1)),
2544                  binop(Iop_CmpEQ64, res, argR)
2545               )
2546            );
2547       xer_ca
2548          = unop(Iop_1Uto32, xer_ca);
2549       break;
2550 
2551    case /* 7 */ PPCG_FLAG_OP_SUBFC:
2552    case /* 9 */ PPCG_FLAG_OP_SUBFI:
2553       /* res <=u argR */
2554       xer_ca
2555          = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR));
2556       break;
2557 
2558 
2559    case /* 10 */ PPCG_FLAG_OP_SRAW:
2560       /* The shift amount is guaranteed to be in 0 .. 31 inclusive.
2561          If it is <= 31, behave like SRAWI; else XER.CA is the sign
2562          bit of argL. */
2563          /* This term valid for shift amount < 31 only */
2564 
2565       xer_ca
2566          = binop(
2567               Iop_And64,
2568               binop(Iop_Sar64, argL, mkU8(31)),
2569               binop( Iop_And64,
2570                      argL,
2571                      binop( Iop_Sub64,
2572                             binop(Iop_Shl64, mkU64(1),
2573                                              unop(Iop_64to8,argR)),
2574                             mkU64(1) )
2575               )
2576            );
2577       xer_ca
2578          = IRExpr_ITE(
2579               /* shift amt > 31 ? */
2580               binop(Iop_CmpLT64U, mkU64(31), argR),
2581               /* yes -- get sign bit of argL */
2582               unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))),
2583               /* no -- be like srawi */
2584               unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)))
2585           );
2586       break;
2587 
2588    case /* 11 */ PPCG_FLAG_OP_SRAWI:
2589       /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
2590          Since the shift amount is known to be in the range 0 .. 31
2591          inclusive the following seems viable:
2592          xer.ca == 1 iff the following is nonzero:
2593          (argL >>s 31)           -- either all 0s or all 1s
2594          & (argL & (1<<argR)-1)  -- the stuff shifted out */
2595 
2596       xer_ca
2597          = binop(
2598               Iop_And64,
2599               binop(Iop_Sar64, argL, mkU8(31)),
2600               binop( Iop_And64,
2601                      argL,
2602                      binop( Iop_Sub64,
2603                             binop(Iop_Shl64, mkU64(1),
2604                                              unop(Iop_64to8,argR)),
2605                             mkU64(1) )
2606               )
2607            );
2608       xer_ca
2609          = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
2610       break;
2611 
2612 
2613    case /* 12 */ PPCG_FLAG_OP_SRAD:
2614       /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
2615          If it is <= 63, behave like SRADI; else XER.CA is the sign
2616          bit of argL. */
2617          /* This term valid for shift amount < 63 only */
2618 
2619       xer_ca
2620          = binop(
2621               Iop_And64,
2622               binop(Iop_Sar64, argL, mkU8(63)),
2623               binop( Iop_And64,
2624                      argL,
2625                      binop( Iop_Sub64,
2626                             binop(Iop_Shl64, mkU64(1),
2627                                              unop(Iop_64to8,argR)),
2628                             mkU64(1) )
2629               )
2630            );
2631       xer_ca
2632          = IRExpr_ITE(
2633               /* shift amt > 63 ? */
2634               binop(Iop_CmpLT64U, mkU64(63), argR),
2635               /* yes -- get sign bit of argL */
2636               unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))),
2637               /* no -- be like sradi */
2638               unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)))
2639            );
2640       break;
2641 
2642 
2643    case /* 13 */ PPCG_FLAG_OP_SRADI:
2644       /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
2645          Since the shift amount is known to be in the range 0 .. 63
2646          inclusive, the following seems viable:
2647          xer.ca == 1 iff the following is nonzero:
2648          (argL >>s 63)           -- either all 0s or all 1s
2649          & (argL & (1<<argR)-1)  -- the stuff shifted out */
2650 
2651       xer_ca
2652          = binop(
2653               Iop_And64,
2654               binop(Iop_Sar64, argL, mkU8(63)),
2655               binop( Iop_And64,
2656                      argL,
2657                      binop( Iop_Sub64,
2658                             binop(Iop_Shl64, mkU64(1),
2659                                              unop(Iop_64to8,argR)),
2660                             mkU64(1) )
2661               )
2662            );
2663       xer_ca
2664          = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
2665       break;
2666 
2667    default:
2668       vex_printf("set_XER_CA: op = %u\n", op);
2669       vpanic("set_XER_CA(ppc64)");
2670    }
2671 
2672    /* xer_ca MUST denote either 0 or 1, no other value allowed */
2673    putXER_CA( unop(Iop_32to8, xer_ca) );
2674 }
2675 
set_XER_CA(IRType ty,UInt op,IRExpr * res,IRExpr * argL,IRExpr * argR,IRExpr * oldca)2676 static void set_XER_CA ( IRType ty, UInt op, IRExpr* res,
2677                          IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2678 {
2679    if (ty == Ity_I32)
2680       set_XER_CA_32( op, res, argL, argR, oldca );
2681    else
2682       set_XER_CA_64( op, res, argL, argR, oldca );
2683 }
2684 
2685 
2686 
2687 /*------------------------------------------------------------*/
2688 /*--- Read/write to guest-state                           --- */
2689 /*------------------------------------------------------------*/
2690 
getGST(PPC_GST reg)2691 static IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg )
2692 {
2693    IRType ty = mode64 ? Ity_I64 : Ity_I32;
2694    switch (reg) {
2695    case PPC_GST_SPRG3_RO:
2696       return IRExpr_Get( OFFB_SPRG3_RO, ty );
2697 
2698    case PPC_GST_CIA:
2699       return IRExpr_Get( OFFB_CIA, ty );
2700 
2701    case PPC_GST_LR:
2702       return IRExpr_Get( OFFB_LR, ty );
2703 
2704    case PPC_GST_CTR:
2705       return IRExpr_Get( OFFB_CTR, ty );
2706 
2707    case PPC_GST_VRSAVE:
2708       return IRExpr_Get( OFFB_VRSAVE, Ity_I32 );
2709 
2710    case PPC_GST_VSCR:
2711       return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ),
2712                               mkU32(MASK_VSCR_VALID));
2713 
2714    case PPC_GST_CR: {
2715       /* Synthesise the entire CR into a single word.  Expensive. */
2716 #     define FIELD(_n)                                               \
2717          binop(Iop_Shl32,                                            \
2718                unop(Iop_8Uto32,                                      \
2719                     binop(Iop_Or8,                                   \
2720                           binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \
2721                           binop(Iop_And8, getCR0(_n), mkU8(1))       \
2722                     )                                                \
2723                ),                                                    \
2724                mkU8(4 * (7-(_n)))                                    \
2725          )
2726       return binop(Iop_Or32,
2727                    binop(Iop_Or32,
2728                          binop(Iop_Or32, FIELD(0), FIELD(1)),
2729                          binop(Iop_Or32, FIELD(2), FIELD(3))
2730                          ),
2731                    binop(Iop_Or32,
2732                          binop(Iop_Or32, FIELD(4), FIELD(5)),
2733                          binop(Iop_Or32, FIELD(6), FIELD(7))
2734                          )
2735                    );
2736 #     undef FIELD
2737    }
2738 
2739    case PPC_GST_XER:
2740       return binop(Iop_Or32,
2741                    binop(Iop_Or32,
2742                          binop( Iop_Shl32, getXER_SO32(), mkU8(31)),
2743                          binop( Iop_Shl32, getXER_OV32(), mkU8(30))),
2744                    binop(Iop_Or32,
2745                          binop( Iop_Shl32, getXER_CA32(), mkU8(29)),
2746                          getXER_BC32()));
2747 
2748    case PPC_GST_TFHAR:
2749       return IRExpr_Get( OFFB_TFHAR, ty );
2750 
2751    case PPC_GST_TEXASR:
2752       return IRExpr_Get( OFFB_TEXASR, ty );
2753 
2754    case PPC_GST_TEXASRU:
2755       return IRExpr_Get( OFFB_TEXASRU, ty );
2756 
2757    case PPC_GST_TFIAR:
2758       return IRExpr_Get( OFFB_TFIAR, ty );
2759 
2760    case PPC_GST_PPR:
2761       return IRExpr_Get( OFFB_PPR, ty );
2762 
2763    case PPC_GST_PPR32:
2764       return unop( Iop_64HIto32, IRExpr_Get( OFFB_PPR, ty ) );
2765 
2766    case PPC_GST_PSPB:
2767       return IRExpr_Get( OFFB_PSPB, ty );
2768 
2769    default:
2770       vex_printf("getGST(ppc): reg = %u", reg);
2771       vpanic("getGST(ppc)");
2772    }
2773 }
2774 
2775 /* Get a masked word from the given reg */
getGST_masked(PPC_GST reg,UInt mask)2776 static IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, UInt mask )
2777 {
2778    IRTemp val = newTemp(Ity_I32);
2779    vassert( reg < PPC_GST_MAX );
2780 
2781    switch (reg) {
2782 
2783    case PPC_GST_FPSCR: {
2784       /* Vex-generated code expects the FPSCR to be set as follows:
2785          all exceptions masked, round-to-nearest.
2786          This corresponds to a FPSCR value of 0x0. */
2787 
2788       /* In the lower 32 bits of FPSCR, we're only keeping track of
2789        * the binary floating point rounding mode, so if the mask isn't
2790        * asking for this, just return 0x0.
2791        */
2792       if (mask & MASK_FPSCR_RN) {
2793          assign( val, unop( Iop_8Uto32, IRExpr_Get( OFFB_FPROUND, Ity_I8 ) ) );
2794       } else {
2795          assign( val, mkU32(0x0) );
2796       }
2797       break;
2798    }
2799 
2800    default:
2801       vex_printf("getGST_masked(ppc): reg = %u", reg);
2802       vpanic("getGST_masked(ppc)");
2803    }
2804 
2805    if (mask != 0xFFFFFFFF) {
2806       return binop(Iop_And32, mkexpr(val), mkU32(mask));
2807    } else {
2808       return mkexpr(val);
2809    }
2810 }
2811 
2812 /* Get a masked word from the given reg */
getGST_masked_upper(PPC_GST reg,ULong mask)2813 static IRExpr* /* ::Ity_I32 */getGST_masked_upper(PPC_GST reg, ULong mask) {
2814    IRExpr * val;
2815    vassert( reg < PPC_GST_MAX );
2816 
2817    switch (reg) {
2818 
2819    case PPC_GST_FPSCR: {
2820       /* In the upper 32 bits of FPSCR, we're only keeping track
2821        * of the decimal floating point rounding mode, so if the mask
2822        * isn't asking for this, just return 0x0.
2823        */
2824       if (mask & MASK_FPSCR_DRN) {
2825          val = binop( Iop_And32,
2826                       unop( Iop_8Uto32, IRExpr_Get( OFFB_DFPROUND, Ity_I8 ) ),
2827                       unop( Iop_64HIto32, mkU64( mask ) ) );
2828       } else {
2829          val = mkU32( 0x0ULL );
2830       }
2831       break;
2832    }
2833 
2834    default:
2835       vex_printf( "getGST_masked_upper(ppc): reg = %u", reg );
2836       vpanic( "getGST_masked_upper(ppc)" );
2837    }
2838    return val;
2839 }
2840 
2841 
2842 /* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation)
2843    and return it at the bottom of an I32; the top 27 bits are
2844    guaranteed to be zero. */
getGST_field(PPC_GST reg,UInt fld)2845 static IRExpr* /* ::Ity_I32 */ getGST_field ( PPC_GST reg, UInt fld )
2846 {
2847    UInt shft, mask;
2848 
2849    vassert( fld < 8 );
2850    vassert( reg < PPC_GST_MAX );
2851 
2852    shft = 4*(7-fld);
2853    mask = 0xF<<shft;
2854 
2855    switch (reg) {
2856    case PPC_GST_XER:
2857       vassert(fld ==7);
2858       return binop(Iop_Or32,
2859                    binop(Iop_Or32,
2860                          binop(Iop_Shl32, getXER_SO32(), mkU8(3)),
2861                          binop(Iop_Shl32, getXER_OV32(), mkU8(2))),
2862                    binop(      Iop_Shl32, getXER_CA32(), mkU8(1)));
2863       break;
2864 
2865    default:
2866       if (shft == 0)
2867          return getGST_masked( reg, mask );
2868       else
2869          return binop(Iop_Shr32,
2870                       getGST_masked( reg, mask ),
2871                       mkU8(toUChar( shft )));
2872    }
2873 }
2874 
putGST(PPC_GST reg,IRExpr * src)2875 static void putGST ( PPC_GST reg, IRExpr* src )
2876 {
2877    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
2878    IRType ty_src = typeOfIRExpr(irsb->tyenv,src );
2879    vassert( reg < PPC_GST_MAX );
2880    switch (reg) {
2881    case PPC_GST_IP_AT_SYSCALL:
2882       vassert( ty_src == ty );
2883       stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) );
2884       break;
2885    case PPC_GST_CIA:
2886       vassert( ty_src == ty );
2887       stmt( IRStmt_Put( OFFB_CIA, src ) );
2888       break;
2889    case PPC_GST_LR:
2890       vassert( ty_src == ty );
2891       stmt( IRStmt_Put( OFFB_LR, src ) );
2892       break;
2893    case PPC_GST_CTR:
2894       vassert( ty_src == ty );
2895       stmt( IRStmt_Put( OFFB_CTR, src ) );
2896       break;
2897    case PPC_GST_VRSAVE:
2898       vassert( ty_src == Ity_I32 );
2899       stmt( IRStmt_Put( OFFB_VRSAVE,src));
2900       break;
2901    case PPC_GST_VSCR:
2902       vassert( ty_src == Ity_I32 );
2903       stmt( IRStmt_Put( OFFB_VSCR,
2904                         binop(Iop_And32, src,
2905                               mkU32(MASK_VSCR_VALID)) ) );
2906       break;
2907    case PPC_GST_XER:
2908       vassert( ty_src == Ity_I32 );
2909       putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) );
2910       putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) );
2911       putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) );
2912       putXER_BC( unop(Iop_32to8, src) );
2913       break;
2914 
2915    case PPC_GST_EMWARN:
2916       vassert( ty_src == Ity_I32 );
2917       stmt( IRStmt_Put( OFFB_EMNOTE,src) );
2918       break;
2919 
2920    case PPC_GST_CMSTART:
2921       vassert( ty_src == ty );
2922       stmt( IRStmt_Put( OFFB_CMSTART, src) );
2923       break;
2924 
2925    case PPC_GST_CMLEN:
2926       vassert( ty_src == ty );
2927       stmt( IRStmt_Put( OFFB_CMLEN, src) );
2928       break;
2929 
2930    case PPC_GST_TEXASR:
2931       vassert( ty_src == Ity_I64 );
2932       stmt( IRStmt_Put( OFFB_TEXASR, src ) );
2933       break;
2934 
2935    case PPC_GST_TEXASRU:
2936       vassert( ty_src == Ity_I32 );
2937       stmt( IRStmt_Put( OFFB_TEXASRU, src ) );
2938       break;
2939 
2940    case PPC_GST_TFIAR:
2941       vassert( ty_src == Ity_I64 );
2942       stmt( IRStmt_Put( OFFB_TFIAR, src ) );
2943       break;
2944    case PPC_GST_TFHAR:
2945       vassert( ty_src == Ity_I64 );
2946       stmt( IRStmt_Put( OFFB_TFHAR, src ) );
2947       break;
2948 
2949    case PPC_GST_PPR32:
2950    case PPC_GST_PPR:
2951       {
2952          /* The Program Priority Register (PPR) stores the priority in
2953           * bits [52:50].  The user setable priorities are:
2954           *
2955           *    001  very low
2956           *    010  low
2957           *    011  medium low
2958           *    100  medium
2959           *    101  medium high
2960           *
2961           * If the argument is not between 0b001 and 0b100 the priority is set
2962           * to 0b100.  The priority can only be set to 0b101 if the the Problem
2963           * State Boost Register is non-zero.  The value of the PPR is not
2964           * changed if the input is not valid.
2965           */
2966 
2967          IRTemp not_valid = newTemp(Ity_I64);
2968          IRTemp has_perm = newTemp(Ity_I64);
2969          IRTemp new_src  = newTemp(Ity_I64);
2970          IRTemp PSPB_val = newTemp(Ity_I64);
2971          IRTemp value    = newTemp(Ity_I64);
2972 
2973          vassert(( ty_src == Ity_I64 ) || ( ty_src == Ity_I32 ));
2974          assign( PSPB_val, binop( Iop_32HLto64,
2975                                   mkU32( 0 ),
2976                                   IRExpr_Get( OFFB_PSPB, Ity_I32 ) ) );
2977          if( reg == PPC_GST_PPR32 ) {
2978             vassert( ty_src == Ity_I32 );
2979             assign( value, binop( Iop_32HLto64,
2980                                   mkU32(0),
2981                                   binop( Iop_And32,
2982                                          binop( Iop_Shr32, src,  mkU8( 18 ) ),
2983                                          mkU32( 0x7 ) ) ) );
2984          } else {
2985             vassert( ty_src == Ity_I64 );
2986             assign( value, binop( Iop_And64,
2987                                   binop( Iop_Shr64, src,  mkU8( 50 ) ),
2988                                   mkU64( 0x7 ) ) );
2989          }
2990          assign( has_perm,
2991                  binop( Iop_And64,
2992                         unop( Iop_1Sto64,
2993                               binop( Iop_CmpEQ64,
2994                                      mkexpr( PSPB_val ),
2995                                      mkU64( 0 ) ) ),
2996                         unop( Iop_1Sto64,
2997                               binop( Iop_CmpEQ64,
2998                                      mkU64( 0x5 ),
2999                                      mkexpr( value ) ) ) ) );
3000          assign( not_valid,
3001                  binop( Iop_Or64,
3002                         unop( Iop_1Sto64,
3003                               binop( Iop_CmpEQ64,
3004                                      mkexpr( value ),
3005                                      mkU64( 0 ) ) ),
3006                         unop( Iop_1Sto64,
3007                               binop( Iop_CmpLT64U,
3008                                      mkU64( 0x5 ),
3009                                      mkexpr( value ) ) ) ) );
3010          assign( new_src,
3011                  binop( Iop_Or64,
3012                         binop( Iop_And64,
3013                                unop( Iop_Not64,
3014                                      mkexpr( not_valid ) ),
3015                                src ),
3016                         binop( Iop_And64,
3017                                mkexpr( not_valid ),
3018                                binop( Iop_Or64,
3019                                       binop( Iop_And64,
3020                                              mkexpr( has_perm),
3021                                              binop( Iop_Shl64,
3022                                                     mkexpr( value ),
3023                                                     mkU8( 50 ) ) ),
3024                                       binop( Iop_And64,
3025                                              IRExpr_Get( OFFB_PPR, ty ),
3026                                              unop( Iop_Not64,
3027                                                    mkexpr( has_perm )
3028                                                    ) ) ) ) ) );
3029 
3030                  /* make sure we only set the valid bit field [52:50] */
3031                  stmt( IRStmt_Put( OFFB_PPR,
3032                                    binop( Iop_And64,
3033                                           mkexpr( new_src ),
3034                                           mkU64( 0x1C000000000000) ) ) );
3035       break;
3036       }
3037    default:
3038       vex_printf("putGST(ppc): reg = %u", reg);
3039       vpanic("putGST(ppc)");
3040    }
3041 }
3042 
3043 /* Write masked src to the given reg */
putGST_masked(PPC_GST reg,IRExpr * src,ULong mask)3044 static void putGST_masked ( PPC_GST reg, IRExpr* src, ULong mask )
3045 {
3046    IRType ty = mode64 ? Ity_I64 : Ity_I32;
3047    vassert( reg < PPC_GST_MAX );
3048    vassert( typeOfIRExpr( irsb->tyenv,src ) == Ity_I64 );
3049 
3050    switch (reg) {
3051    case PPC_GST_FPSCR: {
3052       /* Allow writes to either binary or decimal floating point
3053          Rounding Mode.
3054       */
3055       /* If any part of |mask| covers FPSCR.RN, update the bits of
3056          FPSCR.RN by copying in |src| for locations where the
3057          corresponding bit in |mask| is 1, and leaving it unchanged
3058          for corresponding |mask| zero bits. */
3059       if (mask & MASK_FPSCR_RN) {
3060          stmt(
3061             IRStmt_Put(
3062                OFFB_FPROUND,
3063                unop(
3064                   Iop_32to8,
3065                   binop(
3066                      Iop_Or32,
3067                      binop(
3068                         Iop_And32,
3069                         unop(Iop_64to32, src),
3070                         mkU32(MASK_FPSCR_RN & mask)
3071                      ),
3072                      binop(
3073                         Iop_And32,
3074                         unop(Iop_8Uto32, IRExpr_Get(OFFB_FPROUND,Ity_I8)),
3075                         mkU32(MASK_FPSCR_RN & ~mask)
3076                      )
3077                   )
3078                )
3079             )
3080          );
3081       }
3082       /* Similarly, update FPSCR.DRN if any bits of |mask|
3083          corresponding to FPSCR.DRN are set. */
3084       if (mask & MASK_FPSCR_DRN) {
3085          stmt(
3086             IRStmt_Put(
3087                OFFB_DFPROUND,
3088                unop(
3089                   Iop_32to8,
3090                   binop(
3091                      Iop_Or32,
3092                      binop(
3093                         Iop_And32,
3094                         unop(Iop_64HIto32, src),
3095                         mkU32((MASK_FPSCR_DRN & mask) >> 32)
3096                      ),
3097                      binop(
3098                         Iop_And32,
3099                         unop(Iop_8Uto32, IRExpr_Get(OFFB_DFPROUND,Ity_I8)),
3100                         mkU32((MASK_FPSCR_DRN & ~mask) >> 32)
3101                      )
3102                   )
3103                )
3104             )
3105          );
3106       }
3107 
3108       /* Give EmNote for attempted writes to:
3109          - Exception Controls
3110          - Non-IEEE Mode
3111       */
3112       if (mask & 0xFC) {  // Exception Control, Non-IEE mode
3113          VexEmNote ew = EmWarn_PPCexns;
3114 
3115          /* If any of the src::exception_control bits are actually set,
3116             side-exit to the next insn, reporting the warning,
3117             so that Valgrind's dispatcher sees the warning. */
3118          putGST( PPC_GST_EMWARN, mkU32(ew) );
3119          stmt(
3120             IRStmt_Exit(
3121                binop(Iop_CmpNE32, mkU32(ew), mkU32(EmNote_NONE)),
3122                Ijk_EmWarn,
3123                mkSzConst( ty, nextInsnAddr()), OFFB_CIA ));
3124       }
3125 
3126       /* Ignore all other writes */
3127       break;
3128    }
3129 
3130    default:
3131       vex_printf("putGST_masked(ppc): reg = %u", reg);
3132       vpanic("putGST_masked(ppc)");
3133    }
3134 }
3135 
3136 /* Write the least significant nibble of src to the specified
3137    REG[FLD] (as per IBM/hardware notation). */
putGST_field(PPC_GST reg,IRExpr * src,UInt fld)3138 static void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld )
3139 {
3140    UInt shft;
3141    ULong mask;
3142 
3143    vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 );
3144    vassert( fld < 16 );
3145    vassert( reg < PPC_GST_MAX );
3146 
3147    if (fld < 8)
3148       shft = 4*(7-fld);
3149    else
3150       shft = 4*(15-fld);
3151    mask = 0xF;
3152    mask = mask << shft;
3153 
3154    switch (reg) {
3155    case PPC_GST_CR:
3156       putCR0  (fld, binop(Iop_And8, mkU8(1   ), unop(Iop_32to8, src)));
3157       putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src)));
3158       break;
3159 
3160    default:
3161       {
3162          IRExpr * src64 = unop( Iop_32Uto64, src );
3163 
3164          if (shft == 0) {
3165             putGST_masked( reg, src64, mask );
3166          } else {
3167             putGST_masked( reg,
3168                            binop( Iop_Shl64, src64, mkU8( toUChar( shft ) ) ),
3169                            mask );
3170          }
3171       }
3172    }
3173 }
3174 
3175 /*------------------------------------------------------------*/
3176 /* Helpers for VSX instructions that do floating point
3177  * operations and need to determine if a src contains a
3178  * special FP value.
3179  *
3180  *------------------------------------------------------------*/
3181 
3182 #define NONZERO_FRAC_MASK 0x000fffffffffffffULL
3183 #define FP_FRAC_PART(x) binop( Iop_And64, \
3184                                mkexpr( x ), \
3185                                mkU64( NONZERO_FRAC_MASK ) )
3186 
3187 // Returns exponent part of a single precision floating point as I32
fp_exp_part_sp(IRTemp src)3188 static IRExpr * fp_exp_part_sp(IRTemp src)
3189 {
3190    return binop( Iop_And32,
3191                  binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ),
3192                  mkU32( 0xff ) );
3193 }
3194 
3195 // Returns exponent part of floating point as I32
fp_exp_part(IRTemp src,Bool sp)3196 static IRExpr * fp_exp_part(IRTemp src, Bool sp)
3197 {
3198    IRExpr * exp;
3199    if (sp)
3200       return fp_exp_part_sp(src);
3201 
3202    if (!mode64)
3203       exp = binop( Iop_And32, binop( Iop_Shr32, unop( Iop_64HIto32,
3204                                                       mkexpr( src ) ),
3205                                      mkU8( 20 ) ), mkU32( 0x7ff ) );
3206    else
3207       exp = unop( Iop_64to32,
3208                   binop( Iop_And64,
3209                          binop( Iop_Shr64, mkexpr( src ), mkU8( 52 ) ),
3210                          mkU64( 0x7ff ) ) );
3211    return exp;
3212 }
3213 
is_Inf_sp(IRTemp src)3214 static IRExpr * is_Inf_sp(IRTemp src)
3215 {
3216    IRTemp frac_part = newTemp(Ity_I32);
3217    IRExpr * Inf_exp;
3218 
3219    assign( frac_part, binop( Iop_And32, mkexpr(src), mkU32(0x007fffff)) );
3220    Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, True /*single precision*/ ), mkU32( 0xff ) );
3221    return mkAND1( Inf_exp, binop( Iop_CmpEQ32, mkexpr( frac_part ), mkU32( 0 ) ) );
3222 }
3223 
3224 
3225 // Infinity: exp = 7ff and fraction is zero; s = 0/1
is_Inf(IRTemp src,Bool sp)3226 static IRExpr * is_Inf(IRTemp src, Bool sp)
3227 {
3228    IRExpr * Inf_exp, * hi32, * low32;
3229    IRTemp frac_part;
3230 
3231    if (sp)
3232       return is_Inf_sp(src);
3233 
3234    frac_part = newTemp(Ity_I64);
3235    assign( frac_part, FP_FRAC_PART(src) );
3236    Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/  ), mkU32( 0x7ff ) );
3237    hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
3238    low32 = unop( Iop_64to32, mkexpr( frac_part ) );
3239    return mkAND1( Inf_exp, binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
3240                                   mkU32( 0 ) ) );
3241 }
3242 
is_Zero_sp(IRTemp src)3243 static IRExpr * is_Zero_sp(IRTemp src)
3244 {
3245    IRTemp sign_less_part = newTemp(Ity_I32);
3246    assign( sign_less_part, binop( Iop_And32, mkexpr( src ), mkU32( SIGN_MASK32 ) ) );
3247    return binop( Iop_CmpEQ32, mkexpr( sign_less_part ), mkU32( 0 ) );
3248 }
3249 
3250 // Zero: exp is zero and fraction is zero; s = 0/1
is_Zero(IRTemp src,Bool sp)3251 static IRExpr * is_Zero(IRTemp src, Bool sp)
3252 {
3253    IRExpr * hi32, * low32;
3254    IRTemp sign_less_part;
3255    if (sp)
3256       return is_Zero_sp(src);
3257 
3258    sign_less_part = newTemp(Ity_I64);
3259 
3260    assign( sign_less_part, binop( Iop_And64, mkexpr( src ), mkU64( SIGN_MASK ) ) );
3261    hi32 = unop( Iop_64HIto32, mkexpr( sign_less_part ) );
3262    low32 = unop( Iop_64to32, mkexpr( sign_less_part ) );
3263    return binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
3264                               mkU32( 0 ) );
3265 }
3266 
3267 /*  SNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '1'
3268  *  QNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '0'
3269  *  This function returns an IRExpr value of '1' for any type of NaN.
3270  */
is_NaN(IRTemp src)3271 static IRExpr * is_NaN(IRTemp src)
3272 {
3273    IRExpr * NaN_exp, * hi32, * low32;
3274    IRTemp frac_part = newTemp(Ity_I64);
3275 
3276    assign( frac_part, FP_FRAC_PART(src) );
3277    hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
3278    low32 = unop( Iop_64to32, mkexpr( frac_part ) );
3279    NaN_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ),
3280                     mkU32( 0x7ff ) );
3281 
3282    return mkAND1( NaN_exp, binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
3283                                                mkU32( 0 ) ) );
3284 }
3285 
3286 /* This function returns an IRExpr value of '1' for any type of NaN.
3287  * The passed 'src' argument is assumed to be Ity_I32.
3288  */
is_NaN_32(IRTemp src)3289 static IRExpr * is_NaN_32(IRTemp src)
3290 {
3291 #define NONZERO_FRAC_MASK32 0x007fffffULL
3292 #define FP_FRAC_PART32(x) binop( Iop_And32, \
3293                                  mkexpr( x ), \
3294                                  mkU32( NONZERO_FRAC_MASK32 ) )
3295 
3296    IRExpr * frac_part = FP_FRAC_PART32(src);
3297    IRExpr * exp_part = binop( Iop_And32,
3298                               binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ),
3299                               mkU32( 0x0ff ) );
3300    IRExpr * NaN_exp = binop( Iop_CmpEQ32, exp_part, mkU32( 0xff ) );
3301 
3302    return mkAND1( NaN_exp, binop( Iop_CmpNE32, frac_part, mkU32( 0 ) ) );
3303 }
3304 
3305 /* This function takes an Ity_I32 input argument interpreted
3306  * as a single-precision floating point value. If src is a
3307  * SNaN, it is changed to a QNaN and returned; otherwise,
3308  * the original value is returned.
3309  */
handle_SNaN_to_QNaN_32(IRExpr * src)3310 static IRExpr * handle_SNaN_to_QNaN_32(IRExpr * src)
3311 {
3312 #define SNAN_MASK32 0x00400000
3313    IRTemp tmp = newTemp(Ity_I32);
3314    IRTemp mask = newTemp(Ity_I32);
3315    IRTemp is_SNAN = newTemp(Ity_I1);
3316 
3317    vassert( typeOfIRExpr(irsb->tyenv, src ) == Ity_I32 );
3318    assign(tmp, src);
3319 
3320    /* check if input is SNaN, if it is convert to QNaN */
3321    assign( is_SNAN,
3322            mkAND1( is_NaN_32( tmp ),
3323                    binop( Iop_CmpEQ32,
3324                           binop( Iop_And32, mkexpr( tmp ),
3325                                  mkU32( SNAN_MASK32 ) ),
3326                           mkU32( 0 ) ) ) );
3327    /* create mask with QNaN bit set to make it a QNaN if tmp is SNaN */
3328    assign ( mask, binop( Iop_And32,
3329                          unop( Iop_1Sto32, mkexpr( is_SNAN ) ),
3330                          mkU32( SNAN_MASK32 ) ) );
3331    return binop( Iop_Or32, mkexpr( mask ), mkexpr( tmp) );
3332 }
3333 
3334 
3335 /* This helper function performs the negation part of operations of the form:
3336  *    "Negate Multiply-<op>"
3337  *  where "<op>" is either "Add" or "Sub".
3338  *
3339  * This function takes one argument -- the floating point intermediate result (converted to
3340  * Ity_I64 via Iop_ReinterpF64asI64) that was obtained from the "Multip-<op>" part of
3341  * the operation described above.
3342  */
getNegatedResult(IRTemp intermediateResult)3343 static IRTemp getNegatedResult(IRTemp intermediateResult)
3344 {
3345    ULong signbit_mask = 0x8000000000000000ULL;
3346    IRTemp signbit_32 = newTemp(Ity_I32);
3347    IRTemp resultantSignbit = newTemp(Ity_I1);
3348    IRTemp negatedResult = newTemp(Ity_I64);
3349    assign( signbit_32, binop( Iop_Shr32,
3350                           unop( Iop_64HIto32,
3351                                  binop( Iop_And64, mkexpr( intermediateResult ),
3352                                         mkU64( signbit_mask ) ) ),
3353                                  mkU8( 31 ) ) );
3354    /* We negate the signbit if and only if the intermediate result from the
3355     * multiply-<op> was NOT a NaN.  This is an XNOR predicate.
3356     */
3357    assign( resultantSignbit,
3358         unop( Iop_Not1,
3359               binop( Iop_CmpEQ32,
3360                      binop( Iop_Xor32,
3361                             mkexpr( signbit_32 ),
3362                             unop( Iop_1Uto32, is_NaN( intermediateResult ) ) ),
3363                      mkU32( 1 ) ) ) );
3364 
3365    assign( negatedResult,
3366         binop( Iop_Or64,
3367                binop( Iop_And64,
3368                       mkexpr( intermediateResult ),
3369                       mkU64( ~signbit_mask ) ),
3370                binop( Iop_32HLto64,
3371                       binop( Iop_Shl32,
3372                              unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
3373                              mkU8( 31 ) ),
3374                       mkU32( 0 ) ) ) );
3375 
3376    return negatedResult;
3377 }
3378 
3379 /* This helper function performs the negation part of operations of the form:
3380  *    "Negate Multiply-<op>"
3381  *  where "<op>" is either "Add" or "Sub".
3382  *
3383  * This function takes one argument -- the floating point intermediate result (converted to
3384  * Ity_I32 via Iop_ReinterpF32asI32) that was obtained from the "Multip-<op>" part of
3385  * the operation described above.
3386  */
getNegatedResult_32(IRTemp intermediateResult)3387 static IRTemp getNegatedResult_32(IRTemp intermediateResult)
3388 {
3389    UInt signbit_mask = 0x80000000;
3390    IRTemp signbit_32 = newTemp(Ity_I32);
3391    IRTemp resultantSignbit = newTemp(Ity_I1);
3392    IRTemp negatedResult = newTemp(Ity_I32);
3393    assign( signbit_32, binop( Iop_Shr32,
3394                                  binop( Iop_And32, mkexpr( intermediateResult ),
3395                                         mkU32( signbit_mask ) ),
3396                                  mkU8( 31 ) ) );
3397    /* We negate the signbit if and only if the intermediate result from the
3398     * multiply-<op> was NOT a NaN.  This is an XNOR predicate.
3399     */
3400    assign( resultantSignbit,
3401         unop( Iop_Not1,
3402               binop( Iop_CmpEQ32,
3403                      binop( Iop_Xor32,
3404                             mkexpr( signbit_32 ),
3405                             unop( Iop_1Uto32, is_NaN_32( intermediateResult ) ) ),
3406                      mkU32( 1 ) ) ) );
3407 
3408    assign( negatedResult,
3409            binop( Iop_Or32,
3410                   binop( Iop_And32,
3411                          mkexpr( intermediateResult ),
3412                          mkU32( ~signbit_mask ) ),
3413                   binop( Iop_Shl32,
3414                          unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
3415                          mkU8( 31 ) ) ) );
3416 
3417    return negatedResult;
3418 }
3419 
3420 /*------------------------------------------------------------*/
3421 /* Transactional memory helpers
3422  *
3423  *------------------------------------------------------------*/
3424 
generate_TMreason(UInt failure_code,UInt persistant,UInt nest_overflow,UInt tm_exact)3425 static ULong generate_TMreason( UInt failure_code,
3426                                              UInt persistant,
3427                                              UInt nest_overflow,
3428                                              UInt tm_exact )
3429 {
3430    ULong tm_err_code =
3431      ( (ULong) 0) << (63-6)   /* Failure code */
3432      | ( (ULong) persistant) << (63-7)     /* Failure persistant */
3433      | ( (ULong) 0) << (63-8)   /* Disallowed */
3434      | ( (ULong) nest_overflow) << (63-9)   /* Nesting Overflow */
3435      | ( (ULong) 0) << (63-10)  /* Footprint Overflow */
3436      | ( (ULong) 0) << (63-11)  /* Self-Induced Conflict */
3437      | ( (ULong) 0) << (63-12)  /* Non-Transactional Conflict */
3438      | ( (ULong) 0) << (63-13)  /* Transactional Conflict */
3439      | ( (ULong) 0) << (63-14)  /* Translation Invalidation Conflict */
3440      | ( (ULong) 0) << (63-15)  /* Implementation-specific */
3441      | ( (ULong) 0) << (63-16)  /* Instruction Fetch Conflict */
3442      | ( (ULong) 0) << (63-30)  /* Reserved */
3443      | ( (ULong) 0) << (63-31)  /* Abort */
3444      | ( (ULong) 0) << (63-32)  /* Suspend */
3445      | ( (ULong) 0) << (63-33)  /* Reserved */
3446      | ( (ULong) 0) << (63-35)  /* Privilege */
3447      | ( (ULong) 0) << (63-36)  /* Failure Summary */
3448      | ( (ULong) tm_exact) << (63-37)  /* TFIAR Exact */
3449      | ( (ULong) 0) << (63-38)  /* ROT */
3450      | ( (ULong) 0) << (63-51)  /* Reserved */
3451      | ( (ULong) 0) << (63-63);  /* Transaction Level */
3452 
3453      return tm_err_code;
3454 }
3455 
storeTMfailure(Addr64 err_address,ULong tm_reason,Addr64 handler_address)3456 static void storeTMfailure( Addr64 err_address, ULong tm_reason,
3457                             Addr64 handler_address )
3458 {
3459    putGST( PPC_GST_TFIAR,   mkU64( err_address ) );
3460    putGST( PPC_GST_TEXASR,  mkU64( tm_reason ) );
3461    putGST( PPC_GST_TEXASRU, mkU32( 0 ) );
3462    putGST( PPC_GST_TFHAR,   mkU64( handler_address ) );
3463 }
3464 
3465 /*------------------------------------------------------------*/
3466 /*--- Integer Instruction Translation                     --- */
3467 /*------------------------------------------------------------*/
3468 
3469 /*
3470   Integer Arithmetic Instructions
3471 */
dis_int_arith(UInt theInstr)3472 static Bool dis_int_arith ( UInt theInstr )
3473 {
3474    /* D-Form, XO-Form */
3475    UChar opc1    = ifieldOPC(theInstr);
3476    UChar rD_addr = ifieldRegDS(theInstr);
3477    UChar rA_addr = ifieldRegA(theInstr);
3478    UInt  uimm16  = ifieldUIMM16(theInstr);
3479    UChar rB_addr = ifieldRegB(theInstr);
3480    UChar flag_OE = ifieldBIT10(theInstr);
3481    UInt  opc2    = ifieldOPClo9(theInstr);
3482    UChar flag_rC = ifieldBIT0(theInstr);
3483 
3484    Long   simm16 = extend_s_16to64(uimm16);
3485    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
3486    IRTemp rA     = newTemp(ty);
3487    IRTemp rB     = newTemp(ty);
3488    IRTemp rD     = newTemp(ty);
3489 
3490    Bool do_rc = False;
3491 
3492    assign( rA, getIReg(rA_addr) );
3493    assign( rB, getIReg(rB_addr) );         // XO-Form: rD, rA, rB
3494 
3495    switch (opc1) {
3496    /* D-Form */
3497    case 0x0C: // addic  (Add Immediate Carrying, PPC32 p351
3498       DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
3499       assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
3500                          mkSzExtendS16(ty, uimm16) ) );
3501       set_XER_CA( ty, PPCG_FLAG_OP_ADD,
3502                   mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
3503                   mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
3504       break;
3505 
3506    case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352)
3507       DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
3508       assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
3509                          mkSzExtendS16(ty, uimm16) ) );
3510       set_XER_CA( ty, PPCG_FLAG_OP_ADD,
3511                   mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
3512                   mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
3513       do_rc = True;  // Always record to CR
3514       flag_rC = 1;
3515       break;
3516 
3517    case 0x0E: // addi   (Add Immediate, PPC32 p350)
3518       // li rD,val   == addi rD,0,val
3519       // la disp(rA) == addi rD,rA,disp
3520       if ( rA_addr == 0 ) {
3521          DIP("li r%u,%d\n", rD_addr, (Int)simm16);
3522          assign( rD, mkSzExtendS16(ty, uimm16) );
3523       } else {
3524          DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
3525          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
3526                             mkSzExtendS16(ty, uimm16) ) );
3527       }
3528       break;
3529 
3530    case 0x0F: // addis  (Add Immediate Shifted, PPC32 p353)
3531       // lis rD,val == addis rD,0,val
3532       if ( rA_addr == 0 ) {
3533          DIP("lis r%u,%d\n", rD_addr, (Int)simm16);
3534          assign( rD, mkSzExtendS32(ty, uimm16 << 16) );
3535       } else {
3536          DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (UInt)simm16);
3537          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
3538                             mkSzExtendS32(ty, uimm16 << 16) ) );
3539       }
3540       break;
3541 
3542    case 0x07: // mulli    (Multiply Low Immediate, PPC32 p490)
3543       DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
3544       if (mode64)
3545          assign( rD, unop(Iop_128to64,
3546                           binop(Iop_MullS64, mkexpr(rA),
3547                                 mkSzExtendS16(ty, uimm16))) );
3548       else
3549          assign( rD, unop(Iop_64to32,
3550                           binop(Iop_MullS32, mkexpr(rA),
3551                                 mkSzExtendS16(ty, uimm16))) );
3552       break;
3553 
3554    case 0x08: // subfic   (Subtract from Immediate Carrying, PPC32 p540)
3555       DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
3556       // rD = simm16 - rA
3557       assign( rD, binop( mkSzOp(ty, Iop_Sub8),
3558                          mkSzExtendS16(ty, uimm16),
3559                          mkexpr(rA)) );
3560       set_XER_CA( ty, PPCG_FLAG_OP_SUBFI,
3561                   mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
3562                   mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
3563       break;
3564 
3565    /* XO-Form */
3566    case 0x1F:
3567       do_rc = True;    // All below record to CR
3568 
3569       switch (opc2) {
3570       case 0x10A: // add  (Add, PPC32 p347)
3571          DIP("add%s%s r%u,r%u,r%u\n",
3572              flag_OE ? "o" : "", flag_rC ? ".":"",
3573              rD_addr, rA_addr, rB_addr);
3574          assign( rD, binop( mkSzOp(ty, Iop_Add8),
3575                             mkexpr(rA), mkexpr(rB) ) );
3576          if (flag_OE) {
3577             set_XER_OV( ty, PPCG_FLAG_OP_ADD,
3578                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3579          }
3580          break;
3581 
3582       case 0x00A: // addc      (Add Carrying, PPC32 p348)
3583          DIP("addc%s%s r%u,r%u,r%u\n",
3584              flag_OE ? "o" : "", flag_rC ? ".":"",
3585              rD_addr, rA_addr, rB_addr);
3586          assign( rD, binop( mkSzOp(ty, Iop_Add8),
3587                             mkexpr(rA), mkexpr(rB)) );
3588          set_XER_CA( ty, PPCG_FLAG_OP_ADD,
3589                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
3590                      mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
3591          if (flag_OE) {
3592             set_XER_OV( ty, PPCG_FLAG_OP_ADD,
3593                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3594          }
3595          break;
3596 
3597       case 0x08A: { // adde      (Add Extended, PPC32 p349)
3598          IRTemp old_xer_ca = newTemp(ty);
3599          DIP("adde%s%s r%u,r%u,r%u\n",
3600              flag_OE ? "o" : "", flag_rC ? ".":"",
3601              rD_addr, rA_addr, rB_addr);
3602          // rD = rA + rB + XER[CA]
3603          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3604          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
3605                             binop( mkSzOp(ty, Iop_Add8),
3606                                    mkexpr(rB), mkexpr(old_xer_ca))) );
3607          set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
3608                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
3609                      mkexpr(old_xer_ca) );
3610          if (flag_OE) {
3611             set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
3612                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3613          }
3614          break;
3615       }
3616 
3617       case 0x0EA: { // addme     (Add to Minus One Extended, PPC32 p354)
3618          IRTemp old_xer_ca = newTemp(ty);
3619          IRExpr *min_one;
3620          if (rB_addr != 0) {
3621             vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n");
3622             return False;
3623          }
3624          DIP("addme%s%s r%u,r%u,r%u\n",
3625              flag_OE ? "o" : "", flag_rC ? ".":"",
3626              rD_addr, rA_addr, rB_addr);
3627          // rD = rA + (-1) + XER[CA]
3628          // => Just another form of adde
3629          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3630          min_one = mkSzImm(ty, (Long)-1);
3631          assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
3632                             binop( mkSzOp(ty, Iop_Add8),
3633                                    min_one, mkexpr(old_xer_ca)) ));
3634          set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
3635                      mkexpr(rD), mkexpr(rA), min_one,
3636                      mkexpr(old_xer_ca) );
3637          if (flag_OE) {
3638             set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
3639                         mkexpr(rD), mkexpr(rA), min_one );
3640          }
3641          break;
3642       }
3643 
3644       case 0x0CA: { // addze      (Add to Zero Extended, PPC32 p355)
3645          IRTemp old_xer_ca = newTemp(ty);
3646          if (rB_addr != 0) {
3647             vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n");
3648             return False;
3649          }
3650          DIP("addze%s%s r%u,r%u,r%u\n",
3651              flag_OE ? "o" : "", flag_rC ? ".":"",
3652              rD_addr, rA_addr, rB_addr);
3653          // rD = rA + (0) + XER[CA]
3654          // => Just another form of adde
3655          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3656          assign( rD, binop( mkSzOp(ty, Iop_Add8),
3657                             mkexpr(rA), mkexpr(old_xer_ca)) );
3658          set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
3659                      mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
3660                      mkexpr(old_xer_ca) );
3661          if (flag_OE) {
3662             set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
3663                         mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
3664          }
3665          break;
3666       }
3667 
3668       case 0x1EB: // divw       (Divide Word, PPC32 p388)
3669          DIP("divw%s%s r%u,r%u,r%u\n",
3670              flag_OE ? "o" : "", flag_rC ? ".":"",
3671              rD_addr, rA_addr, rB_addr);
3672          if (mode64) {
3673             /* Note:
3674                XER settings are mode independent, and reflect the
3675                overflow of the low-order 32bit result
3676                CR0[LT|GT|EQ] are undefined if flag_rC && mode64
3677             */
3678             /* rD[hi32] are undefined: setting them to sign of lo32
3679                 - makes set_CR0 happy */
3680             IRExpr* dividend = mk64lo32Sto64( mkexpr(rA) );
3681             IRExpr* divisor  = mk64lo32Sto64( mkexpr(rB) );
3682             assign( rD, mk64lo32Uto64( binop(Iop_DivS64, dividend,
3683                                                          divisor) ) );
3684             if (flag_OE) {
3685                set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
3686                            mkexpr(rD), dividend, divisor );
3687             }
3688          } else {
3689             assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) );
3690             if (flag_OE) {
3691                set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
3692                            mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3693             }
3694          }
3695          /* Note:
3696             if (0x8000_0000 / -1) or (x / 0)
3697             => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
3698             => But _no_ exception raised. */
3699          break;
3700 
3701       case 0x1CB: // divwu      (Divide Word Unsigned, PPC32 p389)
3702          DIP("divwu%s%s r%u,r%u,r%u\n",
3703              flag_OE ? "o" : "", flag_rC ? ".":"",
3704              rD_addr, rA_addr, rB_addr);
3705          if (mode64) {
3706             /* Note:
3707                XER settings are mode independent, and reflect the
3708                overflow of the low-order 32bit result
3709                CR0[LT|GT|EQ] are undefined if flag_rC && mode64
3710             */
3711             IRExpr* dividend = mk64lo32Uto64( mkexpr(rA) );
3712             IRExpr* divisor  = mk64lo32Uto64( mkexpr(rB) );
3713             assign( rD, mk64lo32Uto64( binop(Iop_DivU64, dividend,
3714                                                          divisor) ) );
3715             if (flag_OE) {
3716                set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
3717                            mkexpr(rD), dividend, divisor );
3718             }
3719          } else {
3720             assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) );
3721             if (flag_OE) {
3722                set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
3723                            mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3724             }
3725          }
3726          /* Note: ditto comment divw, for (x / 0) */
3727          break;
3728 
3729       case 0x04B: // mulhw      (Multiply High Word, PPC32 p488)
3730          if (flag_OE != 0) {
3731             vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n");
3732             return False;
3733          }
3734          DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3735              rD_addr, rA_addr, rB_addr);
3736          if (mode64) {
3737             /* rD[hi32] are undefined: setting them to sign of lo32
3738                 - makes set_CR0 happy */
3739             assign( rD, binop(Iop_Sar64,
3740                            binop(Iop_Mul64,
3741                                  mk64lo32Sto64( mkexpr(rA) ),
3742                                  mk64lo32Sto64( mkexpr(rB) )),
3743                               mkU8(32)) );
3744          } else {
3745             assign( rD, unop(Iop_64HIto32,
3746                              binop(Iop_MullS32,
3747                                    mkexpr(rA), mkexpr(rB))) );
3748          }
3749          break;
3750 
3751       case 0x00B: // mulhwu    (Multiply High Word Unsigned, PPC32 p489)
3752          if (flag_OE != 0) {
3753             vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n");
3754             return False;
3755          }
3756          DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3757              rD_addr, rA_addr, rB_addr);
3758          if (mode64) {
3759             /* rD[hi32] are undefined: setting them to sign of lo32
3760                 - makes set_CR0 happy */
3761             assign( rD, binop(Iop_Sar64,
3762                            binop(Iop_Mul64,
3763                                  mk64lo32Uto64( mkexpr(rA) ),
3764                                  mk64lo32Uto64( mkexpr(rB) ) ),
3765                               mkU8(32)) );
3766          } else {
3767             assign( rD, unop(Iop_64HIto32,
3768                              binop(Iop_MullU32,
3769                                    mkexpr(rA), mkexpr(rB))) );
3770          }
3771          break;
3772 
3773       case 0x0EB: // mullw      (Multiply Low Word, PPC32 p491)
3774          DIP("mullw%s%s r%u,r%u,r%u\n",
3775              flag_OE ? "o" : "", flag_rC ? ".":"",
3776              rD_addr, rA_addr, rB_addr);
3777          if (mode64) {
3778             /* rD[hi32] are undefined: setting them to sign of lo32
3779                 - set_XER_OV() and set_CR0() depend on this */
3780             IRExpr *a = unop(Iop_64to32, mkexpr(rA) );
3781             IRExpr *b = unop(Iop_64to32, mkexpr(rB) );
3782             assign( rD, binop(Iop_MullS32, a, b) );
3783             if (flag_OE) {
3784                set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
3785                            mkexpr(rD),
3786                            unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) );
3787             }
3788          } else {
3789             assign( rD, unop(Iop_64to32,
3790                              binop(Iop_MullU32,
3791                                    mkexpr(rA), mkexpr(rB))) );
3792             if (flag_OE) {
3793                set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
3794                            mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3795             }
3796          }
3797          break;
3798 
3799       case 0x068: // neg        (Negate, PPC32 p493)
3800          if (rB_addr != 0) {
3801             vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n");
3802             return False;
3803          }
3804          DIP("neg%s%s r%u,r%u\n",
3805              flag_OE ? "o" : "", flag_rC ? ".":"",
3806              rD_addr, rA_addr);
3807          // rD = (~rA) + 1
3808          assign( rD, binop( mkSzOp(ty, Iop_Add8),
3809                             unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ),
3810                             mkSzImm(ty, 1)) );
3811          if (flag_OE) {
3812             set_XER_OV( ty, PPCG_FLAG_OP_NEG,
3813                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3814          }
3815          break;
3816 
3817       case 0x028: // subf       (Subtract From, PPC32 p537)
3818          DIP("subf%s%s r%u,r%u,r%u\n",
3819              flag_OE ? "o" : "", flag_rC ? ".":"",
3820              rD_addr, rA_addr, rB_addr);
3821          // rD = rB - rA
3822          assign( rD, binop( mkSzOp(ty, Iop_Sub8),
3823                             mkexpr(rB), mkexpr(rA)) );
3824          if (flag_OE) {
3825             set_XER_OV( ty, PPCG_FLAG_OP_SUBF,
3826                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3827          }
3828          break;
3829 
3830       case 0x008: // subfc      (Subtract from Carrying, PPC32 p538)
3831          DIP("subfc%s%s r%u,r%u,r%u\n",
3832              flag_OE ? "o" : "", flag_rC ? ".":"",
3833              rD_addr, rA_addr, rB_addr);
3834          // rD = rB - rA
3835          assign( rD, binop( mkSzOp(ty, Iop_Sub8),
3836                             mkexpr(rB), mkexpr(rA)) );
3837          set_XER_CA( ty, PPCG_FLAG_OP_SUBFC,
3838                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
3839                      mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
3840          if (flag_OE) {
3841             set_XER_OV( ty, PPCG_FLAG_OP_SUBFC,
3842                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3843          }
3844          break;
3845 
3846       case 0x088: {// subfe      (Subtract from Extended, PPC32 p539)
3847          IRTemp old_xer_ca = newTemp(ty);
3848          DIP("subfe%s%s r%u,r%u,r%u\n",
3849              flag_OE ? "o" : "", flag_rC ? ".":"",
3850              rD_addr, rA_addr, rB_addr);
3851          // rD = (log not)rA + rB + XER[CA]
3852          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3853          assign( rD, binop( mkSzOp(ty, Iop_Add8),
3854                             unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
3855                             binop( mkSzOp(ty, Iop_Add8),
3856                                    mkexpr(rB), mkexpr(old_xer_ca))) );
3857          set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
3858                      mkexpr(rD), mkexpr(rA), mkexpr(rB),
3859                      mkexpr(old_xer_ca) );
3860          if (flag_OE) {
3861             set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
3862                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3863          }
3864          break;
3865       }
3866 
3867       case 0x0E8: { // subfme    (Subtract from -1 Extended, PPC32 p541)
3868          IRTemp old_xer_ca = newTemp(ty);
3869          IRExpr *min_one;
3870          if (rB_addr != 0) {
3871             vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n");
3872             return False;
3873          }
3874          DIP("subfme%s%s r%u,r%u\n",
3875              flag_OE ? "o" : "", flag_rC ? ".":"",
3876              rD_addr, rA_addr);
3877          // rD = (log not)rA + (-1) + XER[CA]
3878          // => Just another form of subfe
3879          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3880          min_one = mkSzImm(ty, (Long)-1);
3881          assign( rD, binop( mkSzOp(ty, Iop_Add8),
3882                             unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
3883                             binop( mkSzOp(ty, Iop_Add8),
3884                                    min_one, mkexpr(old_xer_ca))) );
3885          set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
3886                      mkexpr(rD), mkexpr(rA), min_one,
3887                      mkexpr(old_xer_ca) );
3888          if (flag_OE) {
3889             set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
3890                         mkexpr(rD), mkexpr(rA), min_one );
3891          }
3892          break;
3893       }
3894 
3895       case 0x0C8: { // subfze  (Subtract from Zero Extended, PPC32 p542)
3896          IRTemp old_xer_ca = newTemp(ty);
3897          if (rB_addr != 0) {
3898             vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n");
3899             return False;
3900          }
3901          DIP("subfze%s%s r%u,r%u\n",
3902              flag_OE ? "o" : "", flag_rC ? ".":"",
3903              rD_addr, rA_addr);
3904          // rD = (log not)rA + (0) + XER[CA]
3905          // => Just another form of subfe
3906          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3907          assign( rD, binop( mkSzOp(ty, Iop_Add8),
3908                            unop( mkSzOp(ty, Iop_Not8),
3909                                  mkexpr(rA)), mkexpr(old_xer_ca)) );
3910          set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
3911                      mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
3912                      mkexpr(old_xer_ca) );
3913          if (flag_OE) {
3914             set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
3915                         mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
3916          }
3917          break;
3918       }
3919 
3920 
3921       /* 64bit Arithmetic */
3922       case 0x49:  // mulhd (Multiply High DWord, PPC64 p539)
3923          if (flag_OE != 0) {
3924             vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n");
3925             return False;
3926          }
3927          DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3928              rD_addr, rA_addr, rB_addr);
3929          assign( rD, unop(Iop_128HIto64,
3930                           binop(Iop_MullS64,
3931                                 mkexpr(rA), mkexpr(rB))) );
3932 
3933          break;
3934 
3935       case 0x9:   // mulhdu  (Multiply High DWord Unsigned, PPC64 p540)
3936          if (flag_OE != 0) {
3937             vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n");
3938             return False;
3939          }
3940          DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3941              rD_addr, rA_addr, rB_addr);
3942          assign( rD, unop(Iop_128HIto64,
3943                           binop(Iop_MullU64,
3944                                 mkexpr(rA), mkexpr(rB))) );
3945          break;
3946 
3947       case 0xE9:  // mulld (Multiply Low DWord, PPC64 p543)
3948          DIP("mulld%s%s r%u,r%u,r%u\n",
3949              flag_OE ? "o" : "", flag_rC ? ".":"",
3950              rD_addr, rA_addr, rB_addr);
3951          assign( rD, binop(Iop_Mul64, mkexpr(rA), mkexpr(rB)) );
3952          if (flag_OE) {
3953             set_XER_OV( ty, PPCG_FLAG_OP_MULLD,
3954                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3955          }
3956          break;
3957 
3958       case 0x1E9: // divd (Divide DWord, PPC64 p419)
3959          DIP("divd%s%s r%u,r%u,r%u\n",
3960              flag_OE ? "o" : "", flag_rC ? ".":"",
3961              rD_addr, rA_addr, rB_addr);
3962          assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) );
3963          if (flag_OE) {
3964             set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
3965                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3966          }
3967          break;
3968          /* Note:
3969             if (0x8000_0000_0000_0000 / -1) or (x / 0)
3970             => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
3971             => But _no_ exception raised. */
3972 
3973       case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420)
3974          DIP("divdu%s%s r%u,r%u,r%u\n",
3975              flag_OE ? "o" : "", flag_rC ? ".":"",
3976              rD_addr, rA_addr, rB_addr);
3977          assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) );
3978          if (flag_OE) {
3979             set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
3980                         mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3981          }
3982          break;
3983          /* Note: ditto comment divd, for (x / 0) */
3984 
3985       case 0x18B: // divweu (Divide Word Extended Unsigned)
3986       {
3987         /*
3988          *  If (RA) >= (RB), or if an attempt is made to perform the division
3989          *         <anything> / 0
3990          * then the contents of register RD are undefined as are (if Rc=1) the contents of
3991          * the LT, GT, and EQ bits of CR Field 0. In these cases, if OE=1 then OV is set
3992          * to 1.
3993          */
3994          IRTemp res = newTemp(Ity_I32);
3995          IRExpr * dividend, * divisor;
3996          DIP("divweu%s%s r%u,r%u,r%u\n",
3997              flag_OE ? "o" : "", flag_rC ? ".":"",
3998                                          rD_addr, rA_addr, rB_addr);
3999          if (mode64) {
4000             dividend = unop( Iop_64to32, mkexpr( rA ) );
4001             divisor = unop( Iop_64to32, mkexpr( rB ) );
4002             assign( res, binop( Iop_DivU32E, dividend, divisor ) );
4003             assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
4004          } else {
4005             dividend = mkexpr( rA );
4006             divisor =  mkexpr( rB );
4007             assign( res, binop( Iop_DivU32E, dividend, divisor ) );
4008             assign( rD, mkexpr( res) );
4009          }
4010 
4011          if (flag_OE) {
4012             set_XER_OV_32( PPCG_FLAG_OP_DIVWEU,
4013                            mkexpr(res), dividend, divisor );
4014          }
4015          break;
4016       }
4017 
4018       case 0x1AB: // divwe (Divide Word Extended)
4019       {
4020          /*
4021           * If the quotient cannot be represented in 32 bits, or if an
4022           * attempt is made to perform the division
4023           *      <anything> / 0
4024           * then the contents of register RD are undefined as are (if
4025           * Rc=1) the contents of the LT, GT, and EQ bits of CR
4026           * Field 0. In these cases, if OE=1 then OV is set to 1.
4027           */
4028 
4029          IRTemp res = newTemp(Ity_I32);
4030          IRExpr * dividend, * divisor;
4031          DIP("divwe%s%s r%u,r%u,r%u\n",
4032              flag_OE ? "o" : "", flag_rC ? ".":"",
4033                                          rD_addr, rA_addr, rB_addr);
4034          if (mode64) {
4035             dividend = unop( Iop_64to32, mkexpr( rA ) );
4036             divisor = unop( Iop_64to32, mkexpr( rB ) );
4037             assign( res, binop( Iop_DivS32E, dividend, divisor ) );
4038             assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
4039          } else {
4040             dividend = mkexpr( rA );
4041             divisor =  mkexpr( rB );
4042             assign( res, binop( Iop_DivS32E, dividend, divisor ) );
4043             assign( rD, mkexpr( res) );
4044          }
4045 
4046          if (flag_OE) {
4047             set_XER_OV_32( PPCG_FLAG_OP_DIVWE,
4048                            mkexpr(res), dividend, divisor );
4049          }
4050          break;
4051       }
4052 
4053 
4054       case 0x1A9: // divde (Divide Doubleword Extended)
4055         /*
4056          * If the quotient cannot be represented in 64 bits, or if an
4057          * attempt is made to perform the division
4058          *      <anything> / 0
4059          * then the contents of register RD are undefined as are (if
4060          * Rc=1) the contents of the LT, GT, and EQ bits of CR
4061          * Field 0. In these cases, if OE=1 then OV is set to 1.
4062          */
4063          DIP("divde%s%s r%u,r%u,r%u\n",
4064              flag_OE ? "o" : "", flag_rC ? ".":"",
4065              rD_addr, rA_addr, rB_addr);
4066          assign( rD, binop(Iop_DivS64E, mkexpr(rA), mkexpr(rB)) );
4067          if (flag_OE) {
4068             set_XER_OV_64( PPCG_FLAG_OP_DIVDE, mkexpr( rD ),
4069                            mkexpr( rA ), mkexpr( rB ) );
4070          }
4071          break;
4072 
4073       case 0x189: //  divdeuo (Divide Doubleword Extended Unsigned)
4074         // Same CR and OV rules as given for divweu above
4075         DIP("divdeu%s%s r%u,r%u,r%u\n",
4076             flag_OE ? "o" : "", flag_rC ? ".":"",
4077             rD_addr, rA_addr, rB_addr);
4078         assign( rD, binop(Iop_DivU64E, mkexpr(rA), mkexpr(rB)) );
4079         if (flag_OE) {
4080            set_XER_OV_64( PPCG_FLAG_OP_DIVDEU, mkexpr( rD ),
4081                           mkexpr( rA ), mkexpr( rB ) );
4082         }
4083         break;
4084 
4085       default:
4086          vex_printf("dis_int_arith(ppc)(opc2)\n");
4087          return False;
4088       }
4089       break;
4090 
4091    default:
4092       vex_printf("dis_int_arith(ppc)(opc1)\n");
4093       return False;
4094    }
4095 
4096    putIReg( rD_addr, mkexpr(rD) );
4097 
4098    if (do_rc && flag_rC) {
4099       set_CR0( mkexpr(rD) );
4100    }
4101    return True;
4102 }
4103 
4104 
4105 
4106 /*
4107   Integer Compare Instructions
4108 */
dis_int_cmp(UInt theInstr)4109 static Bool dis_int_cmp ( UInt theInstr )
4110 {
4111    /* D-Form, X-Form */
4112    UChar opc1    = ifieldOPC(theInstr);
4113    UChar crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
4114    UChar b22     = toUChar( IFIELD( theInstr, 22, 1 ) );
4115    UChar flag_L  = toUChar( IFIELD( theInstr, 21, 1 ) );
4116    UChar rA_addr = ifieldRegA(theInstr);
4117    UInt  uimm16  = ifieldUIMM16(theInstr);
4118    UChar rB_addr = ifieldRegB(theInstr);
4119    UInt  opc2    = ifieldOPClo10(theInstr);
4120    UChar b0      = ifieldBIT0(theInstr);
4121 
4122    IRType ty = mode64 ? Ity_I64 : Ity_I32;
4123    IRExpr *a = getIReg(rA_addr);
4124    IRExpr *b;
4125 
4126    if (!mode64 && flag_L==1) {  // L==1 invalid for 32 bit.
4127       vex_printf("dis_int_cmp(ppc)(flag_L)\n");
4128       return False;
4129    }
4130 
4131    if (b22 != 0) {
4132       vex_printf("dis_int_cmp(ppc)(b22)\n");
4133       return False;
4134    }
4135 
4136    switch (opc1) {
4137    case 0x0B: // cmpi (Compare Immediate, PPC32 p368)
4138       DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr,
4139           (Int)extend_s_16to32(uimm16));
4140       b = mkSzExtendS16( ty, uimm16 );
4141       if (flag_L == 1) {
4142          putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
4143       } else {
4144          a = mkNarrowTo32( ty, a );
4145          b = mkNarrowTo32( ty, b );
4146          putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b)));
4147       }
4148       putCR0( crfD, getXER_SO() );
4149       break;
4150 
4151    case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370)
4152       DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16);
4153       b = mkSzImm( ty, uimm16 );
4154       if (flag_L == 1) {
4155          putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
4156       } else {
4157          a = mkNarrowTo32( ty, a );
4158          b = mkNarrowTo32( ty, b );
4159          putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
4160       }
4161       putCR0( crfD, getXER_SO() );
4162       break;
4163 
4164    /* X Form */
4165    case 0x1F:
4166       if (b0 != 0) {
4167          vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n");
4168          return False;
4169       }
4170       b = getIReg(rB_addr);
4171 
4172       switch (opc2) {
4173       case 0x000: // cmp (Compare, PPC32 p367)
4174          DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
4175          /* Comparing a reg with itself produces a result which
4176             doesn't depend on the contents of the reg.  Therefore
4177             remove the false dependency, which has been known to cause
4178             memcheck to produce false errors. */
4179          if (rA_addr == rB_addr)
4180             a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
4181                     ? mkU64(0)  : mkU32(0);
4182          if (flag_L == 1) {
4183             putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
4184          } else {
4185             a = mkNarrowTo32( ty, a );
4186             b = mkNarrowTo32( ty, b );
4187             putCR321(crfD, unop(Iop_32to8,binop(Iop_CmpORD32S, a, b)));
4188          }
4189          putCR0( crfD, getXER_SO() );
4190          break;
4191 
4192       case 0x020: // cmpl (Compare Logical, PPC32 p369)
4193          DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
4194          /* Comparing a reg with itself produces a result which
4195             doesn't depend on the contents of the reg.  Therefore
4196             remove the false dependency, which has been known to cause
4197             memcheck to produce false errors. */
4198          if (rA_addr == rB_addr)
4199             a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
4200                     ? mkU64(0)  : mkU32(0);
4201          if (flag_L == 1) {
4202             putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
4203          } else {
4204             a = mkNarrowTo32( ty, a );
4205             b = mkNarrowTo32( ty, b );
4206             putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
4207          }
4208          putCR0( crfD, getXER_SO() );
4209          break;
4210 
4211       default:
4212          vex_printf("dis_int_cmp(ppc)(opc2)\n");
4213          return False;
4214       }
4215       break;
4216 
4217    default:
4218       vex_printf("dis_int_cmp(ppc)(opc1)\n");
4219       return False;
4220    }
4221 
4222    return True;
4223 }
4224 
4225 
4226 /*
4227   Integer Logical Instructions
4228 */
dis_int_logic(UInt theInstr)4229 static Bool dis_int_logic ( UInt theInstr )
4230 {
4231    /* D-Form, X-Form */
4232    UChar opc1    = ifieldOPC(theInstr);
4233    UChar rS_addr = ifieldRegDS(theInstr);
4234    UChar rA_addr = ifieldRegA(theInstr);
4235    UInt  uimm16  = ifieldUIMM16(theInstr);
4236    UChar rB_addr = ifieldRegB(theInstr);
4237    UInt  opc2    = ifieldOPClo10(theInstr);
4238    UChar flag_rC = ifieldBIT0(theInstr);
4239 
4240    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
4241    IRTemp rS     = newTemp(ty);
4242    IRTemp rA     = newTemp(ty);
4243    IRTemp rB     = newTemp(ty);
4244    IRExpr* irx;
4245    Bool do_rc    = False;
4246 
4247    assign( rS, getIReg(rS_addr) );
4248    assign( rB, getIReg(rB_addr) );
4249 
4250    switch (opc1) {
4251    case 0x1C: // andi. (AND Immediate, PPC32 p358)
4252       DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
4253       assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
4254                          mkSzImm(ty, uimm16)) );
4255       do_rc = True;  // Always record to CR
4256       flag_rC = 1;
4257       break;
4258 
4259    case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359)
4260       DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
4261       assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
4262                          mkSzImm(ty, uimm16 << 16)) );
4263       do_rc = True;  // Always record to CR
4264       flag_rC = 1;
4265       break;
4266 
4267    case 0x18: // ori (OR Immediate, PPC32 p497)
4268       DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
4269       assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
4270                          mkSzImm(ty, uimm16)) );
4271       break;
4272 
4273    case 0x19: // oris (OR Immediate Shifted, PPC32 p498)
4274       DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
4275       assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
4276                          mkSzImm(ty, uimm16 << 16)) );
4277       break;
4278 
4279    case 0x1A: // xori (XOR Immediate, PPC32 p550)
4280       DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
4281       assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
4282                          mkSzImm(ty, uimm16)) );
4283       break;
4284 
4285    case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551)
4286       DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
4287       assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
4288                          mkSzImm(ty, uimm16 << 16)) );
4289       break;
4290 
4291    /* X Form */
4292    case 0x1F:
4293       do_rc = True; // All below record to CR, except for where we return at case end.
4294 
4295       switch (opc2) {
4296       case 0x01C: // and (AND, PPC32 p356)
4297          DIP("and%s r%u,r%u,r%u\n",
4298              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4299          assign(rA, binop( mkSzOp(ty, Iop_And8),
4300                            mkexpr(rS), mkexpr(rB)));
4301          break;
4302 
4303       case 0x03C: // andc (AND with Complement, PPC32 p357)
4304          DIP("andc%s r%u,r%u,r%u\n",
4305              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4306          assign(rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
4307                            unop( mkSzOp(ty, Iop_Not8),
4308                                  mkexpr(rB))));
4309          break;
4310 
4311       case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371)
4312          IRExpr* lo32;
4313          if (rB_addr!=0) {
4314             vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n");
4315             return False;
4316          }
4317          DIP("cntlzw%s r%u,r%u\n",
4318              flag_rC ? ".":"", rA_addr, rS_addr);
4319 
4320          // mode64: count in low word only
4321          lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS);
4322 
4323          // Iop_Clz32 undefined for arg==0, so deal with that case:
4324          irx =  binop(Iop_CmpNE32, lo32, mkU32(0));
4325          assign(rA, mkWidenFrom32(ty,
4326                          IRExpr_ITE( irx,
4327                                      unop(Iop_Clz32, lo32),
4328                                      mkU32(32)),
4329                          False));
4330 
4331          // TODO: alternatively: assign(rA, verbose_Clz32(rS));
4332          break;
4333       }
4334 
4335       case 0x11C: // eqv (Equivalent, PPC32 p396)
4336          DIP("eqv%s r%u,r%u,r%u\n",
4337              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4338          assign( rA, unop( mkSzOp(ty, Iop_Not8),
4339                            binop( mkSzOp(ty, Iop_Xor8),
4340                                   mkexpr(rS), mkexpr(rB))) );
4341          break;
4342 
4343       case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397
4344          if (rB_addr!=0) {
4345             vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n");
4346             return False;
4347          }
4348          DIP("extsb%s r%u,r%u\n",
4349              flag_rC ? ".":"", rA_addr, rS_addr);
4350          if (mode64)
4351             assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) );
4352          else
4353             assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) );
4354          break;
4355 
4356       case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398)
4357          if (rB_addr!=0) {
4358             vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n");
4359             return False;
4360          }
4361          DIP("extsh%s r%u,r%u\n",
4362              flag_rC ? ".":"", rA_addr, rS_addr);
4363          if (mode64)
4364             assign( rA, unop(Iop_16Sto64,
4365                              unop(Iop_64to16, mkexpr(rS))) );
4366          else
4367             assign( rA, unop(Iop_16Sto32,
4368                              unop(Iop_32to16, mkexpr(rS))) );
4369          break;
4370 
4371       case 0x1DC: // nand (NAND, PPC32 p492)
4372          DIP("nand%s r%u,r%u,r%u\n",
4373              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4374          assign( rA, unop( mkSzOp(ty, Iop_Not8),
4375                            binop( mkSzOp(ty, Iop_And8),
4376                                   mkexpr(rS), mkexpr(rB))) );
4377          break;
4378 
4379       case 0x07C: // nor (NOR, PPC32 p494)
4380          DIP("nor%s r%u,r%u,r%u\n",
4381              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4382          assign( rA, unop( mkSzOp(ty, Iop_Not8),
4383                            binop( mkSzOp(ty, Iop_Or8),
4384                                   mkexpr(rS), mkexpr(rB))) );
4385          break;
4386 
4387       case 0x1BC: // or (OR, PPC32 p495)
4388          if ((!flag_rC) && rS_addr == rB_addr) {
4389             DIP("mr r%u,r%u\n", rA_addr, rS_addr);
4390             assign( rA, mkexpr(rS) );
4391          } else {
4392             DIP("or%s r%u,r%u,r%u\n",
4393                 flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4394             assign( rA, binop( mkSzOp(ty, Iop_Or8),
4395                                mkexpr(rS), mkexpr(rB)) );
4396          }
4397          break;
4398 
4399       case 0x19C: // orc  (OR with Complement, PPC32 p496)
4400          DIP("orc%s r%u,r%u,r%u\n",
4401              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4402          assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
4403                             unop(mkSzOp(ty, Iop_Not8), mkexpr(rB))));
4404          break;
4405 
4406       case 0x13C: // xor (XOR, PPC32 p549)
4407          DIP("xor%s r%u,r%u,r%u\n",
4408              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
4409          assign( rA, binop( mkSzOp(ty, Iop_Xor8),
4410                             mkexpr(rS), mkexpr(rB)) );
4411          break;
4412 
4413 
4414       /* 64bit Integer Logical Instructions */
4415       case 0x3DA: // extsw (Extend Sign Word, PPC64 p430)
4416          if (rB_addr!=0) {
4417             vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n");
4418             return False;
4419          }
4420          DIP("extsw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr);
4421          assign(rA, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(rS))));
4422          break;
4423 
4424       case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401)
4425          if (rB_addr!=0) {
4426             vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n");
4427             return False;
4428          }
4429          DIP("cntlzd%s r%u,r%u\n",
4430              flag_rC ? ".":"", rA_addr, rS_addr);
4431          // Iop_Clz64 undefined for arg==0, so deal with that case:
4432          irx =  binop(Iop_CmpNE64, mkexpr(rS), mkU64(0));
4433          assign(rA, IRExpr_ITE( irx,
4434                                 unop(Iop_Clz64, mkexpr(rS)),
4435                                 mkU64(64) ));
4436          // TODO: alternatively: assign(rA, verbose_Clz64(rS));
4437          break;
4438 
4439       case 0x1FC: // cmpb (Power6: compare bytes)
4440          DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
4441 
4442          if (mode64)
4443             assign( rA, unop( Iop_V128to64,
4444                               binop( Iop_CmpEQ8x16,
4445                                      binop( Iop_64HLtoV128, mkU64(0), mkexpr(rS) ),
4446                                      binop( Iop_64HLtoV128, mkU64(0), mkexpr(rB) )
4447                                      )) );
4448          else
4449             assign( rA, unop( Iop_V128to32,
4450                               binop( Iop_CmpEQ8x16,
4451                                      unop( Iop_32UtoV128, mkexpr(rS) ),
4452                                      unop( Iop_32UtoV128, mkexpr(rB) )
4453                                      )) );
4454          break;
4455 
4456       case 0x2DF: { // mftgpr (move floating-point to general purpose register)
4457          IRTemp frB = newTemp(Ity_F64);
4458          DIP("mftgpr r%u,fr%u\n", rS_addr, rB_addr);
4459 
4460          assign( frB, getFReg(rB_addr));  // always F64
4461          if (mode64)
4462             assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
4463          else
4464             assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) );
4465 
4466          putIReg( rS_addr, mkexpr(rA));
4467          return True;
4468       }
4469 
4470       case 0x25F: { // mffgpr (move floating-point from general purpose register)
4471          IRTemp frA = newTemp(Ity_F64);
4472          DIP("mffgpr fr%u,r%u\n", rS_addr, rB_addr);
4473 
4474          if (mode64)
4475             assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) );
4476          else
4477             assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) );
4478 
4479          putFReg( rS_addr, mkexpr(frA));
4480          return True;
4481       }
4482       case 0x1FA: // popcntd (population count doubleword
4483       {
4484     	  DIP("popcntd r%u,r%u\n", rA_addr, rS_addr);
4485     	  IRTemp result = gen_POPCOUNT(ty, rS, DWORD);
4486     	  putIReg( rA_addr, mkexpr(result) );
4487     	  return True;
4488       }
4489       case 0x17A: // popcntw (Population Count Words)
4490       {
4491          DIP("popcntw r%u,r%u\n", rA_addr, rS_addr);
4492          if (mode64) {
4493             IRTemp resultHi, resultLo;
4494             IRTemp argLo = newTemp(Ity_I32);
4495             IRTemp argHi = newTemp(Ity_I32);
4496             assign(argLo, unop(Iop_64to32, mkexpr(rS)));
4497             assign(argHi, unop(Iop_64HIto32, mkexpr(rS)));
4498             resultLo = gen_POPCOUNT(Ity_I32, argLo, WORD);
4499             resultHi = gen_POPCOUNT(Ity_I32, argHi, WORD);
4500             putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), mkexpr(resultLo)));
4501          } else {
4502             IRTemp result = gen_POPCOUNT(ty, rS, WORD);
4503             putIReg( rA_addr, mkexpr(result) );
4504          }
4505          return True;
4506       }
4507       case 0x7A: // popcntb (Population Count Byte)
4508       {
4509          DIP("popcntb r%u,r%u\n", rA_addr, rS_addr);
4510 
4511          if (mode64) {
4512             IRTemp resultHi, resultLo;
4513             IRTemp argLo = newTemp(Ity_I32);
4514             IRTemp argHi = newTemp(Ity_I32);
4515             assign(argLo, unop(Iop_64to32, mkexpr(rS)));
4516             assign(argHi, unop(Iop_64HIto32, mkexpr(rS)));
4517             resultLo = gen_POPCOUNT(Ity_I32, argLo, BYTE);
4518             resultHi = gen_POPCOUNT(Ity_I32, argHi, BYTE);
4519             putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi),
4520                                     mkexpr(resultLo)));
4521          } else {
4522             IRTemp result = gen_POPCOUNT(ty, rS, BYTE);
4523             putIReg( rA_addr, mkexpr(result) );
4524          }
4525          return True;
4526       }
4527        case 0x0FC: // bpermd (Bit Permute Doubleword)
4528        {
4529           /* This is a lot of rigmarole to emulate bpermd like this, as it
4530            * could be done much faster by implementing a call to the native
4531            * instruction.  However, where possible I want to avoid using new
4532            * native instructions so that we can use valgrind to emulate those
4533            * instructions on older PPC64 hardware.
4534            */
4535  #define BPERMD_IDX_MASK 0x00000000000000FFULL
4536  #define BPERMD_BIT_MASK 0x8000000000000000ULL
4537           int i;
4538           IRExpr * rS_expr = mkexpr(rS);
4539           IRExpr * res = binop(Iop_And64, mkU64(0), mkU64(0));
4540           DIP("bpermd r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
4541           for (i = 0; i < 8; i++) {
4542              IRTemp idx_tmp = newTemp( Ity_I64 );
4543              IRTemp perm_bit = newTemp( Ity_I64 );
4544              IRTemp idx = newTemp( Ity_I8 );
4545              IRTemp idx_LT64 = newTemp( Ity_I1 );
4546              IRTemp idx_LT64_ity64 = newTemp( Ity_I64 );
4547 
4548              assign( idx_tmp,
4549                      binop( Iop_And64, mkU64( BPERMD_IDX_MASK ), rS_expr ) );
4550              assign( idx_LT64,
4551                            binop( Iop_CmpLT64U, mkexpr( idx_tmp ), mkU64( 64 ) ) );
4552              assign( idx,
4553                            binop( Iop_And8,
4554                                   unop( Iop_1Sto8,
4555                                         mkexpr(idx_LT64) ),
4556                                   unop( Iop_64to8, mkexpr( idx_tmp ) ) ) );
4557              /* If idx_LT64 == 0, we must force the perm bit to '0'. Below, we se idx
4558               * to determine which bit of rB to use for the perm bit, and then we shift
4559               * that bit to the MSB position.  We AND that with a 64-bit-ized idx_LT64
4560               * to set the final perm bit.
4561               */
4562              assign( idx_LT64_ity64,
4563                            unop( Iop_32Uto64, unop( Iop_1Uto32, mkexpr(idx_LT64 ) ) ) );
4564              assign( perm_bit,
4565                            binop( Iop_And64,
4566                                   mkexpr( idx_LT64_ity64 ),
4567                                   binop( Iop_Shr64,
4568                                          binop( Iop_And64,
4569                                                 mkU64( BPERMD_BIT_MASK ),
4570                                                 binop( Iop_Shl64,
4571                                                        mkexpr( rB ),
4572                                                        mkexpr( idx ) ) ),
4573                                          mkU8( 63 ) ) ) );
4574              res = binop( Iop_Or64,
4575                                 res,
4576                                 binop( Iop_Shl64,
4577                                        mkexpr( perm_bit ),
4578                                        mkU8( i ) ) );
4579              rS_expr = binop( Iop_Shr64, rS_expr, mkU8( 8 ) );
4580           }
4581           putIReg(rA_addr, res);
4582           return True;
4583        }
4584 
4585       default:
4586          vex_printf("dis_int_logic(ppc)(opc2)\n");
4587          return False;
4588       }
4589       break;
4590 
4591    default:
4592       vex_printf("dis_int_logic(ppc)(opc1)\n");
4593       return False;
4594    }
4595 
4596    putIReg( rA_addr, mkexpr(rA) );
4597 
4598    if (do_rc && flag_rC) {
4599       set_CR0( mkexpr(rA) );
4600    }
4601    return True;
4602 }
4603 
4604 /*
4605   Integer Parity Instructions
4606 */
dis_int_parity(UInt theInstr)4607 static Bool dis_int_parity ( UInt theInstr )
4608 {
4609    /* X-Form */
4610    UChar opc1    = ifieldOPC(theInstr);
4611    UChar rS_addr = ifieldRegDS(theInstr);
4612    UChar rA_addr = ifieldRegA(theInstr);
4613    UChar rB_addr = ifieldRegB(theInstr);
4614    UInt  opc2    = ifieldOPClo10(theInstr);
4615    UChar b0      = ifieldBIT0(theInstr);
4616    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
4617 
4618    IRTemp rS     = newTemp(ty);
4619    IRTemp rA     = newTemp(ty);
4620    IRTemp iTot1  = newTemp(Ity_I32);
4621    IRTemp iTot2  = newTemp(Ity_I32);
4622    IRTemp iTot3  = newTemp(Ity_I32);
4623    IRTemp iTot4  = newTemp(Ity_I32);
4624    IRTemp iTot5  = newTemp(Ity_I32);
4625    IRTemp iTot6  = newTemp(Ity_I32);
4626    IRTemp iTot7  = newTemp(Ity_I32);
4627    IRTemp iTot8  = newTemp(Ity_I32);
4628    IRTemp rS1    = newTemp(ty);
4629    IRTemp rS2    = newTemp(ty);
4630    IRTemp rS3    = newTemp(ty);
4631    IRTemp rS4    = newTemp(ty);
4632    IRTemp rS5    = newTemp(ty);
4633    IRTemp rS6    = newTemp(ty);
4634    IRTemp rS7    = newTemp(ty);
4635    IRTemp iHi    = newTemp(Ity_I32);
4636    IRTemp iLo    = newTemp(Ity_I32);
4637    IROp to_bit   = (mode64 ? Iop_64to1 : Iop_32to1);
4638    IROp shr_op   = (mode64 ? Iop_Shr64 : Iop_Shr32);
4639 
4640    if (opc1 != 0x1f || rB_addr || b0) {
4641       vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n");
4642       return False;
4643    }
4644 
4645    assign( rS, getIReg(rS_addr) );
4646 
4647    switch (opc2) {
4648    case 0xba:  // prtyd (Parity Doubleword, ISA 2.05 p320)
4649       DIP("prtyd r%u,r%u\n", rA_addr, rS_addr);
4650       assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
4651       assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
4652       assign( iTot2, binop(Iop_Add32,
4653                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
4654                            mkexpr(iTot1)) );
4655       assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
4656       assign( iTot3, binop(Iop_Add32,
4657                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
4658                            mkexpr(iTot2)) );
4659       assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
4660       assign( iTot4, binop(Iop_Add32,
4661                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
4662                            mkexpr(iTot3)) );
4663       if (mode64) {
4664          assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
4665          assign( iTot5, binop(Iop_Add32,
4666                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))),
4667                               mkexpr(iTot4)) );
4668          assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
4669          assign( iTot6, binop(Iop_Add32,
4670                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
4671                               mkexpr(iTot5)) );
4672          assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
4673          assign( iTot7, binop(Iop_Add32,
4674                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
4675                               mkexpr(iTot6)) );
4676          assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)) );
4677          assign( iTot8, binop(Iop_Add32,
4678                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
4679                               mkexpr(iTot7)) );
4680          assign( rA, unop(Iop_32Uto64,
4681                           binop(Iop_And32, mkexpr(iTot8), mkU32(1))) );
4682       } else
4683          assign( rA, mkexpr(iTot4) );
4684 
4685       break;
4686    case 0x9a:  // prtyw (Parity Word, ISA 2.05 p320)
4687       assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
4688       assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
4689       assign( iTot2, binop(Iop_Add32,
4690                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
4691                            mkexpr(iTot1)) );
4692       assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
4693       assign( iTot3, binop(Iop_Add32,
4694                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
4695                            mkexpr(iTot2)) );
4696       assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
4697       assign( iTot4, binop(Iop_Add32,
4698                            unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
4699                            mkexpr(iTot3)) );
4700       assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) );
4701 
4702       if (mode64) {
4703          assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
4704          assign( iTot5, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))) );
4705          assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
4706          assign( iTot6, binop(Iop_Add32,
4707                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
4708                               mkexpr(iTot5)) );
4709          assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
4710          assign( iTot7, binop(Iop_Add32,
4711                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
4712                               mkexpr(iTot6)) );
4713          assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)));
4714          assign( iTot8, binop(Iop_Add32,
4715                               unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
4716                               mkexpr(iTot7)) );
4717          assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ),
4718             assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) );
4719       } else
4720          assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) );
4721       break;
4722    default:
4723       vex_printf("dis_int_parity(ppc)(opc2)\n");
4724       return False;
4725    }
4726 
4727    putIReg( rA_addr, mkexpr(rA) );
4728 
4729    return True;
4730 }
4731 
4732 
4733 /*
4734   Integer Rotate Instructions
4735 */
dis_int_rot(UInt theInstr)4736 static Bool dis_int_rot ( UInt theInstr )
4737 {
4738    /* M-Form, MDS-Form */
4739    UChar opc1    = ifieldOPC(theInstr);
4740    UChar rS_addr = ifieldRegDS(theInstr);
4741    UChar rA_addr = ifieldRegA(theInstr);
4742    UChar rB_addr = ifieldRegB(theInstr);
4743    UChar sh_imm  = rB_addr;
4744    UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) );
4745    UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) );
4746    UChar msk_imm = toUChar( IFIELD( theInstr, 5, 6 ) );
4747    UChar opc2    = toUChar( IFIELD( theInstr, 2, 3 ) );
4748    UChar b1      = ifieldBIT1(theInstr);
4749    UChar flag_rC = ifieldBIT0(theInstr);
4750 
4751    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
4752    IRTemp rS     = newTemp(ty);
4753    IRTemp rA     = newTemp(ty);
4754    IRTemp rB     = newTemp(ty);
4755    IRTemp rot    = newTemp(ty);
4756    IRExpr *r;
4757    UInt   mask32;
4758    ULong  mask64;
4759 
4760    assign( rS, getIReg(rS_addr) );
4761    assign( rB, getIReg(rB_addr) );
4762 
4763    switch (opc1) {
4764    case 0x14: {
4765       // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500)
4766       DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
4767           rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
4768       if (mode64) {
4769          // tmp32 = (ROTL(rS_Lo32, Imm)
4770          // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64)
4771          mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
4772          r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
4773          r = unop(Iop_32Uto64, r);
4774          assign( rot, binop(Iop_Or64, r,
4775                             binop(Iop_Shl64, r, mkU8(32))) );
4776          assign( rA,
4777             binop(Iop_Or64,
4778                   binop(Iop_And64, mkexpr(rot), mkU64(mask64)),
4779                   binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) );
4780       }
4781       else {
4782          // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask);
4783          mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
4784          r = ROTL(mkexpr(rS), mkU8(sh_imm));
4785          assign( rA,
4786             binop(Iop_Or32,
4787                   binop(Iop_And32, mkU32(mask32), r),
4788                   binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) );
4789       }
4790       break;
4791    }
4792 
4793    case 0x15: {
4794       // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501)
4795       vassert(MaskBeg < 32);
4796       vassert(MaskEnd < 32);
4797       vassert(sh_imm  < 32);
4798 
4799       if (mode64) {
4800          IRTemp rTmp = newTemp(Ity_I64);
4801          mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
4802          DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
4803              rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
4804          // tmp32 = (ROTL(rS_Lo32, Imm)
4805          // rA = ((tmp32 || tmp32) & mask64)
4806          r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
4807          r = unop(Iop_32Uto64, r);
4808          assign( rTmp, r );
4809          r = NULL;
4810          assign( rot, binop(Iop_Or64, mkexpr(rTmp),
4811                             binop(Iop_Shl64, mkexpr(rTmp), mkU8(32))) );
4812          assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
4813       }
4814       else {
4815          if (MaskBeg == 0 && sh_imm+MaskEnd == 31) {
4816             /* Special-case the ,n,0,31-n form as that is just n-bit
4817                shift left, PPC32 p501 */
4818             DIP("slwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
4819                 rA_addr, rS_addr, sh_imm);
4820             assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) );
4821          }
4822          else if (MaskEnd == 31 && sh_imm+MaskBeg == 32) {
4823             /* Special-case the ,32-n,n,31 form as that is just n-bit
4824                unsigned shift right, PPC32 p501 */
4825             DIP("srwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
4826                 rA_addr, rS_addr, MaskBeg);
4827             assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) );
4828          }
4829          else {
4830             /* General case. */
4831             mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
4832             DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
4833                 rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
4834             // rA = ROTL(rS, Imm) & mask
4835             assign( rA, binop(Iop_And32,
4836                               ROTL(mkexpr(rS), mkU8(sh_imm)),
4837                               mkU32(mask32)) );
4838          }
4839       }
4840       break;
4841    }
4842 
4843    case 0x17: {
4844       // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503
4845       DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? ".":"",
4846           rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd);
4847       if (mode64) {
4848          mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
4849          /* weird insn alert!
4850             tmp32 = (ROTL(rS_Lo32, rB[0-4])
4851             rA = ((tmp32 || tmp32) & mask64)
4852          */
4853          // note, ROTL does the masking, so we don't do it here
4854          r = ROTL( unop(Iop_64to32, mkexpr(rS)),
4855                    unop(Iop_64to8, mkexpr(rB)) );
4856          r = unop(Iop_32Uto64, r);
4857          assign(rot, binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32))));
4858          assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
4859       } else {
4860          mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
4861          // rA = ROTL(rS, rB[0-4]) & mask
4862          // note, ROTL does the masking, so we don't do it here
4863          assign( rA, binop(Iop_And32,
4864                            ROTL(mkexpr(rS),
4865                                 unop(Iop_32to8, mkexpr(rB))),
4866                            mkU32(mask32)) );
4867       }
4868       break;
4869    }
4870 
4871    /* 64bit Integer Rotates */
4872    case 0x1E: {
4873       msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1);
4874       sh_imm |= b1 << 5;
4875 
4876       vassert( msk_imm < 64 );
4877       vassert( sh_imm < 64 );
4878 
4879       switch (opc2) {
4880       case 0x4: {
4881          /* r = ROTL64( rS, rB_lo6) */
4882          r = ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) );
4883 
4884          if (b1 == 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555)
4885             DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
4886                 rA_addr, rS_addr, rB_addr, msk_imm);
4887             // note, ROTL does the masking, so we don't do it here
4888             mask64 = MASK64(0, 63-msk_imm);
4889             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4890             break;
4891          } else {       // rldcr (Rotl DWord, Clear Right, PPC64 p556)
4892             DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
4893                 rA_addr, rS_addr, rB_addr, msk_imm);
4894             mask64 = MASK64(63-msk_imm, 63);
4895             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4896             break;
4897          }
4898          break;
4899       }
4900       case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557)
4901          DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4902              rA_addr, rS_addr, sh_imm, msk_imm);
4903          r = ROTL(mkexpr(rS), mkU8(sh_imm));
4904          mask64 = MASK64(sh_imm, 63-msk_imm);
4905          assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4906          break;
4907          // later: deal with special case: (msk_imm==0) => SHL(sh_imm)
4908          /*
4909            Hmm... looks like this'll do the job more simply:
4910            r = SHL(rS, sh_imm)
4911            m = ~(1 << (63-msk_imm))
4912            assign(rA, r & m);
4913          */
4914 
4915       case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558)
4916          if (mode64
4917              && sh_imm + msk_imm == 64 && msk_imm >= 1 && msk_imm <= 63) {
4918             /* special-case the ,64-n,n form as that is just
4919                unsigned shift-right by n */
4920             DIP("srdi%s r%u,r%u,%u\n",
4921                 flag_rC ? ".":"", rA_addr, rS_addr, msk_imm);
4922             assign( rA, binop(Iop_Shr64, mkexpr(rS), mkU8(msk_imm)) );
4923          } else {
4924             DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4925                 rA_addr, rS_addr, sh_imm, msk_imm);
4926             r = ROTL(mkexpr(rS), mkU8(sh_imm));
4927             mask64 = MASK64(0, 63-msk_imm);
4928             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4929          }
4930          break;
4931 
4932       case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559)
4933          if (mode64
4934              && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) {
4935             /* special-case the ,n,63-n form as that is just
4936                shift-left by n */
4937             DIP("sldi%s r%u,r%u,%u\n",
4938                 flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
4939             assign( rA, binop(Iop_Shl64, mkexpr(rS), mkU8(sh_imm)) );
4940          } else {
4941             DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4942                 rA_addr, rS_addr, sh_imm, msk_imm);
4943             r = ROTL(mkexpr(rS), mkU8(sh_imm));
4944             mask64 = MASK64(63-msk_imm, 63);
4945             assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4946          }
4947          break;
4948 
4949       case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560)
4950          IRTemp rA_orig = newTemp(ty);
4951          DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4952              rA_addr, rS_addr, sh_imm, msk_imm);
4953          r = ROTL(mkexpr(rS), mkU8(sh_imm));
4954          mask64 = MASK64(sh_imm, 63-msk_imm);
4955          assign( rA_orig, getIReg(rA_addr) );
4956          assign( rA, binop(Iop_Or64,
4957                            binop(Iop_And64, mkU64(mask64),  r),
4958                            binop(Iop_And64, mkU64(~mask64),
4959                                             mkexpr(rA_orig))) );
4960          break;
4961       }
4962       default:
4963          vex_printf("dis_int_rot(ppc)(opc2)\n");
4964          return False;
4965       }
4966       break;
4967    }
4968 
4969    default:
4970       vex_printf("dis_int_rot(ppc)(opc1)\n");
4971       return False;
4972    }
4973 
4974    putIReg( rA_addr, mkexpr(rA) );
4975 
4976    if (flag_rC) {
4977       set_CR0( mkexpr(rA) );
4978    }
4979    return True;
4980 }
4981 
4982 
4983 /*
4984   Integer Load Instructions
4985 */
dis_int_load(UInt theInstr)4986 static Bool dis_int_load ( UInt theInstr )
4987 {
4988    /* D-Form, X-Form, DS-Form */
4989    UChar opc1     = ifieldOPC(theInstr);
4990    UChar rD_addr  = ifieldRegDS(theInstr);
4991    UChar rA_addr  = ifieldRegA(theInstr);
4992    UInt  uimm16   = ifieldUIMM16(theInstr);
4993    UChar rB_addr  = ifieldRegB(theInstr);
4994    UInt  opc2     = ifieldOPClo10(theInstr);
4995    UChar b1       = ifieldBIT1(theInstr);
4996    UChar b0       = ifieldBIT0(theInstr);
4997 
4998    Int     simm16 = extend_s_16to32(uimm16);
4999    IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
5000    IRTemp  EA     = newTemp(ty);
5001    IRExpr* val;
5002 
5003    switch (opc1) {
5004    case 0x1F: // register offset
5005       assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
5006       break;
5007    case 0x38: // immediate offset: 64bit: lq: maskoff
5008               // lowest 4 bits of immediate before forming EA
5009       simm16 = simm16 & 0xFFFFFFF0;
5010       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
5011       break;
5012    case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off
5013               // lowest 2 bits of immediate before forming EA
5014       simm16 = simm16 & 0xFFFFFFFC;
5015       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
5016       break;
5017    default:   // immediate offset
5018       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
5019       break;
5020    }
5021 
5022    switch (opc1) {
5023    case 0x22: // lbz (Load B & Zero, PPC32 p433)
5024       DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
5025       val = load(Ity_I8, mkexpr(EA));
5026       putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
5027       break;
5028 
5029    case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434)
5030       if (rA_addr == 0 || rA_addr == rD_addr) {
5031          vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n");
5032          return False;
5033       }
5034       DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
5035       val = load(Ity_I8, mkexpr(EA));
5036       putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
5037       putIReg( rA_addr, mkexpr(EA) );
5038       break;
5039 
5040    case 0x2A: // lha (Load HW Alg, PPC32 p445)
5041       DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
5042       val = load(Ity_I16, mkexpr(EA));
5043       putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
5044       break;
5045 
5046    case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446)
5047       if (rA_addr == 0 || rA_addr == rD_addr) {
5048          vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n");
5049          return False;
5050       }
5051       DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
5052       val = load(Ity_I16, mkexpr(EA));
5053       putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
5054       putIReg( rA_addr, mkexpr(EA) );
5055       break;
5056 
5057    case 0x28: // lhz (Load HW & Zero, PPC32 p450)
5058       DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
5059       val = load(Ity_I16, mkexpr(EA));
5060       putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
5061       break;
5062 
5063    case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451)
5064       if (rA_addr == 0 || rA_addr == rD_addr) {
5065          vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n");
5066          return False;
5067       }
5068       DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
5069       val = load(Ity_I16, mkexpr(EA));
5070       putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
5071       putIReg( rA_addr, mkexpr(EA) );
5072       break;
5073 
5074    case 0x20: // lwz (Load W & Zero, PPC32 p460)
5075       DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
5076       val = load(Ity_I32, mkexpr(EA));
5077       putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
5078       break;
5079 
5080    case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461))
5081       if (rA_addr == 0 || rA_addr == rD_addr) {
5082          vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n");
5083          return False;
5084       }
5085       DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
5086       val = load(Ity_I32, mkexpr(EA));
5087       putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
5088       putIReg( rA_addr, mkexpr(EA) );
5089       break;
5090 
5091    /* X Form */
5092    case 0x1F:
5093       if (b0 != 0) {
5094          vex_printf("dis_int_load(ppc)(Ox1F,b0)\n");
5095          return False;
5096       }
5097 
5098       switch (opc2) {
5099       case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435)
5100          DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5101          if (rA_addr == 0 || rA_addr == rD_addr) {
5102             vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
5103             return False;
5104          }
5105          val = load(Ity_I8, mkexpr(EA));
5106          putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
5107          putIReg( rA_addr, mkexpr(EA) );
5108          break;
5109 
5110       case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436)
5111          DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5112          val = load(Ity_I8, mkexpr(EA));
5113          putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
5114          break;
5115 
5116       case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447)
5117          if (rA_addr == 0 || rA_addr == rD_addr) {
5118             vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n");
5119             return False;
5120          }
5121          DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5122          val = load(Ity_I16, mkexpr(EA));
5123          putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
5124          putIReg( rA_addr, mkexpr(EA) );
5125          break;
5126 
5127       case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448)
5128          DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5129          val = load(Ity_I16, mkexpr(EA));
5130          putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
5131          break;
5132 
5133       case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452)
5134          if (rA_addr == 0 || rA_addr == rD_addr) {
5135             vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n");
5136             return False;
5137          }
5138          DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5139          val = load(Ity_I16, mkexpr(EA));
5140          putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
5141          putIReg( rA_addr, mkexpr(EA) );
5142          break;
5143 
5144       case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453)
5145          DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5146          val = load(Ity_I16, mkexpr(EA));
5147          putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
5148          break;
5149 
5150       case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462)
5151          if (rA_addr == 0 || rA_addr == rD_addr) {
5152             vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
5153             return False;
5154          }
5155          DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5156          val = load(Ity_I32, mkexpr(EA));
5157          putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
5158          putIReg( rA_addr, mkexpr(EA) );
5159          break;
5160 
5161       case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463)
5162          DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5163          val = load(Ity_I32, mkexpr(EA));
5164          putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
5165          break;
5166 
5167 
5168       /* 64bit Loads */
5169       case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475)
5170          if (rA_addr == 0 || rA_addr == rD_addr) {
5171             vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n");
5172             return False;
5173          }
5174          DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5175          putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
5176          putIReg( rA_addr, mkexpr(EA) );
5177          break;
5178 
5179       case 0x015: // ldx (Load DWord, Indexed, PPC64 p476)
5180          DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5181          putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
5182          break;
5183 
5184       case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501)
5185          if (rA_addr == 0 || rA_addr == rD_addr) {
5186             vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n");
5187             return False;
5188          }
5189          DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5190          putIReg( rD_addr,
5191                   unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
5192          putIReg( rA_addr, mkexpr(EA) );
5193          break;
5194 
5195       case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502)
5196          DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5197          putIReg( rD_addr,
5198                   unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
5199          break;
5200 
5201       default:
5202          vex_printf("dis_int_load(ppc)(opc2)\n");
5203          return False;
5204       }
5205       break;
5206 
5207    /* DS Form - 64bit Loads.  In each case EA will have been formed
5208       with the lowest 2 bits masked off the immediate offset. */
5209    case 0x3A:
5210       switch ((b1<<1) | b0) {
5211       case 0x0: // ld (Load DWord, PPC64 p472)
5212          DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
5213          putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
5214          break;
5215 
5216       case 0x1: // ldu (Load DWord, Update, PPC64 p474)
5217          if (rA_addr == 0 || rA_addr == rD_addr) {
5218             vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n");
5219             return False;
5220          }
5221          DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
5222          putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
5223          putIReg( rA_addr, mkexpr(EA) );
5224          break;
5225 
5226       case 0x2: // lwa (Load Word Alg, PPC64 p499)
5227          DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
5228          putIReg( rD_addr,
5229                   unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
5230          break;
5231 
5232       default:
5233          vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
5234          return False;
5235       }
5236       break;
5237 
5238    case 0x38: {
5239       IRTemp  high = newTemp(ty);
5240       IRTemp  low  = newTemp(ty);
5241       /* DQ Form - 128bit Loads. Lowest bits [1:0] are the PT field. */
5242       DIP("lq r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
5243       /* NOTE: there are some changes to XER[41:42] that have not been
5244        * implemented.
5245        */
5246       // trap if EA misaligned on 16 byte address
5247       if (mode64) {
5248          if (host_endness == VexEndnessBE) {
5249             assign(high, load(ty, mkexpr( EA ) ) );
5250             assign(low, load(ty, binop( Iop_Add64,
5251                                         mkexpr( EA ),
5252                                         mkU64( 8 ) ) ) );
5253 	 } else {
5254             assign(low, load(ty, mkexpr( EA ) ) );
5255             assign(high, load(ty, binop( Iop_Add64,
5256                                          mkexpr( EA ),
5257                                          mkU64( 8 ) ) ) );
5258 	 }
5259       } else {
5260          assign(high, load(ty, binop( Iop_Add32,
5261                                       mkexpr( EA ),
5262                                       mkU32( 4 ) ) ) );
5263          assign(low, load(ty, binop( Iop_Add32,
5264                                       mkexpr( EA ),
5265                                       mkU32( 12 ) ) ) );
5266       }
5267       gen_SIGBUS_if_misaligned( EA, 16 );
5268       putIReg( rD_addr,  mkexpr( high) );
5269       putIReg( rD_addr+1,  mkexpr( low) );
5270       break;
5271    }
5272    default:
5273       vex_printf("dis_int_load(ppc)(opc1)\n");
5274       return False;
5275    }
5276    return True;
5277 }
5278 
5279 
5280 
5281 /*
5282   Integer Store Instructions
5283 */
dis_int_store(UInt theInstr,const VexAbiInfo * vbi)5284 static Bool dis_int_store ( UInt theInstr, const VexAbiInfo* vbi )
5285 {
5286    /* D-Form, X-Form, DS-Form */
5287    UChar opc1    = ifieldOPC(theInstr);
5288    UInt  rS_addr = ifieldRegDS(theInstr);
5289    UInt  rA_addr = ifieldRegA(theInstr);
5290    UInt  uimm16  = ifieldUIMM16(theInstr);
5291    UInt  rB_addr = ifieldRegB(theInstr);
5292    UInt  opc2    = ifieldOPClo10(theInstr);
5293    UChar b1      = ifieldBIT1(theInstr);
5294    UChar b0      = ifieldBIT0(theInstr);
5295 
5296    Int    simm16 = extend_s_16to32(uimm16);
5297    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
5298    IRTemp rS     = newTemp(ty);
5299    IRTemp rB     = newTemp(ty);
5300    IRTemp EA     = newTemp(ty);
5301 
5302    assign( rB, getIReg(rB_addr) );
5303    assign( rS, getIReg(rS_addr) );
5304 
5305    switch (opc1) {
5306    case 0x1F: // register offset
5307       assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
5308       break;
5309    case 0x3E: // immediate offset: 64bit: std/stdu/stq: mask off
5310               // lowest 2 bits of immediate before forming EA
5311       simm16 = simm16 & 0xFFFFFFFC;
5312    default:   // immediate offset
5313       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
5314       break;
5315    }
5316 
5317    switch (opc1) {
5318    case 0x26: // stb (Store B, PPC32 p509)
5319       DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5320       store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
5321       break;
5322 
5323    case 0x27: // stbu (Store B, Update, PPC32 p510)
5324       if (rA_addr == 0 ) {
5325          vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n");
5326          return False;
5327       }
5328       DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5329       putIReg( rA_addr, mkexpr(EA) );
5330       store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
5331       break;
5332 
5333    case 0x2C: // sth (Store HW, PPC32 p522)
5334       DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5335       store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
5336       break;
5337 
5338    case 0x2D: // sthu (Store HW, Update, PPC32 p524)
5339       if (rA_addr == 0) {
5340          vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n");
5341          return False;
5342       }
5343       DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5344       putIReg( rA_addr, mkexpr(EA) );
5345       store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
5346       break;
5347 
5348    case 0x24: // stw (Store W, PPC32 p530)
5349       DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5350       store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
5351       break;
5352 
5353    case 0x25: // stwu (Store W, Update, PPC32 p534)
5354       if (rA_addr == 0) {
5355          vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n");
5356          return False;
5357       }
5358       DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5359       putIReg( rA_addr, mkexpr(EA) );
5360       store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
5361       break;
5362 
5363    /* X Form : all these use EA_indexed */
5364    case 0x1F:
5365       if (b0 != 0) {
5366          vex_printf("dis_int_store(ppc)(0x1F,b0)\n");
5367          return False;
5368       }
5369 
5370       switch (opc2) {
5371       case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511)
5372          if (rA_addr == 0) {
5373             vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n");
5374             return False;
5375          }
5376          DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5377          putIReg( rA_addr, mkexpr(EA) );
5378          store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
5379          break;
5380 
5381       case 0x0D7: // stbx (Store B Indexed, PPC32 p512)
5382          DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5383          store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
5384          break;
5385 
5386       case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525)
5387          if (rA_addr == 0) {
5388             vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n");
5389             return False;
5390          }
5391          DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5392          putIReg( rA_addr, mkexpr(EA) );
5393          store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
5394          break;
5395 
5396       case 0x197: // sthx (Store HW Indexed, PPC32 p526)
5397          DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5398          store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
5399          break;
5400 
5401       case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535)
5402          if (rA_addr == 0) {
5403             vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n");
5404             return False;
5405          }
5406          DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5407          putIReg( rA_addr, mkexpr(EA) );
5408          store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
5409          break;
5410 
5411       case 0x097: // stwx (Store W Indexed, PPC32 p536)
5412          DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5413          store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
5414          break;
5415 
5416 
5417       /* 64bit Stores */
5418       case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584)
5419          if (rA_addr == 0) {
5420             vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n");
5421             return False;
5422          }
5423          DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5424          putIReg( rA_addr, mkexpr(EA) );
5425          store( mkexpr(EA), mkexpr(rS) );
5426          break;
5427 
5428       case 0x095: // stdx (Store DWord Indexed, PPC64 p585)
5429          DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5430          store( mkexpr(EA), mkexpr(rS) );
5431          break;
5432 
5433       default:
5434          vex_printf("dis_int_store(ppc)(opc2)\n");
5435          return False;
5436       }
5437       break;
5438 
5439    /* DS Form - 64bit Stores.  In each case EA will have been formed
5440       with the lowest 2 bits masked off the immediate offset. */
5441    case 0x3E:
5442       switch ((b1<<1) | b0) {
5443       case 0x0: // std (Store DWord, PPC64 p580)
5444          if (!mode64)
5445             return False;
5446 
5447          DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5448          store( mkexpr(EA), mkexpr(rS) );
5449          break;
5450 
5451       case 0x1: // stdu (Store DWord, Update, PPC64 p583)
5452          if (!mode64)
5453             return False;
5454 
5455          DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5456          putIReg( rA_addr, mkexpr(EA) );
5457          store( mkexpr(EA), mkexpr(rS) );
5458          break;
5459 
5460       case 0x2: { // stq (Store QuadWord, Update, PPC64 p583)
5461          IRTemp EA_hi = newTemp(ty);
5462          IRTemp EA_lo = newTemp(ty);
5463          DIP("stq r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5464 
5465          if (mode64) {
5466             if (host_endness == VexEndnessBE) {
5467 
5468                /* upper 64-bits */
5469                assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) );
5470 
5471                /* lower 64-bits */
5472                assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+8 ) );
5473 	    } else {
5474                /* upper 64-bits */
5475                assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+8 ) );
5476 
5477                /* lower 64-bits */
5478                assign( EA_lo, ea_rAor0_simm( rA_addr, simm16 ) );
5479 	    }
5480          } else {
5481             /* upper half of upper 64-bits */
5482             assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+4 ) );
5483 
5484             /* lower half of upper 64-bits */
5485             assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+12 ) );
5486          }
5487          store( mkexpr(EA_hi), mkexpr(rS) );
5488          store( mkexpr(EA_lo), getIReg( rS_addr+1 ) );
5489          break;
5490       }
5491       default:
5492          vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
5493          return False;
5494       }
5495       break;
5496 
5497    default:
5498       vex_printf("dis_int_store(ppc)(opc1)\n");
5499       return False;
5500    }
5501    return True;
5502 }
5503 
5504 
5505 
5506 /*
5507   Integer Load/Store Multiple Instructions
5508 */
dis_int_ldst_mult(UInt theInstr)5509 static Bool dis_int_ldst_mult ( UInt theInstr )
5510 {
5511    /* D-Form */
5512    UChar opc1     = ifieldOPC(theInstr);
5513    UChar rD_addr  = ifieldRegDS(theInstr);
5514    UChar rS_addr  = rD_addr;
5515    UChar rA_addr  = ifieldRegA(theInstr);
5516    UInt  uimm16   = ifieldUIMM16(theInstr);
5517 
5518    Int     simm16 = extend_s_16to32(uimm16);
5519    IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
5520    IROp    mkAdd  = mode64 ? Iop_Add64 : Iop_Add32;
5521    IRTemp  EA     = newTemp(ty);
5522    UInt    r      = 0;
5523    UInt    ea_off = 0;
5524    IRExpr* irx_addr;
5525 
5526    assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
5527 
5528    switch (opc1) {
5529    case 0x2E: // lmw (Load Multiple Word, PPC32 p454)
5530       if (rA_addr >= rD_addr) {
5531          vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n");
5532          return False;
5533       }
5534       DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
5535       for (r = rD_addr; r <= 31; r++) {
5536          irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off));
5537          putIReg( r, mkWidenFrom32(ty, load(Ity_I32, irx_addr ),
5538                                        False) );
5539          ea_off += 4;
5540       }
5541       break;
5542 
5543    case 0x2F: // stmw (Store Multiple Word, PPC32 p527)
5544       DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5545       for (r = rS_addr; r <= 31; r++) {
5546          irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off));
5547          store( irx_addr, mkNarrowTo32(ty, getIReg(r)) );
5548          ea_off += 4;
5549       }
5550       break;
5551 
5552    default:
5553       vex_printf("dis_int_ldst_mult(ppc)(opc1)\n");
5554       return False;
5555    }
5556    return True;
5557 }
5558 
5559 
5560 
5561 /*
5562   Integer Load/Store String Instructions
5563 */
5564 static
generate_lsw_sequence(IRTemp tNBytes,IRTemp EA,Int rD,Int maxBytes)5565 void generate_lsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
5566                              IRTemp EA,        // EA
5567                              Int    rD,        // first dst register
5568                              Int    maxBytes ) // 32 or 128
5569 {
5570    Int     i, shift = 24;
5571    IRExpr* e_nbytes = mkexpr(tNBytes);
5572    IRExpr* e_EA     = mkexpr(EA);
5573    IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
5574 
5575    vassert(rD >= 0 && rD < 32);
5576    rD--; if (rD < 0) rD = 31;
5577 
5578    for (i = 0; i < maxBytes; i++) {
5579       /* if (nBytes < (i+1)) goto NIA; */
5580       stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
5581                          Ijk_Boring,
5582                          mkSzConst( ty, nextInsnAddr()), OFFB_CIA ));
5583       /* when crossing into a new dest register, set it to zero. */
5584       if ((i % 4) == 0) {
5585          rD++; if (rD == 32) rD = 0;
5586          putIReg(rD, mkSzImm(ty, 0));
5587          shift = 24;
5588       }
5589       /* rD |=  (8Uto32(*(EA+i))) << shift */
5590       vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
5591       putIReg(
5592          rD,
5593          mkWidenFrom32(
5594             ty,
5595             binop(
5596                Iop_Or32,
5597                mkNarrowTo32(ty, getIReg(rD)),
5598                binop(
5599                   Iop_Shl32,
5600                   unop(
5601                      Iop_8Uto32,
5602                      load( Ity_I8,
5603                            binop( mkSzOp(ty,Iop_Add8),
5604                                   e_EA, mkSzImm(ty,i)))
5605                   ),
5606                   mkU8(toUChar(shift))
5607                )
5608             ),
5609             /*Signed*/False
5610 	 )
5611       );
5612       shift -= 8;
5613    }
5614 }
5615 
5616 static
generate_stsw_sequence(IRTemp tNBytes,IRTemp EA,Int rS,Int maxBytes)5617 void generate_stsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
5618                               IRTemp EA,        // EA
5619                               Int    rS,        // first src register
5620                               Int    maxBytes ) // 32 or 128
5621 {
5622    Int     i, shift = 24;
5623    IRExpr* e_nbytes = mkexpr(tNBytes);
5624    IRExpr* e_EA     = mkexpr(EA);
5625    IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
5626 
5627    vassert(rS >= 0 && rS < 32);
5628    rS--; if (rS < 0) rS = 31;
5629 
5630    for (i = 0; i < maxBytes; i++) {
5631       /* if (nBytes < (i+1)) goto NIA; */
5632       stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
5633                          Ijk_Boring,
5634                          mkSzConst( ty, nextInsnAddr() ), OFFB_CIA ));
5635       /* check for crossing into a new src register. */
5636       if ((i % 4) == 0) {
5637          rS++; if (rS == 32) rS = 0;
5638          shift = 24;
5639       }
5640       /* *(EA+i) = 32to8(rS >> shift) */
5641       vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
5642       store(
5643             binop( mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)),
5644             unop( Iop_32to8,
5645                   binop( Iop_Shr32,
5646                          mkNarrowTo32( ty, getIReg(rS) ),
5647                          mkU8( toUChar(shift) )))
5648       );
5649       shift -= 8;
5650    }
5651 }
5652 
dis_int_ldst_str(UInt theInstr,Bool * stopHere)5653 static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere )
5654 {
5655    /* X-Form */
5656    UChar opc1     = ifieldOPC(theInstr);
5657    UChar rD_addr  = ifieldRegDS(theInstr);
5658    UChar rS_addr  = rD_addr;
5659    UChar rA_addr  = ifieldRegA(theInstr);
5660    UChar rB_addr  = ifieldRegB(theInstr);
5661    UChar NumBytes = rB_addr;
5662    UInt  opc2     = ifieldOPClo10(theInstr);
5663    UChar b0       = ifieldBIT0(theInstr);
5664 
5665    IRType ty      = mode64 ? Ity_I64 : Ity_I32;
5666    IRTemp t_EA    = newTemp(ty);
5667    IRTemp t_nbytes = IRTemp_INVALID;
5668 
5669    *stopHere = False;
5670 
5671    if (opc1 != 0x1F || b0 != 0) {
5672       vex_printf("dis_int_ldst_str(ppc)(opc1)\n");
5673       return False;
5674    }
5675 
5676    switch (opc2) {
5677    case 0x255: // lswi (Load String Word Immediate, PPC32 p455)
5678       /* NB: does not reject the case where RA is in the range of
5679          registers to be loaded.  It should. */
5680       DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes);
5681       assign( t_EA, ea_rAor0(rA_addr) );
5682       if (NumBytes == 8 && !mode64) {
5683          /* Special case hack */
5684          /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */
5685          putIReg( rD_addr,
5686                   load(Ity_I32, mkexpr(t_EA)) );
5687          putIReg( (rD_addr+1) % 32,
5688                   load(Ity_I32,
5689                        binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) );
5690       } else {
5691          t_nbytes = newTemp(Ity_I32);
5692          assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
5693          generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
5694          *stopHere = True;
5695       }
5696       return True;
5697 
5698    case 0x215: // lswx (Load String Word Indexed, PPC32 p456)
5699       /* NB: does not reject the case where RA is in the range of
5700          registers to be loaded.  It should.  Although considering
5701          that that can only be detected at run time, it's not easy to
5702          do so. */
5703       if (rD_addr == rA_addr || rD_addr == rB_addr)
5704          return False;
5705       if (rD_addr == 0 && rA_addr == 0)
5706          return False;
5707       DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5708       t_nbytes = newTemp(Ity_I32);
5709       assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
5710       assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
5711       generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 );
5712       *stopHere = True;
5713       return True;
5714 
5715    case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528)
5716       DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes);
5717       assign( t_EA, ea_rAor0(rA_addr) );
5718       if (NumBytes == 8 && !mode64) {
5719          /* Special case hack */
5720          /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */
5721          store( mkexpr(t_EA),
5722                 getIReg(rD_addr) );
5723          store( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)),
5724                 getIReg((rD_addr+1) % 32) );
5725       } else {
5726          t_nbytes = newTemp(Ity_I32);
5727          assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
5728          generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
5729          *stopHere = True;
5730       }
5731       return True;
5732 
5733    case 0x295: // stswx (Store String Word Indexed, PPC32 p529)
5734       DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5735       t_nbytes = newTemp(Ity_I32);
5736       assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
5737       assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
5738       generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 );
5739       *stopHere = True;
5740       return True;
5741 
5742    default:
5743       vex_printf("dis_int_ldst_str(ppc)(opc2)\n");
5744       return False;
5745    }
5746    return True;
5747 }
5748 
5749 
5750 /* ------------------------------------------------------------------
5751    Integer Branch Instructions
5752    ------------------------------------------------------------------ */
5753 
5754 /*
5755   Branch helper function
5756   ok = BO[2] | ((CTR[0] != 0) ^ BO[1])
5757   Returns an I32 which is 0x00000000 if the ctr condition failed
5758   and 0xFFFFFFFF otherwise.
5759 */
branch_ctr_ok(UInt BO)5760 static IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO )
5761 {
5762    IRType ty = mode64 ? Ity_I64 : Ity_I32;
5763    IRTemp ok = newTemp(Ity_I32);
5764 
5765    if ((BO >> 2) & 1) {     // independent of ctr
5766       assign( ok, mkU32(0xFFFFFFFF) );
5767    } else {
5768       if ((BO >> 1) & 1) {  // ctr == 0 ?
5769          assign( ok, unop( Iop_1Sto32,
5770                            binop( mkSzOp(ty, Iop_CmpEQ8),
5771                                   getGST( PPC_GST_CTR ),
5772                                   mkSzImm(ty,0))) );
5773       } else {              // ctr != 0 ?
5774          assign( ok, unop( Iop_1Sto32,
5775                            binop( mkSzOp(ty, Iop_CmpNE8),
5776                                   getGST( PPC_GST_CTR ),
5777                                   mkSzImm(ty,0))) );
5778       }
5779    }
5780    return mkexpr(ok);
5781 }
5782 
5783 
5784 /*
5785   Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3])
5786   Returns an I32 which is either 0 if the condition failed or
5787   some arbitrary nonzero value otherwise. */
5788 
branch_cond_ok(UInt BO,UInt BI)5789 static IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI )
5790 {
5791    Int where;
5792    IRTemp res   = newTemp(Ity_I32);
5793    IRTemp cr_bi = newTemp(Ity_I32);
5794 
5795    if ((BO >> 4) & 1) {
5796       assign( res, mkU32(1) );
5797    } else {
5798       // ok = (CR[BI] == BO[3]) Note, the following relies on
5799       // getCRbit_anywhere returning a value which
5800       // is either zero or has exactly 1 bit set.
5801       assign( cr_bi, getCRbit_anywhere( BI, &where ) );
5802 
5803       if ((BO >> 3) & 1) {
5804          /* We can use cr_bi as-is. */
5805          assign( res, mkexpr(cr_bi) );
5806       } else {
5807          /* We have to invert the sense of the information held in
5808             cr_bi.  For that we need to know which bit
5809             getCRbit_anywhere regards as significant. */
5810          assign( res, binop(Iop_Xor32, mkexpr(cr_bi),
5811                                        mkU32(1<<where)) );
5812       }
5813    }
5814    return mkexpr(res);
5815 }
5816 
5817 
5818 /*
5819   Integer Branch Instructions
5820 */
dis_branch(UInt theInstr,const VexAbiInfo * vbi,DisResult * dres,Bool (* resteerOkFn)(void *,Addr),void * callback_opaque)5821 static Bool dis_branch ( UInt theInstr,
5822                          const VexAbiInfo* vbi,
5823                          /*OUT*/DisResult* dres,
5824                          Bool (*resteerOkFn)(void*,Addr),
5825                          void* callback_opaque )
5826 {
5827    UChar opc1    = ifieldOPC(theInstr);
5828    UChar BO      = ifieldRegDS(theInstr);
5829    UChar BI      = ifieldRegA(theInstr);
5830    UInt  BD_u16  = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */
5831    UChar b11to15 = ifieldRegB(theInstr);
5832    UInt  opc2    = ifieldOPClo10(theInstr);
5833    UInt  LI_u26  = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */
5834    UChar flag_AA = ifieldBIT1(theInstr);
5835    UChar flag_LK = ifieldBIT0(theInstr);
5836 
5837    IRType   ty        = mode64 ? Ity_I64 : Ity_I32;
5838    Addr64   tgt       = 0;
5839    UInt     BD        = extend_s_16to32(BD_u16);
5840    IRTemp   do_branch = newTemp(Ity_I32);
5841    IRTemp   ctr_ok    = newTemp(Ity_I32);
5842    IRTemp   cond_ok   = newTemp(Ity_I32);
5843    IRExpr*  e_nia     = mkSzImm(ty, nextInsnAddr());
5844    IRConst* c_nia     = mkSzConst(ty, nextInsnAddr());
5845    IRTemp   lr_old    = newTemp(ty);
5846 
5847    /* Hack to pass through code that just wants to read the PC */
5848    if (theInstr == 0x429F0005) {
5849       DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI);
5850       putGST( PPC_GST_LR, e_nia );
5851       return True;
5852    }
5853 
5854    /* The default what-next.  Individual cases can override it. */
5855    dres->whatNext = Dis_StopHere;
5856    vassert(dres->jk_StopHere == Ijk_INVALID);
5857 
5858    switch (opc1) {
5859    case 0x12: // b     (Branch, PPC32 p360)
5860       if (flag_AA) {
5861          tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) );
5862       } else {
5863          tgt = mkSzAddr( ty, guest_CIA_curr_instr +
5864                              (Long)extend_s_26to64(LI_u26) );
5865       }
5866       if (mode64) {
5867          DIP("b%s%s 0x%llx\n",
5868              flag_LK ? "l" : "", flag_AA ? "a" : "", tgt);
5869       } else {
5870          DIP("b%s%s 0x%x\n",
5871              flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt);
5872       }
5873 
5874       if (flag_LK) {
5875          putGST( PPC_GST_LR, e_nia );
5876          if (vbi->guest_ppc_zap_RZ_at_bl
5877              && vbi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) {
5878             IRTemp t_tgt = newTemp(ty);
5879             assign(t_tgt, mode64 ? mkU64(tgt) : mkU32(tgt) );
5880             make_redzone_AbiHint( vbi, t_tgt,
5881                                   "branch-and-link (unconditional call)" );
5882          }
5883       }
5884 
5885       if (resteerOkFn( callback_opaque, tgt )) {
5886          dres->whatNext   = Dis_ResteerU;
5887          dres->continueAt = tgt;
5888       } else {
5889          dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring; ;
5890          putGST( PPC_GST_CIA, mkSzImm(ty, tgt) );
5891       }
5892       break;
5893 
5894    case 0x10: // bc    (Branch Conditional, PPC32 p361)
5895       DIP("bc%s%s 0x%x, 0x%x, 0x%x\n",
5896           flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD);
5897 
5898       if (!(BO & 0x4)) {
5899          putGST( PPC_GST_CTR,
5900                  binop(mkSzOp(ty, Iop_Sub8),
5901                        getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
5902       }
5903 
5904       /* This is a bit subtle.  ctr_ok is either all 0s or all 1s.
5905          cond_ok is either zero or nonzero, since that's the cheapest
5906          way to compute it.  Anding them together gives a value which
5907          is either zero or non zero and so that's what we must test
5908          for in the IRStmt_Exit. */
5909       assign( ctr_ok,  branch_ctr_ok( BO ) );
5910       assign( cond_ok, branch_cond_ok( BO, BI ) );
5911       assign( do_branch,
5912               binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
5913 
5914       if (flag_AA) {
5915          tgt = mkSzAddr(ty, extend_s_16to64(BD_u16));
5916       } else {
5917          tgt = mkSzAddr(ty, guest_CIA_curr_instr +
5918                             (Long)extend_s_16to64(BD_u16));
5919       }
5920       if (flag_LK)
5921          putGST( PPC_GST_LR, e_nia );
5922 
5923       stmt( IRStmt_Exit(
5924                binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)),
5925                flag_LK ? Ijk_Call : Ijk_Boring,
5926                mkSzConst(ty, tgt), OFFB_CIA ) );
5927 
5928       dres->jk_StopHere = Ijk_Boring;
5929       putGST( PPC_GST_CIA, e_nia );
5930       break;
5931 
5932    case 0x13:
5933       /* For bclr and bcctr, it appears that the lowest two bits of
5934          b11to15 are a branch hint, and so we only need to ensure it's
5935          of the form 000XX. */
5936       if ((b11to15 & ~3) != 0) {
5937          vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", b11to15);
5938          return False;
5939       }
5940 
5941       switch (opc2) {
5942       case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363)
5943          if ((BO & 0x4) == 0) { // "decr and test CTR" option invalid
5944             vex_printf("dis_int_branch(ppc)(bcctr,BO)\n");
5945             return False;
5946          }
5947          DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
5948 
5949          assign( cond_ok, branch_cond_ok( BO, BI ) );
5950 
5951          /* FIXME: this is confusing.  lr_old holds the old value
5952             of ctr, not lr :-) */
5953          assign( lr_old, addr_align( getGST( PPC_GST_CTR ), 4 ));
5954 
5955          if (flag_LK)
5956             putGST( PPC_GST_LR, e_nia );
5957 
5958          stmt( IRStmt_Exit(
5959                   binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)),
5960                   Ijk_Boring,
5961                   c_nia, OFFB_CIA ));
5962 
5963          if (flag_LK && vbi->guest_ppc_zap_RZ_at_bl) {
5964             make_redzone_AbiHint( vbi, lr_old,
5965                                   "b-ctr-l (indirect call)" );
5966 	 }
5967 
5968          dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring;;
5969          putGST( PPC_GST_CIA, mkexpr(lr_old) );
5970          break;
5971 
5972       case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365)
5973          Bool vanilla_return = False;
5974          if ((BO & 0x14 /* 1z1zz */) == 0x14 && flag_LK == 0) {
5975             DIP("blr\n");
5976             vanilla_return = True;
5977          } else {
5978             DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
5979          }
5980 
5981          if (!(BO & 0x4)) {
5982             putGST( PPC_GST_CTR,
5983                     binop(mkSzOp(ty, Iop_Sub8),
5984                           getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
5985          }
5986 
5987          /* See comments above for 'bc' about this */
5988          assign( ctr_ok,  branch_ctr_ok( BO ) );
5989          assign( cond_ok, branch_cond_ok( BO, BI ) );
5990          assign( do_branch,
5991                  binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
5992 
5993          assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 ));
5994 
5995          if (flag_LK)
5996             putGST( PPC_GST_LR,  e_nia );
5997 
5998          stmt( IRStmt_Exit(
5999                   binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)),
6000                   Ijk_Boring,
6001                   c_nia, OFFB_CIA ));
6002 
6003          if (vanilla_return && vbi->guest_ppc_zap_RZ_at_blr) {
6004             make_redzone_AbiHint( vbi, lr_old,
6005                                   "branch-to-lr (unconditional return)" );
6006          }
6007 
6008          /* blrl is pretty strange; it's like a return that sets the
6009             return address of its caller to the insn following this
6010             one.  Mark it as a return. */
6011          dres->jk_StopHere = Ijk_Ret;  /* was flag_LK ? Ijk_Call : Ijk_Ret; */
6012          putGST( PPC_GST_CIA, mkexpr(lr_old) );
6013          break;
6014       }
6015       default:
6016          vex_printf("dis_int_branch(ppc)(opc2)\n");
6017          return False;
6018       }
6019       break;
6020 
6021    default:
6022       vex_printf("dis_int_branch(ppc)(opc1)\n");
6023       return False;
6024    }
6025 
6026    return True;
6027 }
6028 
6029 
6030 
6031 /*
6032   Condition Register Logical Instructions
6033 */
dis_cond_logic(UInt theInstr)6034 static Bool dis_cond_logic ( UInt theInstr )
6035 {
6036    /* XL-Form */
6037    UChar opc1      = ifieldOPC(theInstr);
6038    UChar crbD_addr = ifieldRegDS(theInstr);
6039    UChar crfD_addr = toUChar( IFIELD(theInstr, 23, 3) );
6040    UChar crbA_addr = ifieldRegA(theInstr);
6041    UChar crfS_addr = toUChar( IFIELD(theInstr, 18, 3) );
6042    UChar crbB_addr = ifieldRegB(theInstr);
6043    UInt  opc2      = ifieldOPClo10(theInstr);
6044    UChar b0        = ifieldBIT0(theInstr);
6045 
6046    IRTemp crbD     = newTemp(Ity_I32);
6047    IRTemp crbA     = newTemp(Ity_I32);
6048    IRTemp crbB     = newTemp(Ity_I32);
6049 
6050    if (opc1 != 19 || b0 != 0) {
6051       vex_printf("dis_cond_logic(ppc)(opc1)\n");
6052       return False;
6053    }
6054 
6055    if (opc2 == 0) {  // mcrf    (Move Cond Reg Field, PPC32 p464)
6056       if (((crbD_addr & 0x3) != 0) ||
6057           ((crbA_addr & 0x3) != 0) || (crbB_addr != 0)) {
6058          vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n");
6059          return False;
6060       }
6061       DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr);
6062       putCR0(   crfD_addr, getCR0(  crfS_addr) );
6063       putCR321( crfD_addr, getCR321(crfS_addr) );
6064    } else {
6065       assign( crbA, getCRbit(crbA_addr) );
6066       if (crbA_addr == crbB_addr)
6067          crbB = crbA;
6068       else
6069          assign( crbB, getCRbit(crbB_addr) );
6070 
6071       switch (opc2) {
6072       case 0x101: // crand   (Cond Reg AND, PPC32 p372)
6073          DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
6074          assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) );
6075          break;
6076       case 0x081: // crandc  (Cond Reg AND w. Complement, PPC32 p373)
6077          DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
6078          assign( crbD, binop(Iop_And32,
6079                              mkexpr(crbA),
6080                              unop(Iop_Not32, mkexpr(crbB))) );
6081          break;
6082       case 0x121: // creqv   (Cond Reg Equivalent, PPC32 p374)
6083          DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
6084          assign( crbD, unop(Iop_Not32,
6085                             binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) );
6086          break;
6087       case 0x0E1: // crnand  (Cond Reg NAND, PPC32 p375)
6088          DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
6089          assign( crbD, unop(Iop_Not32,
6090                             binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) );
6091          break;
6092       case 0x021: // crnor   (Cond Reg NOR, PPC32 p376)
6093          DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
6094          assign( crbD, unop(Iop_Not32,
6095                             binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) );
6096          break;
6097       case 0x1C1: // cror    (Cond Reg OR, PPC32 p377)
6098          DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
6099          assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) );
6100          break;
6101       case 0x1A1: // crorc   (Cond Reg OR w. Complement, PPC32 p378)
6102          DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
6103          assign( crbD, binop(Iop_Or32,
6104                              mkexpr(crbA),
6105                              unop(Iop_Not32, mkexpr(crbB))) );
6106          break;
6107       case 0x0C1: // crxor   (Cond Reg XOR, PPC32 p379)
6108          DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
6109          assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) );
6110          break;
6111       default:
6112          vex_printf("dis_cond_logic(ppc)(opc2)\n");
6113          return False;
6114       }
6115 
6116       putCRbit( crbD_addr, mkexpr(crbD) );
6117    }
6118    return True;
6119 }
6120 
6121 
6122 /*
6123   Trap instructions
6124 */
6125 
6126 /* Do the code generation for a trap.  Returned Bool is true iff
6127    this is an unconditional trap.  If the two arg IRExpr*s are
6128    Ity_I32s then the comparison is 32-bit.  If they are Ity_I64s
6129    then they are 64-bit, and we must be disassembling 64-bit
6130    instructions. */
do_trap(UChar TO,IRExpr * argL0,IRExpr * argR0,Addr64 cia)6131 static Bool do_trap ( UChar TO,
6132                       IRExpr* argL0, IRExpr* argR0, Addr64 cia )
6133 {
6134    IRTemp argL, argR;
6135    IRExpr *argLe, *argRe, *cond, *tmp;
6136 
6137    Bool    is32bit = typeOfIRExpr(irsb->tyenv, argL0 ) == Ity_I32;
6138 
6139    IROp    opAND     = is32bit ? Iop_And32     : Iop_And64;
6140    IROp    opOR      = is32bit ? Iop_Or32      : Iop_Or64;
6141    IROp    opCMPORDS = is32bit ? Iop_CmpORD32S : Iop_CmpORD64S;
6142    IROp    opCMPORDU = is32bit ? Iop_CmpORD32U : Iop_CmpORD64U;
6143    IROp    opCMPNE   = is32bit ? Iop_CmpNE32   : Iop_CmpNE64;
6144    IROp    opCMPEQ   = is32bit ? Iop_CmpEQ32   : Iop_CmpEQ64;
6145    IRExpr* const0    = is32bit ? mkU32(0)      : mkU64(0);
6146    IRExpr* const2    = is32bit ? mkU32(2)      : mkU64(2);
6147    IRExpr* const4    = is32bit ? mkU32(4)      : mkU64(4);
6148    IRExpr* const8    = is32bit ? mkU32(8)      : mkU64(8);
6149 
6150    const UChar b11100 = 0x1C;
6151    const UChar b00111 = 0x07;
6152 
6153    if (is32bit) {
6154       vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 );
6155       vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 );
6156    } else {
6157       vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 );
6158       vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 );
6159       vassert( mode64 );
6160    }
6161 
6162    if ((TO & b11100) == b11100 || (TO & b00111) == b00111) {
6163       /* Unconditional trap.  Just do the exit without
6164          testing the arguments. */
6165       stmt( IRStmt_Exit(
6166                binop(opCMPEQ, const0, const0),
6167                Ijk_SigTRAP,
6168                mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia),
6169                OFFB_CIA
6170       ));
6171       return True; /* unconditional trap */
6172    }
6173 
6174    if (is32bit) {
6175       argL = newTemp(Ity_I32);
6176       argR = newTemp(Ity_I32);
6177    } else {
6178       argL = newTemp(Ity_I64);
6179       argR = newTemp(Ity_I64);
6180    }
6181 
6182    assign( argL, argL0 );
6183    assign( argR, argR0 );
6184 
6185    argLe = mkexpr(argL);
6186    argRe = mkexpr(argR);
6187 
6188    cond = const0;
6189    if (TO & 16) { // L <s R
6190       tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const8);
6191       cond = binop(opOR, tmp, cond);
6192    }
6193    if (TO & 8) { // L >s R
6194       tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4);
6195       cond = binop(opOR, tmp, cond);
6196    }
6197    if (TO & 4) { // L == R
6198       tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2);
6199       cond = binop(opOR, tmp, cond);
6200    }
6201    if (TO & 2) { // L <u R
6202       tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const8);
6203       cond = binop(opOR, tmp, cond);
6204    }
6205    if (TO & 1) { // L >u R
6206       tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4);
6207       cond = binop(opOR, tmp, cond);
6208    }
6209    stmt( IRStmt_Exit(
6210             binop(opCMPNE, cond, const0),
6211             Ijk_SigTRAP,
6212             mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia),
6213             OFFB_CIA
6214    ));
6215    return False; /* not an unconditional trap */
6216 }
6217 
dis_trapi(UInt theInstr,DisResult * dres)6218 static Bool dis_trapi ( UInt theInstr,
6219                         /*OUT*/DisResult* dres )
6220 {
6221    /* D-Form */
6222    UChar  opc1    = ifieldOPC(theInstr);
6223    UChar  TO      = ifieldRegDS(theInstr);
6224    UChar  rA_addr = ifieldRegA(theInstr);
6225    UInt   uimm16  = ifieldUIMM16(theInstr);
6226    ULong  simm16  = extend_s_16to64(uimm16);
6227    Addr64 cia     = guest_CIA_curr_instr;
6228    IRType ty      = mode64 ? Ity_I64 : Ity_I32;
6229    Bool   uncond  = False;
6230 
6231    switch (opc1) {
6232    case 0x03: // twi  (Trap Word Immediate, PPC32 p548)
6233       uncond = do_trap( TO,
6234                         mode64 ? unop(Iop_64to32, getIReg(rA_addr))
6235                                : getIReg(rA_addr),
6236                         mkU32( (UInt)simm16 ),
6237                         cia );
6238       if (TO == 4) {
6239          DIP("tweqi r%u,%d\n", rA_addr, (Int)simm16);
6240       } else {
6241          DIP("tw%di r%u,%d\n", TO, rA_addr, (Int)simm16);
6242       }
6243       break;
6244    case 0x02: // tdi
6245       if (!mode64)
6246          return False;
6247       uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia );
6248       if (TO == 4) {
6249          DIP("tdeqi r%u,%d\n", rA_addr, (Int)simm16);
6250       } else {
6251          DIP("td%di r%u,%d\n", TO, rA_addr, (Int)simm16);
6252       }
6253       break;
6254    default:
6255       return False;
6256    }
6257 
6258    if (uncond) {
6259       /* If the trap shows signs of being unconditional, don't
6260          continue decoding past it. */
6261       putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
6262       dres->jk_StopHere = Ijk_Boring;
6263       dres->whatNext    = Dis_StopHere;
6264    }
6265 
6266    return True;
6267 }
6268 
dis_trap(UInt theInstr,DisResult * dres)6269 static Bool dis_trap ( UInt theInstr,
6270                         /*OUT*/DisResult* dres )
6271 {
6272    /* X-Form */
6273    UInt   opc2    = ifieldOPClo10(theInstr);
6274    UChar  TO      = ifieldRegDS(theInstr);
6275    UChar  rA_addr = ifieldRegA(theInstr);
6276    UChar  rB_addr = ifieldRegB(theInstr);
6277    Addr64 cia     = guest_CIA_curr_instr;
6278    IRType ty      = mode64 ? Ity_I64 : Ity_I32;
6279    Bool   uncond  = False;
6280 
6281    if (ifieldBIT0(theInstr) != 0)
6282       return False;
6283 
6284    switch (opc2) {
6285    case 0x004: // tw  (Trap Word, PPC64 p540)
6286       uncond = do_trap( TO,
6287                         mode64 ? unop(Iop_64to32, getIReg(rA_addr))
6288                                : getIReg(rA_addr),
6289                         mode64 ? unop(Iop_64to32, getIReg(rB_addr))
6290                                : getIReg(rB_addr),
6291                         cia );
6292       if (TO == 4) {
6293          DIP("tweq r%u,r%u\n", rA_addr, rB_addr);
6294       } else {
6295          DIP("tw%d r%u,r%u\n", TO, rA_addr, rB_addr);
6296       }
6297       break;
6298    case 0x044: // td (Trap Doubleword, PPC64 p534)
6299       if (!mode64)
6300          return False;
6301       uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia );
6302       if (TO == 4) {
6303          DIP("tdeq r%u,r%u\n", rA_addr, rB_addr);
6304       } else {
6305          DIP("td%d r%u,r%u\n", TO, rA_addr, rB_addr);
6306       }
6307       break;
6308    default:
6309       return False;
6310    }
6311 
6312    if (uncond) {
6313       /* If the trap shows signs of being unconditional, don't
6314          continue decoding past it. */
6315       putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
6316       dres->jk_StopHere = Ijk_Boring;
6317       dres->whatNext    = Dis_StopHere;
6318    }
6319 
6320    return True;
6321 }
6322 
6323 
6324 /*
6325   System Linkage Instructions
6326 */
dis_syslink(UInt theInstr,const VexAbiInfo * abiinfo,DisResult * dres)6327 static Bool dis_syslink ( UInt theInstr,
6328                           const VexAbiInfo* abiinfo, DisResult* dres )
6329 {
6330    IRType ty = mode64 ? Ity_I64 : Ity_I32;
6331 
6332    if (theInstr != 0x44000002) {
6333       vex_printf("dis_syslink(ppc)(theInstr)\n");
6334       return False;
6335    }
6336 
6337    // sc  (System Call, PPC32 p504)
6338    DIP("sc\n");
6339 
6340    /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on Darwin
6341       Valgrind can back the guest up to this instruction if it needs
6342       to restart the syscall. */
6343    putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) );
6344 
6345    /* It's important that all ArchRegs carry their up-to-date value
6346       at this point.  So we declare an end-of-block here, which
6347       forces any TempRegs caching ArchRegs to be flushed. */
6348    putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
6349 
6350    dres->whatNext    = Dis_StopHere;
6351    dres->jk_StopHere = Ijk_Sys_syscall;
6352    return True;
6353 }
6354 
6355 
6356 /*
6357   Memory Synchronization Instructions
6358 
6359   Note on Reservations:
6360   We rely on the assumption that V will in fact only allow one thread at
6361   once to run.  In effect, a thread can make a reservation, but we don't
6362   check any stores it does.  Instead, the reservation is cancelled when
6363   the scheduler switches to another thread (run_thread_for_a_while()).
6364 */
dis_memsync(UInt theInstr)6365 static Bool dis_memsync ( UInt theInstr )
6366 {
6367    /* X-Form, XL-Form */
6368    UChar opc1    = ifieldOPC(theInstr);
6369    UInt  b11to25 = IFIELD(theInstr, 11, 15);
6370    UChar flag_L  = ifieldRegDS(theInstr);
6371    UInt  b11to20 = IFIELD(theInstr, 11, 10);
6372    UInt  M0      = IFIELD(theInstr, 11, 5);
6373    UChar rD_addr = ifieldRegDS(theInstr);
6374    UChar rS_addr = rD_addr;
6375    UChar rA_addr = ifieldRegA(theInstr);
6376    UChar rB_addr = ifieldRegB(theInstr);
6377    UInt  opc2    = ifieldOPClo10(theInstr);
6378    UChar b0      = ifieldBIT0(theInstr);
6379 
6380    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
6381    IRTemp EA     = newTemp(ty);
6382 
6383    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
6384 
6385    switch (opc1) {
6386    /* XL-Form */
6387    case 0x13:   // isync (Instruction Synchronize, PPC32 p432)
6388       if (opc2 != 0x096) {
6389          vex_printf("dis_memsync(ppc)(0x13,opc2)\n");
6390          return False;
6391       }
6392       if (b11to25 != 0 || b0 != 0) {
6393          vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n");
6394          return False;
6395       }
6396       DIP("isync\n");
6397       stmt( IRStmt_MBE(Imbe_Fence) );
6398       break;
6399 
6400    /* X-Form */
6401    case 0x1F:
6402       switch (opc2) {
6403       case 0x356: // eieio or mbar (Enforce In-Order Exec of I/O, PPC32 p394)
6404          if (M0 == 0) {
6405             if (b11to20 != 0 || b0 != 0) {
6406                vex_printf("dis_memsync(ppc)(eieio,b11to20|b0)\n");
6407                return False;
6408             }
6409             DIP("eieio\n");
6410          } else {
6411             if (b11to20 != 0 || b0 != 0) {
6412                vex_printf("dis_memsync(ppc)(mbar,b11to20|b0)\n");
6413                return False;
6414             }
6415             DIP("mbar %d\n", M0);
6416          }
6417          /* Insert a memory fence, just to be on the safe side. */
6418          stmt( IRStmt_MBE(Imbe_Fence) );
6419          break;
6420 
6421       case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458)
6422          IRTemp res;
6423          /* According to the PowerPC ISA version 2.05, b0 (called EH
6424             in the documentation) is merely a hint bit to the
6425             hardware, I think as to whether or not contention is
6426             likely.  So we can just ignore it. */
6427          DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
6428 
6429          // trap if misaligned
6430          gen_SIGBUS_if_misaligned( EA, 4 );
6431 
6432          // and actually do the load
6433          res = newTemp(Ity_I32);
6434          stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) );
6435 
6436          putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) );
6437          break;
6438       }
6439 
6440       case 0x034: { // lbarx (Load Word and Reserve Indexed)
6441          IRTemp res;
6442          /* According to the PowerPC ISA version 2.05, b0 (called EH
6443             in the documentation) is merely a hint bit to the
6444             hardware, I think as to whether or not contention is
6445             likely.  So we can just ignore it. */
6446          DIP("lbarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
6447 
6448          // and actually do the load
6449          res = newTemp(Ity_I8);
6450          stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) );
6451 
6452          putIReg( rD_addr, mkWidenFrom8(ty, mkexpr(res), False) );
6453          break;
6454      }
6455 
6456       case 0x074: { // lharx (Load Word and Reserve Indexed)
6457          IRTemp res;
6458          /* According to the PowerPC ISA version 2.05, b0 (called EH
6459             in the documentation) is merely a hint bit to the
6460             hardware, I think as to whether or not contention is
6461             likely.  So we can just ignore it. */
6462          DIP("lharx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
6463 
6464          // trap if misaligned
6465          gen_SIGBUS_if_misaligned( EA, 2 );
6466 
6467          // and actually do the load
6468          res = newTemp(Ity_I16);
6469          stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) );
6470 
6471          putIReg( rD_addr, mkWidenFrom16(ty, mkexpr(res), False) );
6472          break;
6473       }
6474 
6475       case 0x096: {
6476          // stwcx. (Store Word Conditional Indexed, PPC32 p532)
6477          // Note this has to handle stwcx. in both 32- and 64-bit modes,
6478          // so isn't quite as straightforward as it might otherwise be.
6479          IRTemp rS = newTemp(Ity_I32);
6480          IRTemp resSC;
6481          if (b0 != 1) {
6482             vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
6483             return False;
6484          }
6485          DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6486 
6487          // trap if misaligned
6488          gen_SIGBUS_if_misaligned( EA, 4 );
6489 
6490          // Get the data to be stored, and narrow to 32 bits if necessary
6491          assign( rS, mkNarrowTo32(ty, getIReg(rS_addr)) );
6492 
6493          // Do the store, and get success/failure bit into resSC
6494          resSC = newTemp(Ity_I1);
6495          stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
6496 
6497          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
6498          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
6499          putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
6500          putCR0(0, getXER_SO());
6501 
6502          /* Note:
6503             If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
6504             whether rS is stored is dependent on that value. */
6505          /* So I guess we can just ignore this case? */
6506          break;
6507       }
6508 
6509       case 0x2B6: {
6510          // stbcx. (Store Byte Conditional Indexed)
6511          // Note this has to handle stbcx. in both 32- and 64-bit modes,
6512          // so isn't quite as straightforward as it might otherwise be.
6513          IRTemp rS = newTemp(Ity_I8);
6514          IRTemp resSC;
6515          if (b0 != 1) {
6516             vex_printf("dis_memsync(ppc)(stbcx.,b0)\n");
6517             return False;
6518          }
6519          DIP("stbcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6520 
6521          // Get the data to be stored, and narrow to 32 bits if necessary
6522          assign( rS, mkNarrowTo8(ty, getIReg(rS_addr)) );
6523 
6524          // Do the store, and get success/failure bit into resSC
6525          resSC = newTemp(Ity_I1);
6526          stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
6527 
6528          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
6529          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
6530          putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
6531          putCR0(0, getXER_SO());
6532 
6533          /* Note:
6534             If resaddr != lbarx_resaddr, CR0[EQ] is undefined, and
6535             whether rS is stored is dependent on that value. */
6536          /* So I guess we can just ignore this case? */
6537          break;
6538       }
6539 
6540       case 0x2D6: {
6541          // sthcx. (Store Word Conditional Indexed, PPC32 p532)
6542          // Note this has to handle sthcx. in both 32- and 64-bit modes,
6543          // so isn't quite as straightforward as it might otherwise be.
6544          IRTemp rS = newTemp(Ity_I16);
6545          IRTemp resSC;
6546          if (b0 != 1) {
6547             vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
6548             return False;
6549          }
6550          DIP("sthcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6551 
6552          // trap if misaligned
6553          gen_SIGBUS_if_misaligned( EA, 2 );
6554 
6555          // Get the data to be stored, and narrow to 16 bits if necessary
6556          assign( rS, mkNarrowTo16(ty, getIReg(rS_addr)) );
6557 
6558          // Do the store, and get success/failure bit into resSC
6559          resSC = newTemp(Ity_I1);
6560          stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
6561 
6562          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
6563          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
6564          putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
6565          putCR0(0, getXER_SO());
6566 
6567          /* Note:
6568             If resaddr != lharx_resaddr, CR0[EQ] is undefined, and
6569             whether rS is stored is dependent on that value. */
6570          /* So I guess we can just ignore this case? */
6571          break;
6572       }
6573 
6574       case 0x256: // sync (Synchronize, PPC32 p543),
6575                   // also lwsync (L==1), ptesync (L==2)
6576          /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html
6577 
6578             The PowerPC architecture used in IBM chips has expanded
6579             the sync instruction into two variants: lightweight sync
6580             and heavyweight sync.  The original sync instruction is
6581             the new heavyweight sync and lightweight sync is a strict
6582             subset of the heavyweight sync functionality. This allows
6583             the programmer to specify a less expensive operation on
6584             high-end systems when the full sync functionality is not
6585             necessary.
6586 
6587             The basic "sync" mnemonic now utilizes an operand. "sync"
6588             without an operand now becomes a extended mnemonic for
6589             heavyweight sync.  Processors without the lwsync
6590             instruction will not decode the L field and will perform a
6591             heavyweight sync.  Everything is backward compatible.
6592 
6593             sync    =       sync 0
6594             lwsync  =       sync 1
6595             ptesync =       sync 2    *** TODO - not implemented ***
6596          */
6597          if (b11to20 != 0 || b0 != 0) {
6598             vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n");
6599             return False;
6600          }
6601          if (flag_L != 0/*sync*/ && flag_L != 1/*lwsync*/) {
6602             vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n");
6603             return False;
6604          }
6605          DIP("%ssync\n", flag_L == 1 ? "lw" : "");
6606          /* Insert a memory fence.  It's sometimes important that these
6607             are carried through to the generated code. */
6608          stmt( IRStmt_MBE(Imbe_Fence) );
6609          break;
6610 
6611       /* 64bit Memsync */
6612       case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473)
6613          IRTemp res;
6614          /* According to the PowerPC ISA version 2.05, b0 (called EH
6615             in the documentation) is merely a hint bit to the
6616             hardware, I think as to whether or not contention is
6617             likely.  So we can just ignore it. */
6618          if (!mode64)
6619             return False;
6620          DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
6621 
6622          // trap if misaligned
6623          gen_SIGBUS_if_misaligned( EA, 8 );
6624 
6625          // and actually do the load
6626          res = newTemp(Ity_I64);
6627          stmt( stmt_load( res, mkexpr(EA), NULL/*this is a load*/) );
6628 
6629          putIReg( rD_addr, mkexpr(res) );
6630          break;
6631       }
6632 
6633       case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581)
6634          // A marginally simplified version of the stwcx. case
6635          IRTemp rS = newTemp(Ity_I64);
6636          IRTemp resSC;
6637          if (b0 != 1) {
6638             vex_printf("dis_memsync(ppc)(stdcx.,b0)\n");
6639             return False;
6640          }
6641          if (!mode64)
6642             return False;
6643          DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6644 
6645          // trap if misaligned
6646          gen_SIGBUS_if_misaligned( EA, 8 );
6647 
6648          // Get the data to be stored
6649          assign( rS, getIReg(rS_addr) );
6650 
6651          // Do the store, and get success/failure bit into resSC
6652          resSC = newTemp(Ity_I1);
6653          stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
6654 
6655          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
6656          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
6657          putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
6658          putCR0(0, getXER_SO());
6659 
6660          /* Note:
6661             If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
6662             whether rS is stored is dependent on that value. */
6663          /* So I guess we can just ignore this case? */
6664          break;
6665       }
6666 
6667       /* 128bit Memsync */
6668       case 0x114: { // lqarx (Load QuadWord and Reserve Indexed)
6669          IRTemp res_hi = newTemp(ty);
6670          IRTemp res_lo = newTemp(ty);
6671 
6672          /* According to the PowerPC ISA version 2.07, b0 (called EH
6673             in the documentation) is merely a hint bit to the
6674             hardware, I think as to whether or not contention is
6675             likely.  So we can just ignore it. */
6676          DIP("lqarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
6677 
6678          // trap if misaligned
6679          gen_SIGBUS_if_misaligned( EA, 16 );
6680 
6681          // and actually do the load
6682          if (mode64) {
6683             if (host_endness == VexEndnessBE) {
6684                stmt( stmt_load( res_hi,
6685                                 mkexpr(EA), NULL/*this is a load*/) );
6686                stmt( stmt_load( res_lo,
6687                                 binop(Iop_Add64, mkexpr(EA), mkU64(8) ),
6688                                 NULL/*this is a load*/) );
6689 	    } else {
6690                stmt( stmt_load( res_lo,
6691                                 mkexpr(EA), NULL/*this is a load*/) );
6692                stmt( stmt_load( res_hi,
6693                                 binop(Iop_Add64, mkexpr(EA), mkU64(8) ),
6694                                 NULL/*this is a load*/) );
6695             }
6696          } else {
6697             stmt( stmt_load( res_hi,
6698                              binop( Iop_Add32, mkexpr(EA), mkU32(4) ),
6699                              NULL/*this is a load*/) );
6700             stmt( stmt_load( res_lo,
6701                              binop( Iop_Add32, mkexpr(EA), mkU32(12) ),
6702                              NULL/*this is a load*/) );
6703          }
6704          putIReg( rD_addr,   mkexpr(res_hi) );
6705          putIReg( rD_addr+1, mkexpr(res_lo) );
6706          break;
6707       }
6708 
6709       case 0x0B6: { // stqcx. (Store QuadWord Condition Indexd, PPC64)
6710          // A marginally simplified version of the stwcx. case
6711          IRTemp rS_hi = newTemp(ty);
6712          IRTemp rS_lo = newTemp(ty);
6713          IRTemp resSC;
6714          if (b0 != 1) {
6715             vex_printf("dis_memsync(ppc)(stqcx.,b0)\n");
6716             return False;
6717          }
6718 
6719          DIP("stqcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6720 
6721          // trap if misaligned
6722          gen_SIGBUS_if_misaligned( EA, 16 );
6723          // Get the data to be stored
6724          assign( rS_hi, getIReg(rS_addr) );
6725          assign( rS_lo, getIReg(rS_addr+1) );
6726 
6727          // Do the store, and get success/failure bit into resSC
6728          resSC = newTemp(Ity_I1);
6729 
6730          if (mode64) {
6731             if (host_endness == VexEndnessBE) {
6732                stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_hi) ) );
6733                store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ),
6734                       mkexpr(rS_lo) );
6735 	    } else {
6736                stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_lo) ) );
6737                store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ),
6738                       mkexpr(rS_hi) );
6739 	    }
6740          } else {
6741             stmt( stmt_load( resSC, binop( Iop_Add32,
6742                                            mkexpr(EA),
6743                                            mkU32(4) ),
6744                                            mkexpr(rS_hi) ) );
6745             store( binop(Iop_Add32, mkexpr(EA), mkU32(12) ), mkexpr(rS_lo) );
6746          }
6747 
6748          // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
6749          // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
6750          putCR321(0, binop( Iop_Shl8,
6751                             unop(Iop_1Uto8, mkexpr(resSC) ),
6752                             mkU8(1)));
6753          putCR0(0, getXER_SO());
6754          break;
6755       }
6756 
6757       default:
6758          vex_printf("dis_memsync(ppc)(opc2)\n");
6759          return False;
6760       }
6761       break;
6762 
6763    default:
6764       vex_printf("dis_memsync(ppc)(opc1)\n");
6765       return False;
6766    }
6767    return True;
6768 }
6769 
6770 
6771 
6772 /*
6773   Integer Shift Instructions
6774 */
dis_int_shift(UInt theInstr)6775 static Bool dis_int_shift ( UInt theInstr )
6776 {
6777    /* X-Form, XS-Form */
6778    UChar opc1    = ifieldOPC(theInstr);
6779    UChar rS_addr = ifieldRegDS(theInstr);
6780    UChar rA_addr = ifieldRegA(theInstr);
6781    UChar rB_addr = ifieldRegB(theInstr);
6782    UChar sh_imm  = rB_addr;
6783    UInt  opc2    = ifieldOPClo10(theInstr);
6784    UChar b1      = ifieldBIT1(theInstr);
6785    UChar flag_rC = ifieldBIT0(theInstr);
6786 
6787    IRType  ty         = mode64 ? Ity_I64 : Ity_I32;
6788    IRTemp  rA         = newTemp(ty);
6789    IRTemp  rS         = newTemp(ty);
6790    IRTemp  rB         = newTemp(ty);
6791    IRTemp  outofrange = newTemp(Ity_I1);
6792    IRTemp  rS_lo32    = newTemp(Ity_I32);
6793    IRTemp  rB_lo32    = newTemp(Ity_I32);
6794    IRExpr* e_tmp;
6795 
6796    assign( rS, getIReg(rS_addr) );
6797    assign( rB, getIReg(rB_addr) );
6798    assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) );
6799    assign( rB_lo32, mkNarrowTo32(ty, mkexpr(rB)) );
6800 
6801    if (opc1 == 0x1F) {
6802       switch (opc2) {
6803       case 0x018: { // slw (Shift Left Word, PPC32 p505)
6804          DIP("slw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
6805              rA_addr, rS_addr, rB_addr);
6806          /* rA = rS << rB */
6807          /* ppc32 semantics are:
6808             slw(x,y) = (x << (y & 31))         -- primary result
6809                        & ~((y << 26) >>s 31)   -- make result 0
6810                                                   for y in 32 .. 63
6811          */
6812          e_tmp =
6813             binop( Iop_And32,
6814                binop( Iop_Shl32,
6815                       mkexpr(rS_lo32),
6816                       unop( Iop_32to8,
6817                             binop(Iop_And32,
6818                                   mkexpr(rB_lo32), mkU32(31)))),
6819                unop( Iop_Not32,
6820                      binop( Iop_Sar32,
6821                             binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)),
6822                             mkU8(31))) );
6823          assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
6824          break;
6825       }
6826 
6827       case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506)
6828          IRTemp sh_amt = newTemp(Ity_I32);
6829          DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
6830              rA_addr, rS_addr, rB_addr);
6831          /* JRS: my reading of the (poorly worded) PPC32 doc p506 is:
6832             amt = rB & 63
6833             rA = Sar32( rS, amt > 31 ? 31 : amt )
6834             XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi)
6835          */
6836          assign( sh_amt, binop(Iop_And32, mkU32(0x3F),
6837                                           mkexpr(rB_lo32)) );
6838          assign( outofrange,
6839                  binop(Iop_CmpLT32U, mkU32(31), mkexpr(sh_amt)) );
6840          e_tmp = binop( Iop_Sar32,
6841                         mkexpr(rS_lo32),
6842                         unop( Iop_32to8,
6843                               IRExpr_ITE( mkexpr(outofrange),
6844                                           mkU32(31),
6845                                           mkexpr(sh_amt)) ) );
6846          assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) );
6847 
6848          set_XER_CA( ty, PPCG_FLAG_OP_SRAW,
6849                      mkexpr(rA),
6850                      mkWidenFrom32(ty, mkexpr(rS_lo32), True),
6851                      mkWidenFrom32(ty, mkexpr(sh_amt), True ),
6852                      mkWidenFrom32(ty, getXER_CA32(), True) );
6853          break;
6854       }
6855 
6856       case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507)
6857          DIP("srawi%s r%u,r%u,%d\n", flag_rC ? ".":"",
6858              rA_addr, rS_addr, sh_imm);
6859          vassert(sh_imm < 32);
6860          if (mode64) {
6861             assign( rA, binop(Iop_Sar64,
6862                               binop(Iop_Shl64, getIReg(rS_addr),
6863                                                mkU8(32)),
6864                               mkU8(32 + sh_imm)) );
6865          } else {
6866             assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32),
6867                                          mkU8(sh_imm)) );
6868          }
6869 
6870          set_XER_CA( ty, PPCG_FLAG_OP_SRAWI,
6871                      mkexpr(rA),
6872                      mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True),
6873                      mkSzImm(ty, sh_imm),
6874                      mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
6875          break;
6876 
6877       case 0x218: // srw (Shift Right Word, PPC32 p508)
6878          DIP("srw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
6879              rA_addr, rS_addr, rB_addr);
6880          /* rA = rS >>u rB */
6881          /* ppc32 semantics are:
6882             srw(x,y) = (x >>u (y & 31))        -- primary result
6883                        & ~((y << 26) >>s 31)   -- make result 0
6884                                                   for y in 32 .. 63
6885          */
6886          e_tmp =
6887             binop(
6888                Iop_And32,
6889                binop( Iop_Shr32,
6890                       mkexpr(rS_lo32),
6891                       unop( Iop_32to8,
6892                             binop(Iop_And32, mkexpr(rB_lo32),
6893                                              mkU32(31)))),
6894                unop( Iop_Not32,
6895                      binop( Iop_Sar32,
6896                             binop(Iop_Shl32, mkexpr(rB_lo32),
6897                                              mkU8(26)),
6898                             mkU8(31))));
6899          assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
6900          break;
6901 
6902 
6903       /* 64bit Shifts */
6904       case 0x01B: // sld (Shift Left DWord, PPC64 p568)
6905          DIP("sld%s r%u,r%u,r%u\n",
6906              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6907          /* rA = rS << rB */
6908          /* ppc64 semantics are:
6909             slw(x,y) = (x << (y & 63))         -- primary result
6910                        & ~((y << 57) >>s 63)   -- make result 0
6911                                                   for y in 64 ..
6912          */
6913          assign( rA,
6914             binop(
6915                Iop_And64,
6916                binop( Iop_Shl64,
6917                       mkexpr(rS),
6918                       unop( Iop_64to8,
6919                             binop(Iop_And64, mkexpr(rB), mkU64(63)))),
6920                unop( Iop_Not64,
6921                      binop( Iop_Sar64,
6922                             binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
6923                             mkU8(63)))) );
6924          break;
6925 
6926       case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570)
6927          IRTemp sh_amt = newTemp(Ity_I64);
6928          DIP("srad%s r%u,r%u,r%u\n",
6929              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6930          /* amt = rB & 127
6931             rA = Sar64( rS, amt > 63 ? 63 : amt )
6932             XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi)
6933          */
6934          assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) );
6935          assign( outofrange,
6936                  binop(Iop_CmpLT64U, mkU64(63), mkexpr(sh_amt)) );
6937          assign( rA,
6938                  binop( Iop_Sar64,
6939                         mkexpr(rS),
6940                         unop( Iop_64to8,
6941                               IRExpr_ITE( mkexpr(outofrange),
6942                                           mkU64(63),
6943                                           mkexpr(sh_amt)) ))
6944                );
6945          set_XER_CA( ty, PPCG_FLAG_OP_SRAD,
6946                      mkexpr(rA), mkexpr(rS), mkexpr(sh_amt),
6947                      mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
6948          break;
6949       }
6950 
6951       case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571)
6952          sh_imm |= b1<<5;
6953          vassert(sh_imm < 64);
6954          DIP("sradi%s r%u,r%u,%u\n",
6955              flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
6956          assign( rA, binop(Iop_Sar64, getIReg(rS_addr), mkU8(sh_imm)) );
6957 
6958          set_XER_CA( ty, PPCG_FLAG_OP_SRADI,
6959                      mkexpr(rA),
6960                      getIReg(rS_addr),
6961                      mkU64(sh_imm),
6962                      mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
6963          break;
6964 
6965       case 0x21B: // srd (Shift Right DWord, PPC64 p574)
6966          DIP("srd%s r%u,r%u,r%u\n",
6967              flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6968          /* rA = rS >>u rB */
6969          /* ppc semantics are:
6970             srw(x,y) = (x >>u (y & 63))        -- primary result
6971                        & ~((y << 57) >>s 63)   -- make result 0
6972                                                   for y in 64 .. 127
6973          */
6974          assign( rA,
6975             binop(
6976                Iop_And64,
6977                binop( Iop_Shr64,
6978                       mkexpr(rS),
6979                       unop( Iop_64to8,
6980                             binop(Iop_And64, mkexpr(rB), mkU64(63)))),
6981                unop( Iop_Not64,
6982                      binop( Iop_Sar64,
6983                             binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
6984                             mkU8(63)))) );
6985          break;
6986 
6987       default:
6988          vex_printf("dis_int_shift(ppc)(opc2)\n");
6989          return False;
6990       }
6991    } else {
6992       vex_printf("dis_int_shift(ppc)(opc1)\n");
6993       return False;
6994    }
6995 
6996    putIReg( rA_addr, mkexpr(rA) );
6997 
6998    if (flag_rC) {
6999       set_CR0( mkexpr(rA) );
7000    }
7001    return True;
7002 }
7003 
7004 
7005 
7006 /*
7007   Integer Load/Store Reverse Instructions
7008 */
7009 /* Generates code to swap the byte order in an Ity_I32. */
gen_byterev32(IRTemp t)7010 static IRExpr* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t )
7011 {
7012    vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
7013    return
7014       binop(Iop_Or32,
7015          binop(Iop_Shl32, mkexpr(t), mkU8(24)),
7016       binop(Iop_Or32,
7017          binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
7018                           mkU32(0x00FF0000)),
7019       binop(Iop_Or32,
7020          binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
7021                           mkU32(0x0000FF00)),
7022          binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(24)),
7023                           mkU32(0x000000FF) )
7024       )));
7025 }
7026 
7027 /* Generates code to swap the byte order in the lower half of an Ity_I32,
7028    and zeroes the upper half. */
gen_byterev16(IRTemp t)7029 static IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t )
7030 {
7031    vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
7032    return
7033       binop(Iop_Or32,
7034          binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
7035                           mkU32(0x0000FF00)),
7036          binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
7037                           mkU32(0x000000FF))
7038       );
7039 }
7040 
dis_int_ldst_rev(UInt theInstr)7041 static Bool dis_int_ldst_rev ( UInt theInstr )
7042 {
7043    /* X-Form */
7044    UChar opc1    = ifieldOPC(theInstr);
7045    UChar rD_addr = ifieldRegDS(theInstr);
7046    UChar rS_addr = rD_addr;
7047    UChar rA_addr = ifieldRegA(theInstr);
7048    UChar rB_addr = ifieldRegB(theInstr);
7049    UInt  opc2    = ifieldOPClo10(theInstr);
7050    UChar b0      = ifieldBIT0(theInstr);
7051 
7052    IRType ty = mode64 ? Ity_I64 : Ity_I32;
7053    IRTemp EA = newTemp(ty);
7054    IRTemp w1 = newTemp(Ity_I32);
7055    IRTemp w2 = newTemp(Ity_I32);
7056 
7057    if (opc1 != 0x1F || b0 != 0) {
7058       vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n");
7059       return False;
7060    }
7061 
7062    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
7063 
7064    switch (opc2) {
7065 
7066       case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449)
7067          DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7068          assign( w1, unop(Iop_16Uto32, load(Ity_I16, mkexpr(EA))) );
7069          assign( w2, gen_byterev16(w1) );
7070          putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
7071                                          /* Signed */False) );
7072          break;
7073 
7074       case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459)
7075          DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7076          assign( w1, load(Ity_I32, mkexpr(EA)) );
7077          assign( w2, gen_byterev32(w1) );
7078          putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
7079                                          /* Signed */False) );
7080          break;
7081 
7082       case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed)
7083       {
7084          IRExpr * nextAddr;
7085          IRTemp w3 = newTemp( Ity_I32 );
7086          IRTemp w4 = newTemp( Ity_I32 );
7087          DIP("ldbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
7088          assign( w1, load( Ity_I32, mkexpr( EA ) ) );
7089          assign( w2, gen_byterev32( w1 ) );
7090          nextAddr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
7091                            ty == Ity_I64 ? mkU64( 4 ) : mkU32( 4 ) );
7092          assign( w3, load( Ity_I32, nextAddr ) );
7093          assign( w4, gen_byterev32( w3 ) );
7094          if (host_endness == VexEndnessLE)
7095             putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w2 ), mkexpr( w4 ) ) );
7096          else
7097             putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) );
7098          break;
7099       }
7100 
7101       case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523)
7102          DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7103          assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
7104          store( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) );
7105          break;
7106 
7107       case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531)
7108          DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7109          assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
7110          store( mkexpr(EA), gen_byterev32(w1) );
7111          break;
7112 
7113       case 0x294: // stdbrx (Store Doubleword Byte-Reverse Indexed)
7114       {
7115          IRTemp lo = newTemp(Ity_I32);
7116          IRTemp hi = newTemp(Ity_I32);
7117          IRTemp rS = newTemp(Ity_I64);
7118          assign( rS, getIReg( rS_addr ) );
7119          DIP("stdbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7120          assign(lo, unop(Iop_64HIto32, mkexpr(rS)));
7121          assign(hi, unop(Iop_64to32, mkexpr(rS)));
7122          store( mkexpr( EA ),
7123                 binop( Iop_32HLto64, gen_byterev32( hi ),
7124                        gen_byterev32( lo ) ) );
7125          break;
7126       }
7127 
7128       default:
7129          vex_printf("dis_int_ldst_rev(ppc)(opc2)\n");
7130          return False;
7131    }
7132    return True;
7133 }
7134 
7135 
7136 
7137 /*
7138   Processor Control Instructions
7139 */
dis_proc_ctl(const VexAbiInfo * vbi,UInt theInstr)7140 static Bool dis_proc_ctl ( const VexAbiInfo* vbi, UInt theInstr )
7141 {
7142    UChar opc1     = ifieldOPC(theInstr);
7143 
7144    /* X-Form */
7145    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
7146    UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
7147    UChar rD_addr  = ifieldRegDS(theInstr);
7148    UInt  b11to20  = IFIELD( theInstr, 11, 10 );
7149 
7150    /* XFX-Form */
7151    UChar rS_addr  = rD_addr;
7152    UInt  SPR      = b11to20;
7153    UInt  TBR      = b11to20;
7154    UChar b20      = toUChar( IFIELD( theInstr, 20, 1 ) );
7155    UInt  CRM      = IFIELD( theInstr, 12, 8 );
7156    UChar b11      = toUChar( IFIELD( theInstr, 11, 1 ) );
7157 
7158    UInt  opc2     = ifieldOPClo10(theInstr);
7159    UChar b0       = ifieldBIT0(theInstr);
7160 
7161    IRType ty = mode64 ? Ity_I64 : Ity_I32;
7162    IRTemp rS = newTemp(ty);
7163    assign( rS, getIReg(rS_addr) );
7164 
7165    /* Reorder SPR field as per PPC32 p470 */
7166    SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F);
7167    /* Reorder TBR field as per PPC32 p475 */
7168    TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31);
7169 
7170    /* b0 = 0, inst is treated as floating point inst for reservation purposes
7171     * b0 = 1, inst is treated as vector inst for reservation purposes
7172     */
7173    if (opc1 != 0x1F) {
7174       vex_printf("dis_proc_ctl(ppc)(opc1|b%d)\n", b0);
7175       return False;
7176    }
7177 
7178    switch (opc2) {
7179    /* X-Form */
7180    case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466)
7181       if (b21to22 != 0 || b11to20 != 0) {
7182          vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n");
7183          return False;
7184       }
7185       DIP("mcrxr crf%d\n", crfD);
7186       /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */
7187       putGST_field( PPC_GST_CR,
7188                     getGST_field( PPC_GST_XER, 7 ),
7189                     crfD );
7190 
7191       // Clear XER[0-3]
7192       putXER_SO( mkU8(0) );
7193       putXER_OV( mkU8(0) );
7194       putXER_CA( mkU8(0) );
7195       break;
7196    }
7197 
7198    case 0x013:
7199       // b11to20==0:      mfcr (Move from Cond Register, PPC32 p467)
7200       // b20==1 & b11==0: mfocrf (Move from One CR Field)
7201       // However it seems that the 'mfcr' behaviour is an acceptable
7202       // implementation of mfocr (from the 2.02 arch spec)
7203       if (b11to20 == 0) {
7204          DIP("mfcr r%u\n", rD_addr);
7205          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
7206                                          /* Signed */False) );
7207          break;
7208       }
7209       if (b20 == 1 && b11 == 0) {
7210          DIP("mfocrf r%u,%u\n", rD_addr, CRM);
7211          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
7212                                          /* Signed */False) );
7213          break;
7214       }
7215       /* not decodable */
7216       return False;
7217 
7218    /* XFX-Form */
7219    case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470)
7220 
7221       switch (SPR) {  // Choose a register...
7222       case 0x1:
7223          DIP("mfxer r%u\n", rD_addr);
7224          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ),
7225                                          /* Signed */False) );
7226          break;
7227       case 0x8:
7228          DIP("mflr r%u\n", rD_addr);
7229          putIReg( rD_addr, getGST( PPC_GST_LR ) );
7230          break;
7231       case 0x9:
7232          DIP("mfctr r%u\n", rD_addr);
7233          putIReg( rD_addr, getGST( PPC_GST_CTR ) );
7234          break;
7235       case 0x80:  // 128
7236          DIP("mfspr r%u (TFHAR)\n", rD_addr);
7237          putIReg( rD_addr, getGST( PPC_GST_TFHAR) );
7238          break;
7239       case 0x81:  // 129
7240          DIP("mfspr r%u (TFIAR)\n", rD_addr);
7241          putIReg( rD_addr, getGST( PPC_GST_TFIAR) );
7242          break;
7243       case 0x82:  // 130
7244          DIP("mfspr r%u (TEXASR)\n", rD_addr);
7245          putIReg( rD_addr, getGST( PPC_GST_TEXASR) );
7246          break;
7247       case 0x83:  // 131
7248          DIP("mfspr r%u (TEXASRU)\n", rD_addr);
7249          putIReg( rD_addr, getGST( PPC_GST_TEXASRU) );
7250          break;
7251       case 0x9F:  // 159
7252          DIP("mfspr r%u (PSPB)\n", rD_addr);
7253          putIReg( rD_addr, getGST( PPC_GST_PSPB) );
7254          break;
7255       case 0x380:  // 896
7256          DIP("mfspr r%u (PPR)\n", rD_addr);
7257          putIReg( rD_addr, getGST( PPC_GST_PPR) );
7258          break;
7259       case 0x382:  // 898
7260          DIP("mfspr r%u (PPR)32\n", rD_addr);
7261          putIReg( rD_addr, getGST( PPC_GST_PPR32) );
7262          break;
7263       case 0x100:
7264          DIP("mfvrsave r%u\n", rD_addr);
7265          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ),
7266                                          /* Signed */False) );
7267          break;
7268 
7269       case 0x103:
7270          DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr);
7271          putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) );
7272          break;
7273 
7274       /* Even a lowly PPC7400 can run the associated helper, so no
7275          obvious need for feature testing at this point. */
7276       case 268 /* 0x10C */:
7277       case 269 /* 0x10D */: {
7278          UInt     arg  = SPR==268 ? 0 : 1;
7279          IRTemp   val  = newTemp(Ity_I32);
7280          IRExpr** args = mkIRExprVec_1( mkU32(arg) );
7281          IRDirty* d    = unsafeIRDirty_1_N(
7282                             val,
7283                             0/*regparms*/,
7284                             "ppc32g_dirtyhelper_MFSPR_268_269",
7285                             fnptr_to_fnentry
7286                                (vbi, &ppc32g_dirtyhelper_MFSPR_268_269),
7287                             args
7288                          );
7289          /* execute the dirty call, dumping the result in val. */
7290          stmt( IRStmt_Dirty(d) );
7291          putIReg( rD_addr,
7292                   mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
7293          DIP("mfspr r%u,%u", rD_addr, SPR);
7294          break;
7295       }
7296 
7297       /* Again, runs natively on PPC7400 (7447, really).  Not
7298          bothering with a feature test. */
7299       case 287: /* 0x11F */ {
7300          IRTemp   val  = newTemp(Ity_I32);
7301          IRExpr** args = mkIRExprVec_0();
7302          IRDirty* d    = unsafeIRDirty_1_N(
7303                             val,
7304                             0/*regparms*/,
7305                             "ppc32g_dirtyhelper_MFSPR_287",
7306                             fnptr_to_fnentry
7307                                (vbi, &ppc32g_dirtyhelper_MFSPR_287),
7308                             args
7309                          );
7310          /* execute the dirty call, dumping the result in val. */
7311          stmt( IRStmt_Dirty(d) );
7312          putIReg( rD_addr,
7313                   mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
7314          DIP("mfspr r%u,%u", rD_addr, SPR);
7315          break;
7316       }
7317 
7318       default:
7319          vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR);
7320          return False;
7321       }
7322       break;
7323 
7324    case 0x173: { // mftb (Move from Time Base, PPC32 p475)
7325       IRTemp   val  = newTemp(Ity_I64);
7326       IRExpr** args = mkIRExprVec_0();
7327       IRDirty* d    = unsafeIRDirty_1_N(
7328                               val,
7329                               0/*regparms*/,
7330                               "ppcg_dirtyhelper_MFTB",
7331                               fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB),
7332                               args );
7333       /* execute the dirty call, dumping the result in val. */
7334       stmt( IRStmt_Dirty(d) );
7335 
7336       switch (TBR) {
7337       case 269:
7338          DIP("mftbu r%u", rD_addr);
7339          putIReg( rD_addr,
7340                   mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)),
7341                                 /* Signed */False) );
7342          break;
7343       case 268:
7344          DIP("mftb r%u", rD_addr);
7345          putIReg( rD_addr, (mode64) ? mkexpr(val) :
7346                                       unop(Iop_64to32, mkexpr(val)) );
7347          break;
7348       default:
7349          return False; /* illegal instruction */
7350       }
7351       break;
7352    }
7353 
7354    case 0x090: {
7355       // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477)
7356       // b20==1: mtocrf (Move to One Cond Reg Field)
7357       Int   cr;
7358       UChar shft;
7359       if (b11 != 0)
7360          return False;
7361       if (b20 == 1) {
7362          /* ppc64 v2.02 spec says mtocrf gives undefined outcome if >
7363             1 field is written.  It seems more robust to decline to
7364             decode the insn if so. */
7365          switch (CRM) {
7366             case 0x01: case 0x02: case 0x04: case 0x08:
7367             case 0x10: case 0x20: case 0x40: case 0x80:
7368                break;
7369             default:
7370                return False;
7371          }
7372       }
7373       DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf",
7374                            CRM, rS_addr);
7375       /* Write to each field specified by CRM */
7376       for (cr = 0; cr < 8; cr++) {
7377          if ((CRM & (1 << (7-cr))) == 0)
7378             continue;
7379          shft = 4*(7-cr);
7380          putGST_field( PPC_GST_CR,
7381                        binop(Iop_Shr32,
7382                              mkNarrowTo32(ty, mkexpr(rS)),
7383                              mkU8(shft)), cr );
7384       }
7385       break;
7386    }
7387 
7388    case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483)
7389 
7390       switch (SPR) {  // Choose a register...
7391       case 0x1:
7392          DIP("mtxer r%u\n", rS_addr);
7393          putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) );
7394          break;
7395       case 0x8:
7396          DIP("mtlr r%u\n", rS_addr);
7397          putGST( PPC_GST_LR, mkexpr(rS) );
7398          break;
7399       case 0x9:
7400          DIP("mtctr r%u\n", rS_addr);
7401          putGST( PPC_GST_CTR, mkexpr(rS) );
7402          break;
7403       case 0x100:
7404          DIP("mtvrsave r%u\n", rS_addr);
7405          putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) );
7406          break;
7407       case 0x80:  // 128
7408          DIP("mtspr r%u (TFHAR)\n", rS_addr);
7409          putGST( PPC_GST_TFHAR, mkexpr(rS) );
7410          break;
7411       case 0x81:  // 129
7412          DIP("mtspr r%u (TFIAR)\n", rS_addr);
7413          putGST( PPC_GST_TFIAR, mkexpr(rS) );
7414          break;
7415       case 0x82:  // 130
7416          DIP("mtspr r%u (TEXASR)\n", rS_addr);
7417          putGST( PPC_GST_TEXASR, mkexpr(rS) );
7418          break;
7419       case 0x9F:  // 159
7420          DIP("mtspr r%u (PSPB)\n", rS_addr);
7421          putGST( PPC_GST_PSPB, mkexpr(rS) );
7422          break;
7423       case 0x380:  // 896
7424          DIP("mtspr r%u (PPR)\n", rS_addr);
7425          putGST( PPC_GST_PPR, mkexpr(rS) );
7426          break;
7427       case 0x382:  // 898
7428          DIP("mtspr r%u (PPR32)\n", rS_addr);
7429          putGST( PPC_GST_PPR32, mkexpr(rS) );
7430          break;
7431       default:
7432          vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR);
7433          return False;
7434       }
7435       break;
7436 
7437    case 0x33:                // mfvsrd
7438    {
7439       UChar XS = ifieldRegXS( theInstr );
7440       UChar rA_addr = ifieldRegA(theInstr);
7441       IRExpr * high64;
7442       IRTemp vS = newTemp( Ity_V128 );
7443       DIP("mfvsrd r%u,vsr%d\n", rA_addr, XS);
7444 
7445       /*  XS = SX || S
7446        *  For SX=0, mfvsrd is treated as a Floating-Point
7447        *            instruction in terms of resource availability.
7448        *  For SX=1, mfvsrd is treated as a Vector instruction in
7449        *            terms of resource availability.
7450        * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
7451        */
7452       assign( vS, getVSReg( XS ) );
7453       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
7454       putIReg( rA_addr, (mode64) ? high64 :
7455       unop( Iop_64to32, high64 ) );
7456       break;
7457    }
7458 
7459    case 0x73:                // mfvsrwz
7460    {
7461       UChar XS = ifieldRegXS( theInstr );
7462       UChar rA_addr = ifieldRegA(theInstr);
7463       IRExpr * high64;
7464       IRTemp vS = newTemp( Ity_V128 );
7465       DIP("mfvsrwz r%u,vsr%d\n", rA_addr, XS);
7466       /*  XS = SX || S
7467        *  For SX=0, mfvsrwz is treated as a Floating-Point
7468        *            instruction in terms of resource availability.
7469        *  For SX=1, mfvsrwz is treated as a Vector instruction in
7470        *            terms of resource availability.
7471        * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
7472        */
7473 
7474       assign( vS, getVSReg( XS ) );
7475       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
7476       /* move value to the destination setting the upper 32-bits to zero */
7477       putIReg( rA_addr, (mode64) ?
7478                                   binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) :
7479                                   unop(  Iop_64to32,
7480                                          binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) ) );
7481       break;
7482    }
7483 
7484    case 0xB3:                // mtvsrd
7485    {
7486       UChar XT = ifieldRegXT( theInstr );
7487       UChar rA_addr = ifieldRegA(theInstr);
7488       IRTemp rA = newTemp(ty);
7489       DIP("mtvsrd vsr%d,r%u\n", XT, rA_addr);
7490       /*  XS = SX || S
7491        *  For SX=0, mfvsrd is treated as a Floating-Point
7492        *            instruction in terms of resource availability.
7493        *  For SX=1, mfvsrd is treated as a Vector instruction in
7494        *            terms of resource availability.
7495        * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
7496        */
7497       assign( rA, getIReg(rA_addr) );
7498 
7499       if (mode64)
7500          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( rA ), mkU64( 0 ) ) );
7501       else
7502          putVSReg( XT, binop( Iop_64HLtoV128,
7503                               binop( Iop_32HLto64,
7504                                      mkU32( 0 ),
7505                                      mkexpr( rA ) ),
7506                                      mkU64( 0 ) ) );
7507       break;
7508    }
7509 
7510    case 0xD3:                // mtvsrwa
7511    {
7512       UChar XT = ifieldRegXT( theInstr );
7513       UChar rA_addr = ifieldRegA(theInstr);
7514       IRTemp rA = newTemp( Ity_I32 );
7515       DIP("mtvsrwa vsr%d,r%u\n", XT, rA_addr);
7516       /*  XS = SX || S
7517        *  For SX=0, mtvsrwa is treated as a Floating-Point
7518        *            instruction in terms of resource availability.
7519        *  For SX=1, mtvsrwa is treated as a Vector instruction in
7520        *            terms of resource availability.
7521        * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
7522        */
7523       if (mode64)
7524          assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) );
7525       else
7526          assign( rA, getIReg(rA_addr) );
7527 
7528       putVSReg( XT, binop( Iop_64HLtoV128,
7529                            unop( Iop_32Sto64, mkexpr( rA ) ),
7530                            mkU64( 0 ) ) );
7531       break;
7532    }
7533 
7534    case 0xF3:                // mtvsrwz
7535       {
7536          UChar XT = ifieldRegXT( theInstr );
7537          UChar rA_addr = ifieldRegA(theInstr);
7538          IRTemp rA = newTemp( Ity_I32 );
7539          DIP("mtvsrwz vsr%d,r%u\n", rA_addr, XT);
7540          /*  XS = SX || S
7541           *  For SX=0, mtvsrwz is treated as a Floating-Point
7542           *            instruction in terms of resource availability.
7543           *  For SX=1, mtvsrwz is treated as a Vector instruction in
7544           *            terms of resource availability.
7545           * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
7546           */
7547          if (mode64)
7548              assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) );
7549          else
7550              assign( rA, getIReg(rA_addr) );
7551 
7552          putVSReg( XT, binop( Iop_64HLtoV128,
7553                               binop( Iop_32HLto64, mkU32( 0 ), mkexpr ( rA ) ),
7554                               mkU64( 0 ) ) );
7555          break;
7556       }
7557 
7558    default:
7559       vex_printf("dis_proc_ctl(ppc)(opc2)\n");
7560       return False;
7561    }
7562    return True;
7563 }
7564 
7565 
7566 /*
7567   Cache Management Instructions
7568 */
dis_cache_manage(UInt theInstr,DisResult * dres,const VexArchInfo * guest_archinfo)7569 static Bool dis_cache_manage ( UInt         theInstr,
7570                                DisResult*   dres,
7571                                const VexArchInfo* guest_archinfo )
7572 {
7573    /* X-Form */
7574    UChar opc1    = ifieldOPC(theInstr);
7575    UChar b21to25 = ifieldRegDS(theInstr);
7576    UChar rA_addr = ifieldRegA(theInstr);
7577    UChar rB_addr = ifieldRegB(theInstr);
7578    UInt  opc2    = ifieldOPClo10(theInstr);
7579    UChar b0      = ifieldBIT0(theInstr);
7580    UInt  lineszB = guest_archinfo->ppc_icache_line_szB;
7581    Bool  is_dcbzl = False;
7582 
7583    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
7584 
7585    // Check for valid hint values for dcbt and dcbtst as currently described in
7586    // ISA 2.07.  If valid, then we simply set b21to25 to zero since we have no
7587    // means of modeling the hint anyway.
7588    if (opc1 == 0x1F && ((opc2 == 0x116) || (opc2 == 0xF6))) {
7589       if (b21to25 == 0x10 || b21to25 < 0x10)
7590          b21to25 = 0;
7591    }
7592    if (opc1 == 0x1F && opc2 == 0x116 && b21to25 == 0x11)
7593       b21to25 = 0;
7594 
7595    if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz
7596       if (b21to25 == 1) {
7597          is_dcbzl = True;
7598          b21to25 = 0;
7599          if (!(guest_archinfo->ppc_dcbzl_szB)) {
7600             vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n");
7601             return False;
7602          }
7603       }
7604    }
7605 
7606    if (opc1 != 0x1F || b0 != 0) {
7607       if (0) vex_printf("dis_cache_manage %d %d\n",
7608                         opc1, b0);
7609       vex_printf("dis_cache_manage(ppc)(opc1|b0)\n");
7610       return False;
7611    }
7612 
7613    /* stay sane .. */
7614    vassert(lineszB == 16 || lineszB == 32 || lineszB == 64 || lineszB == 128);
7615 
7616    switch (opc2) {
7617 //zz    case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380)
7618 //zz       vassert(0); /* AWAITING TEST CASE */
7619 //zz       DIP("dcba r%u,r%u\n", rA_addr, rB_addr);
7620 //zz       if (0) vex_printf("vex ppc->IR: kludged dcba\n");
7621 //zz       break;
7622 
7623    case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382)
7624       DIP("dcbf r%u,r%u\n", rA_addr, rB_addr);
7625       /* nop as far as vex is concerned */
7626       break;
7627 
7628    case 0x036: // dcbst (Data Cache Block Store, PPC32 p384)
7629       DIP("dcbst r%u,r%u\n", rA_addr, rB_addr);
7630       /* nop as far as vex is concerned */
7631       break;
7632 
7633    case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385)
7634       DIP("dcbt r%u,r%u\n", rA_addr, rB_addr);
7635       /* nop as far as vex is concerned */
7636       break;
7637 
7638    case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386)
7639       DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr);
7640       /* nop as far as vex is concerned */
7641       break;
7642 
7643    case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387)
7644                  // dcbzl (Data Cache Block Clear to Zero Long, bug#135264)
7645       /* Clear all bytes in cache block at (rA|0) + rB. */
7646       IRTemp  EA   = newTemp(ty);
7647       IRTemp  addr = newTemp(ty);
7648       IRExpr* irx_addr;
7649       UInt    i;
7650       UInt clearszB;
7651       if (is_dcbzl) {
7652           clearszB = guest_archinfo->ppc_dcbzl_szB;
7653           DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr);
7654       }
7655       else {
7656           clearszB = guest_archinfo->ppc_dcbz_szB;
7657           DIP("dcbz r%u,r%u\n", rA_addr, rB_addr);
7658       }
7659 
7660       assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
7661 
7662       if (mode64) {
7663          /* Round EA down to the start of the containing block. */
7664          assign( addr, binop( Iop_And64,
7665                               mkexpr(EA),
7666                               mkU64( ~((ULong)clearszB-1) )) );
7667 
7668          for (i = 0; i < clearszB / 8; i++) {
7669             irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) );
7670             store( irx_addr, mkU64(0) );
7671          }
7672       } else {
7673          /* Round EA down to the start of the containing block. */
7674          assign( addr, binop( Iop_And32,
7675                               mkexpr(EA),
7676                               mkU32( ~(clearszB-1) )) );
7677 
7678          for (i = 0; i < clearszB / 4; i++) {
7679             irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) );
7680             store( irx_addr, mkU32(0) );
7681          }
7682       }
7683       break;
7684    }
7685 
7686    case 0x3D6: {
7687       // icbi (Instruction Cache Block Invalidate, PPC32 p431)
7688       /* Invalidate all translations containing code from the cache
7689          block at (rA|0) + rB. */
7690       IRTemp EA   = newTemp(ty);
7691       IRTemp addr = newTemp(ty);
7692       DIP("icbi r%u,r%u\n", rA_addr, rB_addr);
7693       assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
7694 
7695       /* Round EA down to the start of the containing block. */
7696       assign( addr, binop( mkSzOp(ty, Iop_And8),
7697                            mkexpr(EA),
7698                            mkSzImm(ty, ~(((ULong)lineszB)-1) )) );
7699       putGST( PPC_GST_CMSTART, mkexpr(addr) );
7700       putGST( PPC_GST_CMLEN, mkSzImm(ty, lineszB) );
7701 
7702       /* be paranoid ... */
7703       stmt( IRStmt_MBE(Imbe_Fence) );
7704 
7705       putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()));
7706       dres->jk_StopHere = Ijk_InvalICache;
7707       dres->whatNext    = Dis_StopHere;
7708       break;
7709    }
7710 
7711    default:
7712       vex_printf("dis_cache_manage(ppc)(opc2)\n");
7713       return False;
7714    }
7715    return True;
7716 }
7717 
7718 
7719 /*------------------------------------------------------------*/
7720 /*--- Floating Point Helpers                               ---*/
7721 /*------------------------------------------------------------*/
7722 
7723 /* --------- Synthesise a 2-bit FPU rounding mode. --------- */
7724 /* Produces a value in 0 .. 3, which is encoded as per the type
7725    IRRoundingMode.  PPCRoundingMode encoding is different to
7726    IRRoundingMode, so need to map it.
7727 */
get_IR_roundingmode(void)7728 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void )
7729 {
7730 /*
7731    rounding mode | PPC | IR
7732    ------------------------
7733    to nearest    | 00  | 00
7734    to zero       | 01  | 11
7735    to +infinity  | 10  | 10
7736    to -infinity  | 11  | 01
7737 */
7738    IRTemp rm_PPC32 = newTemp(Ity_I32);
7739    assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) );
7740 
7741    // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
7742    return binop( Iop_Xor32,
7743                  mkexpr(rm_PPC32),
7744                  binop( Iop_And32,
7745                         binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)),
7746                         mkU32(2) ));
7747 }
7748 
7749 /* The DFP IR rounding modes were chosen such that the existing PPC to IR
7750  * mapping would still work with the extended three bit DFP rounding
7751  * mode designator.
7752 
7753  *  rounding mode                     | PPC  |  IR
7754  *  -----------------------------------------------
7755  *  to nearest, ties to even          | 000  | 000
7756  *  to zero                           | 001  | 011
7757  *  to +infinity                      | 010  | 010
7758  *  to -infinity                      | 011  | 001
7759  *  to nearest, ties away from 0      | 100  | 100
7760  *  to nearest, ties toward 0         | 101  | 111
7761  *  to away from 0                    | 110  | 110
7762  *  to prepare for shorter precision  | 111  | 101
7763  */
get_IR_roundingmode_DFP(void)7764 static IRExpr* /* :: Ity_I32 */ get_IR_roundingmode_DFP( void )
7765 {
7766    IRTemp rm_PPC32 = newTemp( Ity_I32 );
7767    assign( rm_PPC32, getGST_masked_upper( PPC_GST_FPSCR, MASK_FPSCR_DRN ) );
7768 
7769    // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
7770    return binop( Iop_Xor32,
7771                  mkexpr( rm_PPC32 ),
7772                  binop( Iop_And32,
7773                         binop( Iop_Shl32, mkexpr( rm_PPC32 ), mkU8( 1 ) ),
7774                         mkU32( 2 ) ) );
7775 }
7776 
7777 #define NANmaskSingle   0x7F800000
7778 #define NANmaskDouble   0x7FF00000
7779 
Check_NaN(IRExpr * value,IRExpr * Hi32Mask)7780 static IRExpr * Check_NaN( IRExpr * value, IRExpr * Hi32Mask )
7781 {
7782    IRTemp exp_zero  = newTemp(Ity_I8);
7783    IRTemp frac_mask = newTemp(Ity_I32);
7784    IRTemp frac_not_zero = newTemp(Ity_I8);
7785 
7786    /* Check if the result is QNAN or SNAN and not +infinity or -infinity.
7787     * The input value is always 64-bits, for single precision values, the
7788     * lower 32 bits must be zero.
7789     *
7790     * Single Pricision
7791     *  [62:54] exponent field is equal to 0xFF for NAN and Infinity.
7792     *  [53:32] fraction field is zero for Infinity and non-zero for NAN
7793     *  [31:0]  unused for single precision representation
7794     *
7795     * Double Pricision
7796     *  [62:51] exponent field is equal to 0xFF for NAN and Infinity.
7797     *  [50:0]  fraction field is zero for Infinity and non-zero for NAN
7798     *
7799     * Returned result is a U32 value of 0xFFFFFFFF for NaN and 0 otherwise.
7800     */
7801    assign( frac_mask, unop( Iop_Not32,
7802                             binop( Iop_Or32,
7803                                    mkU32( 0x80000000ULL ), Hi32Mask) ) );
7804 
7805    assign( exp_zero,
7806            unop( Iop_1Sto8,
7807                  binop( Iop_CmpEQ32,
7808                         binop( Iop_And32,
7809                                unop( Iop_64HIto32,
7810                                      unop( Iop_ReinterpF64asI64,
7811                                            value ) ),
7812                                Hi32Mask ),
7813                         Hi32Mask ) ) );
7814    assign( frac_not_zero,
7815            binop( Iop_Or8,
7816                   unop( Iop_1Sto8,
7817                         binop( Iop_CmpNE32,
7818                                binop( Iop_And32,
7819                                       unop( Iop_64HIto32,
7820                                             unop( Iop_ReinterpF64asI64,
7821                                                   value ) ),
7822                                       mkexpr( frac_mask ) ),
7823                                mkU32( 0x0 ) ) ),
7824                   unop( Iop_1Sto8,
7825                         binop( Iop_CmpNE32,
7826                                binop( Iop_And32,
7827                                       unop( Iop_64to32,
7828                                             unop( Iop_ReinterpF64asI64,
7829                                                   value ) ),
7830                                       mkU32( 0xFFFFFFFF ) ),
7831                                mkU32( 0x0 ) ) ) ) );
7832    return unop( Iop_8Sto32,
7833                 binop( Iop_And8,
7834                        mkexpr( exp_zero ),
7835                        mkexpr( frac_not_zero ) ) );
7836 }
7837 
Complement_non_NaN(IRExpr * value,IRExpr * nan_mask)7838 static IRExpr * Complement_non_NaN( IRExpr * value, IRExpr * nan_mask )
7839 {
7840    /* This function will only complement the 64-bit floating point value if it
7841     * is not Nan.  NaN is not a signed value.  Need to do computations using
7842     * 32-bit operands to ensure it will run in 32-bit mode.
7843     */
7844    return  binop( Iop_32HLto64,
7845                   binop( Iop_Or32,
7846                          binop( Iop_And32,
7847                                 nan_mask,
7848                                 unop( Iop_64HIto32,
7849                                       unop( Iop_ReinterpF64asI64,
7850                                             value ) ) ),
7851                          binop( Iop_And32,
7852                                 unop( Iop_Not32,
7853                                       nan_mask ),
7854                                 unop( Iop_64HIto32,
7855                                       unop( Iop_ReinterpF64asI64,
7856                                             unop( Iop_NegF64,
7857                                                   value ) ) ) ) ),
7858                   unop( Iop_64to32,
7859                         unop( Iop_ReinterpF64asI64, value ) ) );
7860 }
7861 
7862 /*------------------------------------------------------------*/
7863 /*--- Floating Point Instruction Translation               ---*/
7864 /*------------------------------------------------------------*/
7865 
7866 /*
7867   Floating Point Load Instructions
7868 */
dis_fp_load(UInt theInstr)7869 static Bool dis_fp_load ( UInt theInstr )
7870 {
7871    /* X-Form, D-Form */
7872    UChar opc1      = ifieldOPC(theInstr);
7873    UChar frD_addr  = ifieldRegDS(theInstr);
7874    UChar rA_addr   = ifieldRegA(theInstr);
7875    UChar rB_addr   = ifieldRegB(theInstr);
7876    UInt  opc2      = ifieldOPClo10(theInstr);
7877    UChar b0        = ifieldBIT0(theInstr);
7878    UInt  uimm16    = ifieldUIMM16(theInstr);
7879 
7880    Int    simm16 = extend_s_16to32(uimm16);
7881    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
7882    IRTemp EA     = newTemp(ty);
7883    IRTemp rA     = newTemp(ty);
7884    IRTemp rB     = newTemp(ty);
7885    IRTemp iHi    = newTemp(Ity_I32);
7886    IRTemp iLo    = newTemp(Ity_I32);
7887 
7888    assign( rA, getIReg(rA_addr) );
7889    assign( rB, getIReg(rB_addr) );
7890 
7891    /* These are completely straightforward from a rounding and status
7892       bits perspective: no rounding involved and no funny status or CR
7893       bits affected. */
7894 
7895    switch (opc1) {
7896    case 0x30: // lfs (Load Float Single, PPC32 p441)
7897       DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
7898       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
7899       putFReg( frD_addr,
7900                unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
7901       break;
7902 
7903    case 0x31: // lfsu (Load Float Single, Update, PPC32 p442)
7904       if (rA_addr == 0)
7905          return False;
7906       DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
7907       assign( EA, ea_rA_simm(rA_addr, simm16) );
7908       putFReg( frD_addr,
7909                unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
7910       putIReg( rA_addr, mkexpr(EA) );
7911       break;
7912 
7913    case 0x32: // lfd (Load Float Double, PPC32 p437)
7914       DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
7915       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
7916       putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
7917       break;
7918 
7919    case 0x33: // lfdu (Load Float Double, Update, PPC32 p438)
7920       if (rA_addr == 0)
7921          return False;
7922       DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
7923       assign( EA, ea_rA_simm(rA_addr, simm16) );
7924       putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
7925       putIReg( rA_addr, mkexpr(EA) );
7926       break;
7927 
7928    case 0x1F:
7929       if (b0 != 0) {
7930          vex_printf("dis_fp_load(ppc)(instr,b0)\n");
7931          return False;
7932       }
7933 
7934       switch(opc2) {
7935       case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444)
7936          DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7937          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
7938          putFReg( frD_addr, unop( Iop_F32toF64,
7939                                   load(Ity_F32, mkexpr(EA))) );
7940          break;
7941 
7942       case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443)
7943          if (rA_addr == 0)
7944             return False;
7945          DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7946          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
7947          putFReg( frD_addr,
7948                   unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
7949          putIReg( rA_addr, mkexpr(EA) );
7950          break;
7951 
7952       case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440)
7953          DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7954          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
7955          putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
7956          break;
7957 
7958       case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439)
7959          if (rA_addr == 0)
7960             return False;
7961          DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7962          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
7963          putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
7964          putIReg( rA_addr, mkexpr(EA) );
7965          break;
7966 
7967       case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120)
7968          DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7969          assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
7970          assign( iLo, load(Ity_I32, mkexpr(EA)) );
7971          assign( iHi, binop(Iop_Sub32,
7972                             mkU32(0),
7973                             binop(Iop_Shr32, mkexpr(iLo), mkU8(31)))  );
7974          putFReg( frD_addr, unop(Iop_ReinterpI64asF64,
7975                                  binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) );
7976          break;
7977 
7978       case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed
7979       {
7980          IRTemp dw = newTemp( Ity_I64 );
7981          DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7982          assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
7983          assign( iLo, load(Ity_I32, mkexpr(EA)) );
7984          assign( dw, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( iLo ) ) );
7985          putFReg( frD_addr, unop( Iop_ReinterpI64asF64, mkexpr( dw ) ) );
7986          break;
7987       }
7988 
7989       default:
7990          vex_printf("dis_fp_load(ppc)(opc2)\n");
7991          return False;
7992       }
7993       break;
7994 
7995    default:
7996       vex_printf("dis_fp_load(ppc)(opc1)\n");
7997       return False;
7998    }
7999    return True;
8000 }
8001 
8002 
8003 
8004 /*
8005   Floating Point Store Instructions
8006 */
dis_fp_store(UInt theInstr)8007 static Bool dis_fp_store ( UInt theInstr )
8008 {
8009    /* X-Form, D-Form */
8010    UChar opc1      = ifieldOPC(theInstr);
8011    UChar frS_addr  = ifieldRegDS(theInstr);
8012    UChar rA_addr   = ifieldRegA(theInstr);
8013    UChar rB_addr   = ifieldRegB(theInstr);
8014    UInt  opc2      = ifieldOPClo10(theInstr);
8015    UChar b0        = ifieldBIT0(theInstr);
8016    Int   uimm16    = ifieldUIMM16(theInstr);
8017 
8018    Int    simm16 = extend_s_16to32(uimm16);
8019    IRTemp frS    = newTemp(Ity_F64);
8020    IRType ty     = mode64 ? Ity_I64 : Ity_I32;
8021    IRTemp EA     = newTemp(ty);
8022    IRTemp rA     = newTemp(ty);
8023    IRTemp rB     = newTemp(ty);
8024 
8025    assign( frS, getFReg(frS_addr) );
8026    assign( rA,  getIReg(rA_addr) );
8027    assign( rB,  getIReg(rB_addr) );
8028 
8029    /* These are straightforward from a status bits perspective: no
8030       funny status or CR bits affected.  For single precision stores,
8031       the values are truncated and denormalised (not rounded) to turn
8032       them into single precision values. */
8033 
8034    switch (opc1) {
8035 
8036    case 0x34: // stfs (Store Float Single, PPC32 p518)
8037       DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
8038       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
8039       /* Use Iop_TruncF64asF32 to truncate and possible denormalise
8040          the value to be stored in the correct way, without any
8041          rounding. */
8042       store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
8043       break;
8044 
8045    case 0x35: // stfsu (Store Float Single, Update, PPC32 p519)
8046       if (rA_addr == 0)
8047          return False;
8048       DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
8049       assign( EA, ea_rA_simm(rA_addr, simm16) );
8050       /* See comment for stfs */
8051       store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
8052       putIReg( rA_addr, mkexpr(EA) );
8053       break;
8054 
8055    case 0x36: // stfd (Store Float Double, PPC32 p513)
8056       DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
8057       assign( EA, ea_rAor0_simm(rA_addr, simm16) );
8058       store( mkexpr(EA), mkexpr(frS) );
8059       break;
8060 
8061    case 0x37: // stfdu (Store Float Double, Update, PPC32 p514)
8062       if (rA_addr == 0)
8063          return False;
8064       DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
8065       assign( EA, ea_rA_simm(rA_addr, simm16) );
8066       store( mkexpr(EA), mkexpr(frS) );
8067       putIReg( rA_addr, mkexpr(EA) );
8068       break;
8069 
8070    case 0x1F:
8071       if (b0 != 0) {
8072          vex_printf("dis_fp_store(ppc)(instr,b0)\n");
8073          return False;
8074       }
8075       switch(opc2) {
8076       case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521)
8077          DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
8078          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
8079          /* See note for stfs */
8080          store( mkexpr(EA),
8081                 unop(Iop_TruncF64asF32, mkexpr(frS)) );
8082          break;
8083 
8084       case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520)
8085          if (rA_addr == 0)
8086             return False;
8087          DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
8088          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
8089          /* See note for stfs */
8090          store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
8091          putIReg( rA_addr, mkexpr(EA) );
8092          break;
8093 
8094       case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516)
8095          DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
8096          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
8097          store( mkexpr(EA), mkexpr(frS) );
8098          break;
8099 
8100       case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515)
8101          if (rA_addr == 0)
8102             return False;
8103          DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
8104          assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
8105          store( mkexpr(EA), mkexpr(frS) );
8106          putIReg( rA_addr, mkexpr(EA) );
8107          break;
8108 
8109       case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517)
8110          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
8111          DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
8112          assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
8113          store( mkexpr(EA),
8114                 unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) );
8115          break;
8116 
8117       default:
8118          vex_printf("dis_fp_store(ppc)(opc2)\n");
8119          return False;
8120       }
8121       break;
8122 
8123    default:
8124       vex_printf("dis_fp_store(ppc)(opc1)\n");
8125       return False;
8126    }
8127    return True;
8128 }
8129 
8130 
8131 
8132 /*
8133   Floating Point Arith Instructions
8134 */
dis_fp_arith(UInt theInstr)8135 static Bool dis_fp_arith ( UInt theInstr )
8136 {
8137    /* A-Form */
8138    UChar opc1     = ifieldOPC(theInstr);
8139    UChar frD_addr = ifieldRegDS(theInstr);
8140    UChar frA_addr = ifieldRegA(theInstr);
8141    UChar frB_addr = ifieldRegB(theInstr);
8142    UChar frC_addr = ifieldRegC(theInstr);
8143    UChar opc2     = ifieldOPClo5(theInstr);
8144    UChar flag_rC  = ifieldBIT0(theInstr);
8145 
8146    IRTemp  frD = newTemp(Ity_F64);
8147    IRTemp  frA = newTemp(Ity_F64);
8148    IRTemp  frB = newTemp(Ity_F64);
8149    IRTemp  frC = newTemp(Ity_F64);
8150    IRExpr* rm  = get_IR_roundingmode();
8151 
8152    /* By default, we will examine the results of the operation and set
8153       fpscr[FPRF] accordingly. */
8154    Bool set_FPRF = True;
8155 
8156    /* By default, if flag_RC is set, we will clear cr1 after the
8157       operation.  In reality we should set cr1 to indicate the
8158       exception status of the operation, but since we're not
8159       simulating exceptions, the exception status will appear to be
8160       zero.  Hence cr1 should be cleared if this is a . form insn. */
8161    Bool clear_CR1 = True;
8162 
8163    assign( frA, getFReg(frA_addr));
8164    assign( frB, getFReg(frB_addr));
8165    assign( frC, getFReg(frC_addr));
8166 
8167    switch (opc1) {
8168    case 0x3B:
8169       switch (opc2) {
8170       case 0x12: // fdivs (Floating Divide Single, PPC32 p407)
8171          if (frC_addr != 0)
8172             return False;
8173          DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8174              frD_addr, frA_addr, frB_addr);
8175          assign( frD, triop( Iop_DivF64r32,
8176                              rm, mkexpr(frA), mkexpr(frB) ));
8177          break;
8178 
8179       case 0x14: // fsubs (Floating Subtract Single, PPC32 p430)
8180          if (frC_addr != 0)
8181             return False;
8182          DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8183              frD_addr, frA_addr, frB_addr);
8184          assign( frD, triop( Iop_SubF64r32,
8185                              rm, mkexpr(frA), mkexpr(frB) ));
8186          break;
8187 
8188       case 0x15: // fadds (Floating Add Single, PPC32 p401)
8189          if (frC_addr != 0)
8190             return False;
8191          DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8192              frD_addr, frA_addr, frB_addr);
8193          assign( frD, triop( Iop_AddF64r32,
8194                              rm, mkexpr(frA), mkexpr(frB) ));
8195          break;
8196 
8197       case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428)
8198          // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
8199          if (frA_addr != 0 || frC_addr != 0)
8200             return False;
8201          DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? ".":"",
8202              frD_addr, frB_addr);
8203          // however illogically, on ppc970 this insn behaves identically
8204          // to fsqrt (double-precision).  So use SqrtF64, not SqrtF64r32.
8205          assign( frD, binop( Iop_SqrtF64, rm, mkexpr(frB) ));
8206          break;
8207 
8208       case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421)
8209          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
8210          if (frA_addr != 0 || frC_addr != 0)
8211             return False;
8212          DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"",
8213              frD_addr, frB_addr);
8214          { IRExpr* ieee_one
8215               = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
8216            assign( frD, triop( Iop_DivF64r32,
8217                                rm,
8218                                ieee_one, mkexpr(frB) ));
8219          }
8220          break;
8221 
8222       case 0x19: // fmuls (Floating Multiply Single, PPC32 p414)
8223          if (frB_addr != 0)
8224             return False;
8225          DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8226              frD_addr, frA_addr, frC_addr);
8227          assign( frD, triop( Iop_MulF64r32,
8228                              rm, mkexpr(frA), mkexpr(frC) ));
8229          break;
8230 
8231       case 0x1A: // frsqrtes (Floating Recip SqRt Est Single)
8232          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
8233          // Undocumented instruction?
8234          if (frA_addr != 0 || frC_addr != 0)
8235             return False;
8236          DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"",
8237              frD_addr, frB_addr);
8238          assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) );
8239          break;
8240 
8241       default:
8242          vex_printf("dis_fp_arith(ppc)(3B: opc2)\n");
8243          return False;
8244       }
8245       break;
8246 
8247    case 0x3F:
8248       switch (opc2) {
8249       case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406)
8250          if (frC_addr != 0)
8251             return False;
8252          DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8253              frD_addr, frA_addr, frB_addr);
8254          assign( frD, triop(Iop_DivF64, rm, mkexpr(frA), mkexpr(frB)) );
8255          break;
8256 
8257       case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429)
8258          if (frC_addr != 0)
8259             return False;
8260          DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8261              frD_addr, frA_addr, frB_addr);
8262          assign( frD, triop(Iop_SubF64, rm, mkexpr(frA), mkexpr(frB)) );
8263          break;
8264 
8265       case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400)
8266          if (frC_addr != 0)
8267             return False;
8268          DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8269              frD_addr, frA_addr, frB_addr);
8270          assign( frD, triop(Iop_AddF64, rm, mkexpr(frA), mkexpr(frB)) );
8271          break;
8272 
8273       case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427)
8274          // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
8275          if (frA_addr != 0 || frC_addr != 0)
8276             return False;
8277          DIP("fsqrt%s fr%u,fr%u\n", flag_rC ? ".":"",
8278              frD_addr, frB_addr);
8279          assign( frD, binop(Iop_SqrtF64, rm, mkexpr(frB)) );
8280          break;
8281 
8282       case 0x17: { // fsel (Floating Select, PPC32 p426)
8283          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
8284          IRTemp cc    = newTemp(Ity_I32);
8285          IRTemp cc_b0 = newTemp(Ity_I32);
8286 
8287          DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8288              frD_addr, frA_addr, frC_addr, frB_addr);
8289 
8290          // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40
8291          // => GT|EQ == (cc & 0x1 == 0)
8292          assign( cc, binop(Iop_CmpF64, mkexpr(frA),
8293                                        IRExpr_Const(IRConst_F64(0))) );
8294          assign( cc_b0, binop(Iop_And32, mkexpr(cc), mkU32(1)) );
8295 
8296          // frD = (frA >= 0.0) ? frC : frB
8297          //     = (cc_b0 == 0) ? frC : frB
8298          assign( frD,
8299                  IRExpr_ITE(
8300                     binop(Iop_CmpEQ32, mkexpr(cc_b0), mkU32(0)),
8301                     mkexpr(frC),
8302                     mkexpr(frB) ));
8303 
8304          /* One of the rare ones which don't mess with FPRF */
8305          set_FPRF = False;
8306          break;
8307       }
8308 
8309       case 0x18: // fre (Floating Reciprocal Estimate)
8310          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
8311          // Note: unclear whether this insn really exists or not
8312          // ppc970 doesn't have it, but POWER5 does
8313          if (frA_addr != 0 || frC_addr != 0)
8314             return False;
8315          DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"",
8316              frD_addr, frB_addr);
8317          { IRExpr* ieee_one
8318               = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
8319            assign( frD, triop( Iop_DivF64,
8320                                rm,
8321                                ieee_one, mkexpr(frB) ));
8322          }
8323          break;
8324 
8325       case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413)
8326          if (frB_addr != 0)
8327             vex_printf("dis_fp_arith(ppc)(instr,fmul)\n");
8328          DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8329              frD_addr, frA_addr, frC_addr);
8330          assign( frD, triop(Iop_MulF64, rm, mkexpr(frA), mkexpr(frC)) );
8331          break;
8332 
8333       case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424)
8334          // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
8335          if (frA_addr != 0 || frC_addr != 0)
8336             return False;
8337          DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"",
8338              frD_addr, frB_addr);
8339          assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) );
8340          break;
8341 
8342       default:
8343          vex_printf("dis_fp_arith(ppc)(3F: opc2)\n");
8344          return False;
8345       }
8346       break;
8347 
8348    default:
8349       vex_printf("dis_fp_arith(ppc)(opc1)\n");
8350       return False;
8351    }
8352 
8353    putFReg( frD_addr, mkexpr(frD) );
8354 
8355    if (set_FPRF) {
8356       // XXX XXX XXX FIXME
8357       // set FPRF from frD
8358    }
8359 
8360    if (flag_rC && clear_CR1) {
8361       putCR321( 1, mkU8(0) );
8362       putCR0( 1, mkU8(0) );
8363    }
8364 
8365    return True;
8366 }
8367 
8368 
8369 
8370 /*
8371   Floating Point Mult-Add Instructions
8372 */
dis_fp_multadd(UInt theInstr)8373 static Bool dis_fp_multadd ( UInt theInstr )
8374 {
8375    /* A-Form */
8376    UChar opc1     = ifieldOPC(theInstr);
8377    UChar frD_addr = ifieldRegDS(theInstr);
8378    UChar frA_addr = ifieldRegA(theInstr);
8379    UChar frB_addr = ifieldRegB(theInstr);
8380    UChar frC_addr = ifieldRegC(theInstr);
8381    UChar opc2     = ifieldOPClo5(theInstr);
8382    UChar flag_rC  = ifieldBIT0(theInstr);
8383 
8384    IRTemp  frD = newTemp(Ity_F64);
8385    IRTemp  frA = newTemp(Ity_F64);
8386    IRTemp  frB = newTemp(Ity_F64);
8387    IRTemp  frC = newTemp(Ity_F64);
8388    IRTemp  rmt = newTemp(Ity_I32);
8389    IRTemp  tmp = newTemp(Ity_F64);
8390    IRTemp  sign_tmp = newTemp(Ity_I64);
8391    IRTemp  nan_mask = newTemp(Ity_I32);
8392    IRExpr* rm;
8393 
8394    /* By default, we will examine the results of the operation and set
8395       fpscr[FPRF] accordingly. */
8396    Bool set_FPRF = True;
8397 
8398    /* By default, if flag_RC is set, we will clear cr1 after the
8399       operation.  In reality we should set cr1 to indicate the
8400       exception status of the operation, but since we're not
8401       simulating exceptions, the exception status will appear to be
8402       zero.  Hence cr1 should be cleared if this is a . form insn. */
8403    Bool clear_CR1 = True;
8404 
8405    /* Bind the rounding mode expression to a temp; there's no
8406       point in creating gratuitous CSEs, as we know we'll need
8407       to use it twice. */
8408    assign( rmt, get_IR_roundingmode() );
8409    rm = mkexpr(rmt);
8410 
8411    assign( frA, getFReg(frA_addr));
8412    assign( frB, getFReg(frB_addr));
8413    assign( frC, getFReg(frC_addr));
8414 
8415    /* The rounding in this is all a bit dodgy.  The idea is to only do
8416       one rounding.  That clearly isn't achieveable without dedicated
8417       four-input IR primops, although in the single precision case we
8418       can sort-of simulate it by doing the inner multiply in double
8419       precision.
8420 
8421       In the negated cases, the negation happens after rounding. */
8422 
8423    switch (opc1) {
8424    case 0x3B:
8425       switch (opc2) {
8426       case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412)
8427          DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8428              frD_addr, frA_addr, frC_addr, frB_addr);
8429          assign( frD, qop( Iop_MSubF64r32, rm,
8430                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
8431          break;
8432 
8433       case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409)
8434          DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8435              frD_addr, frA_addr, frC_addr, frB_addr);
8436          assign( frD, qop( Iop_MAddF64r32, rm,
8437                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
8438          break;
8439 
8440       case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420)
8441       case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418)
8442 
8443          if (opc2 == 0x1E) {
8444             DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8445                      frD_addr, frA_addr, frC_addr, frB_addr);
8446             assign( tmp, qop( Iop_MSubF64r32, rm,
8447                               mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
8448          } else {
8449             DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8450                      frD_addr, frA_addr, frC_addr, frB_addr);
8451             assign( tmp, qop( Iop_MAddF64r32, rm,
8452                               mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
8453          }
8454 
8455          assign( nan_mask, Check_NaN( mkexpr( tmp ),
8456                                       mkU32( NANmaskSingle ) ) );
8457          assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ),
8458                                                mkexpr( nan_mask ) ) );
8459          assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) );
8460          break;
8461 
8462       default:
8463          vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n");
8464          return False;
8465       }
8466       break;
8467 
8468    case 0x3F:
8469       switch (opc2) {
8470       case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411)
8471          DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8472              frD_addr, frA_addr, frC_addr, frB_addr);
8473          assign( frD, qop( Iop_MSubF64, rm,
8474                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
8475          break;
8476 
8477       case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408)
8478          DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8479              frD_addr, frA_addr, frC_addr, frB_addr);
8480          assign( frD, qop( Iop_MAddF64, rm,
8481                            mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
8482          break;
8483 
8484       case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419)
8485       case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417)
8486 
8487          if (opc2 == 0x1E) {
8488             DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8489                      frD_addr, frA_addr, frC_addr, frB_addr);
8490             assign( tmp, qop( Iop_MSubF64, rm,
8491                               mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
8492          } else {
8493             DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8494                      frD_addr, frA_addr, frC_addr, frB_addr);
8495             assign( tmp, qop( Iop_MAddF64, rm,
8496                               mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
8497          }
8498 
8499          assign( nan_mask, Check_NaN( mkexpr( tmp ),
8500                                       mkU32( NANmaskDouble ) ) );
8501          assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ),
8502                                                mkexpr( nan_mask ) ) );
8503          assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) );
8504          break;
8505 
8506       default:
8507          vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n");
8508          return False;
8509       }
8510       break;
8511 
8512    default:
8513       vex_printf("dis_fp_multadd(ppc)(opc1)\n");
8514       return False;
8515    }
8516 
8517    putFReg( frD_addr, mkexpr(frD) );
8518 
8519    if (set_FPRF) {
8520       // XXX XXX XXX FIXME
8521       // set FPRF from frD
8522    }
8523 
8524    if (flag_rC && clear_CR1) {
8525       putCR321( 1, mkU8(0) );
8526       putCR0( 1, mkU8(0) );
8527    }
8528 
8529    return True;
8530 }
8531 
8532 /*
8533  * fe_flag is set to 1 if any of the following conditions occurs:
8534  *  - The floating-point operand in register FRB is a Zero, a
8535  *    NaN, an Infinity, or a negative value.
8536  *  - e_b is less than or equal to: -970 for double precision; -103 for single precision
8537  *  Otherwise fe_flag is set to 0.
8538  *
8539  * fg_flag is set to 1 if either of the following conditions occurs.
8540  *   - The floating-point operand in register FRB is a Zero, an
8541  *     Infinity, or a denormalized value.
8542  *  Otherwise fg_flag is set to 0.
8543  *
8544  */
do_fp_tsqrt(IRTemp frB_Int,Bool sp,IRTemp * fe_flag_tmp,IRTemp * fg_flag_tmp)8545 static void do_fp_tsqrt(IRTemp frB_Int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
8546 {
8547    // The following temps are for holding intermediate results
8548    IRTemp e_b = newTemp(Ity_I32);
8549    IRExpr * fe_flag,  * fg_flag;
8550    IRTemp frB_exp_shR = newTemp(Ity_I32);
8551    UInt bias = sp? 127 : 1023;
8552    IRExpr * frbNaN, * frbDenorm, * frBNeg;
8553    IRExpr * eb_LTE;
8554    IRTemp  frbZero_tmp = newTemp(Ity_I1);
8555    IRTemp  frbInf_tmp = newTemp(Ity_I1);
8556    *fe_flag_tmp = newTemp(Ity_I32);
8557    *fg_flag_tmp = newTemp(Ity_I32);
8558    assign( frB_exp_shR, fp_exp_part( frB_Int, sp ) );
8559    assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
8560 
8561    //////////////////  fe_flag tests BEGIN //////////////////////
8562    /* We first do all tests that may result in setting fe_flag to '1'.
8563     * (NOTE: These tests are similar to those used for ftdiv.  See do_fp_tdiv()
8564     * for details.)
8565     */
8566    frbNaN = sp ? is_NaN_32(frB_Int) : is_NaN(frB_Int);
8567    assign( frbInf_tmp, is_Inf(frB_Int, sp) );
8568    assign( frbZero_tmp, is_Zero(frB_Int, sp ) );
8569    {
8570       // Test_value = -970 for double precision
8571       UInt test_value = sp ? 0xffffff99 : 0xfffffc36;
8572       eb_LTE = binop( Iop_CmpLE32S, mkexpr( e_b ), mkU32( test_value ) );
8573    }
8574    frBNeg = binop( Iop_CmpEQ32,
8575                    binop( Iop_Shr32,
8576                           sp ? mkexpr( frB_Int ) : unop( Iop_64HIto32, mkexpr( frB_Int ) ),
8577                           mkU8( 31 ) ),
8578                    mkU32( 1 ) );
8579    //////////////////  fe_flag tests END //////////////////////
8580 
8581    //////////////////  fg_flag tests BEGIN //////////////////////
8582    /*
8583     * The following tests were already performed above in the fe_flag
8584     * tests.  So these conditions will result in both fe_ and fg_ flags
8585     * being set.
8586     *   - Test if FRB is Zero
8587     *   - Test if FRB is an Infinity
8588     */
8589 
8590    /*
8591     * Test if FRB holds a denormalized value.  A denormalized value is one where
8592     * the exp is 0 and the fraction is non-zero.
8593     */
8594    if (sp) {
8595       IRTemp frac_part = newTemp(Ity_I32);
8596       assign( frac_part, binop( Iop_And32, mkexpr(frB_Int), mkU32(0x007fffff)) );
8597       frbDenorm
8598                = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
8599                          binop( Iop_CmpNE32, mkexpr( frac_part ), mkU32( 0 ) ) );
8600    } else {
8601       IRExpr * hi32, * low32, * fraction_is_nonzero;
8602       IRTemp frac_part = newTemp(Ity_I64);
8603 
8604       assign( frac_part, FP_FRAC_PART(frB_Int) );
8605       hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
8606       low32 = unop( Iop_64to32, mkexpr( frac_part ) );
8607       fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
8608                                                 mkU32( 0 ) );
8609       frbDenorm
8610                = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
8611                          fraction_is_nonzero );
8612    }
8613    //////////////////  fg_flag tests END //////////////////////
8614 
8615    /////////////////////////
8616    fe_flag = mkOR1( mkexpr( frbZero_tmp ),
8617                     mkOR1( frbNaN,
8618                            mkOR1( mkexpr( frbInf_tmp ),
8619                                   mkOR1( frBNeg, eb_LTE ) ) ) );
8620 
8621    fe_flag = unop(Iop_1Uto32, fe_flag);
8622 
8623    fg_flag = mkOR1( mkexpr( frbZero_tmp ),
8624                     mkOR1( mkexpr( frbInf_tmp ), frbDenorm ) );
8625    fg_flag = unop(Iop_1Uto32, fg_flag);
8626    assign (*fg_flag_tmp, fg_flag);
8627    assign (*fe_flag_tmp, fe_flag);
8628 }
8629 /*
8630  * fe_flag is set to 1 if any of the following conditions occurs:
8631  *  - The double-precision floating-point operand in register FRA is a NaN or an
8632  *    Infinity.
8633  *  - The double-precision floating-point operand in register FRB is a Zero, a
8634  *    NaN, or an Infinity.
8635  *  - e_b is less than or equal to -1022.
8636  *  - e_b is greater than or equal to 1021.
8637  *  - The double-precision floating-point operand in register FRA is not a zero
8638  *    and the difference, e_a - e_b, is greater than or equal to 1023.
8639  *  - The double-precision floating-point operand in register FRA is not a zero
8640  *    and the difference, e_a - e_b, is less than or equal to -1021.
8641  *  - The double-precision floating-point operand in register FRA is not a zero
8642  *    and e_a is less than or equal to -970
8643  *  Otherwise fe_flag is set to 0.
8644  *
8645  * fg_flag is set to 1 if either of the following conditions occurs.
8646  *   - The double-precision floating-point operand in register FRA is an Infinity.
8647  *   - The double-precision floating-point operand in register FRB is a Zero, an
8648  *     Infinity, or a denormalized value.
8649  *  Otherwise fg_flag is set to 0.
8650  *
8651  */
_do_fp_tdiv(IRTemp frA_int,IRTemp frB_int,Bool sp,IRTemp * fe_flag_tmp,IRTemp * fg_flag_tmp)8652 static void _do_fp_tdiv(IRTemp frA_int, IRTemp frB_int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
8653 {
8654    // The following temps are for holding intermediate results
8655    IRTemp e_a = newTemp(Ity_I32);
8656    IRTemp e_b = newTemp(Ity_I32);
8657    IRTemp frA_exp_shR = newTemp(Ity_I32);
8658    IRTemp frB_exp_shR = newTemp(Ity_I32);
8659 
8660    UInt bias = sp? 127 : 1023;
8661    *fe_flag_tmp = newTemp(Ity_I32);
8662    *fg_flag_tmp = newTemp(Ity_I32);
8663 
8664    /* The following variables hold boolean results from tests
8665     * that are OR'ed together for setting the fe_ and fg_ flags.
8666     * For some cases, the booleans are used more than once, so
8667     * I make those IRTemp's instead of IRExpr's.
8668     */
8669    IRExpr * fraNaN, * frbNaN, * frbDenorm;
8670    IRExpr * eb_LTE, * eb_GTE, * ea_eb_GTE, * ea_eb_LTE, * ea_LTE;
8671    IRTemp  fraInf_tmp = newTemp(Ity_I1);
8672    IRTemp  frbZero_tmp = newTemp(Ity_I1);
8673    IRTemp  frbInf_tmp = newTemp(Ity_I1);
8674    IRTemp  fraNotZero_tmp = newTemp(Ity_I1);
8675 
8676 /* The following are the flags that are set by OR'ing the results of
8677  * all the tests done for tdiv.  These flags are the input to the specified CR.
8678  */
8679    IRExpr * fe_flag, * fg_flag;
8680 
8681    // Create temps that will be used throughout the following tests.
8682    assign( frA_exp_shR, fp_exp_part( frA_int, sp ) );
8683    assign( frB_exp_shR, fp_exp_part( frB_int, sp ) );
8684    /* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */
8685    assign(e_a, binop( Iop_Sub32, mkexpr(frA_exp_shR), mkU32( bias ) ));
8686    assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
8687 
8688 
8689    //////////////////  fe_flag tests BEGIN //////////////////////
8690    /* We first do all tests that may result in setting fe_flag to '1'. */
8691 
8692    /*
8693     * Test if the double-precision floating-point operand in register FRA is
8694     * a NaN:
8695     */
8696    fraNaN = sp ? is_NaN_32(frA_int) : is_NaN(frA_int);
8697    /*
8698     * Test if the double-precision floating-point operand in register FRA is
8699     * an Infinity.
8700     */
8701    assign(fraInf_tmp, is_Inf(frA_int, sp));
8702 
8703    /*
8704     * Test if the double-precision floating-point operand in register FRB is
8705     * a NaN:
8706     */
8707    frbNaN = sp ? is_NaN_32(frB_int) : is_NaN(frB_int);
8708    /*
8709     * Test if the double-precision floating-point operand in register FRB is
8710     * an Infinity.
8711     */
8712    assign( frbInf_tmp, is_Inf(frB_int, sp) );
8713    /*
8714     * Test if the double-precision floating-point operand in register FRB is
8715     * a Zero.
8716     */
8717    assign( frbZero_tmp, is_Zero(frB_int, sp) );
8718 
8719    /*
8720     * Test if e_b <= -1022 for double precision;
8721     * or e_b <= -126 for single precision
8722     */
8723    {
8724       UInt test_value = sp ? 0xffffff82 : 0xfffffc02;
8725       eb_LTE = binop(Iop_CmpLE32S, mkexpr(e_b), mkU32(test_value));
8726    }
8727 
8728    /*
8729     * Test if e_b >= 1021 (i.e., 1021 < e_b) for double precision;
8730     * or e_b >= -125 (125 < e_b) for single precision
8731     */
8732    {
8733       Int test_value = sp ? 125 : 1021;
8734       eb_GTE = binop(Iop_CmpLT32S, mkU32(test_value), mkexpr(e_b));
8735    }
8736 
8737    /*
8738     * Test if FRA != Zero and (e_a - e_b) >= bias
8739     */
8740    assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( frA_int, sp ) ) );
8741    ea_eb_GTE = mkAND1( mkexpr( fraNotZero_tmp ),
8742                        binop( Iop_CmpLT32S, mkU32( bias ),
8743                               binop( Iop_Sub32, mkexpr( e_a ),
8744                                      mkexpr( e_b ) ) ) );
8745 
8746    /*
8747     * Test if FRA != Zero and (e_a - e_b) <= [-1021 (double precision) or -125 (single precision)]
8748     */
8749    {
8750       UInt test_value = sp ? 0xffffff83 : 0xfffffc03;
8751 
8752       ea_eb_LTE = mkAND1( mkexpr( fraNotZero_tmp ),
8753                           binop( Iop_CmpLE32S,
8754                                  binop( Iop_Sub32,
8755                                         mkexpr( e_a ),
8756                                         mkexpr( e_b ) ),
8757                                         mkU32( test_value ) ) );
8758    }
8759 
8760    /*
8761     * Test if FRA != Zero and e_a <= [-970 (double precision) or -103 (single precision)]
8762     */
8763    {
8764       UInt test_value = 0xfffffc36;  //Int test_value = -970;
8765 
8766       ea_LTE = mkAND1( mkexpr( fraNotZero_tmp ), binop( Iop_CmpLE32S,
8767                                                         mkexpr( e_a ),
8768                                                         mkU32( test_value ) ) );
8769    }
8770    //////////////////  fe_flag tests END //////////////////////
8771 
8772    //////////////////  fg_flag tests BEGIN //////////////////////
8773    /*
8774     * The following tests were already performed above in the fe_flag
8775     * tests.  So these conditions will result in both fe_ and fg_ flags
8776     * being set.
8777     *   - Test if FRA is an Infinity
8778     *   - Test if FRB ix Zero
8779     *   - Test if FRB is an Infinity
8780     */
8781 
8782    /*
8783     * Test if FRB holds a denormalized value.  A denormalized value is one where
8784     * the exp is 0 and the fraction is non-zero.
8785     */
8786    {
8787       IRExpr * fraction_is_nonzero;
8788 
8789       if (sp) {
8790          fraction_is_nonzero = binop( Iop_CmpNE32, FP_FRAC_PART32(frB_int),
8791                                       mkU32( 0 ) );
8792       } else {
8793          IRExpr * hi32, * low32;
8794          IRTemp frac_part = newTemp(Ity_I64);
8795          assign( frac_part, FP_FRAC_PART(frB_int) );
8796 
8797          hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
8798          low32 = unop( Iop_64to32, mkexpr( frac_part ) );
8799          fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
8800                                       mkU32( 0 ) );
8801       }
8802       frbDenorm = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ),
8803                                  mkU32( 0x0 ) ), fraction_is_nonzero );
8804 
8805    }
8806    //////////////////  fg_flag tests END //////////////////////
8807 
8808    fe_flag
8809    = mkOR1(
8810             fraNaN,
8811             mkOR1(
8812                    mkexpr( fraInf_tmp ),
8813                    mkOR1(
8814                           mkexpr( frbZero_tmp ),
8815                           mkOR1(
8816                                  frbNaN,
8817                                  mkOR1(
8818                                         mkexpr( frbInf_tmp ),
8819                                         mkOR1( eb_LTE,
8820                                                mkOR1( eb_GTE,
8821                                                       mkOR1( ea_eb_GTE,
8822                                                              mkOR1( ea_eb_LTE,
8823                                                                     ea_LTE ) ) ) ) ) ) ) ) );
8824 
8825    fe_flag = unop(Iop_1Uto32, fe_flag);
8826 
8827    fg_flag = mkOR1( mkexpr( fraInf_tmp ), mkOR1( mkexpr( frbZero_tmp ),
8828                                                  mkOR1( mkexpr( frbInf_tmp ),
8829                                                         frbDenorm ) ) );
8830    fg_flag = unop(Iop_1Uto32, fg_flag);
8831    assign(*fe_flag_tmp, fe_flag);
8832    assign(*fg_flag_tmp, fg_flag);
8833 }
8834 
8835 /* See description for _do_fp_tdiv() above. */
do_fp_tdiv(IRTemp frA_int,IRTemp frB_int)8836 static IRExpr * do_fp_tdiv(IRTemp frA_int, IRTemp frB_int)
8837 {
8838    IRTemp  fe_flag, fg_flag;
8839    /////////////////////////
8840    /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
8841     * where fl_flag == 1 on ppc64.
8842     */
8843    IRExpr * fl_flag = unop(Iop_Not32, mkU32(0xFFFFFE));
8844    fe_flag = fg_flag = IRTemp_INVALID;
8845    _do_fp_tdiv(frA_int, frB_int, False/*not single precision*/, &fe_flag, &fg_flag);
8846    return binop( Iop_Or32,
8847                  binop( Iop_Or32,
8848                         binop( Iop_Shl32, fl_flag, mkU8( 3 ) ),
8849                         binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
8850                  binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) );
8851 }
8852 
dis_fp_tests(UInt theInstr)8853 static Bool dis_fp_tests ( UInt theInstr )
8854 {
8855    UChar opc1     = ifieldOPC(theInstr);
8856    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
8857    UChar frB_addr = ifieldRegB(theInstr);
8858    UChar b0       = ifieldBIT0(theInstr);
8859    UInt  opc2     = ifieldOPClo10(theInstr);
8860    IRTemp frB_I64     = newTemp(Ity_I64);
8861 
8862    if (opc1 != 0x3F || b0 != 0 ){
8863       vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
8864       return False;
8865    }
8866    assign( frB_I64, unop( Iop_ReinterpF64asI64, getFReg( frB_addr ) ) );
8867 
8868    switch (opc2) {
8869       case 0x080: // ftdiv
8870       {
8871          UChar frA_addr = ifieldRegA(theInstr);
8872          IRTemp frA_I64     = newTemp(Ity_I64);
8873          UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
8874          if (b21to22 != 0 ) {
8875             vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
8876             return False;
8877          }
8878 
8879          assign( frA_I64, unop( Iop_ReinterpF64asI64, getFReg( frA_addr ) ) );
8880          putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
8881 
8882          DIP("ftdiv crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
8883          break;
8884       }
8885       case 0x0A0: // ftsqrt
8886       {
8887          IRTemp flags = newTemp(Ity_I32);
8888          IRTemp  fe_flag, fg_flag;
8889          fe_flag = fg_flag = IRTemp_INVALID;
8890          UChar b18to22  = toUChar( IFIELD( theInstr, 18, 5 ) );
8891          if ( b18to22 != 0) {
8892             vex_printf("dis_fp_tests(ppc)(ftsqrt)\n");
8893             return False;
8894          }
8895          DIP("ftsqrt crf%d,fr%u\n", crfD, frB_addr);
8896          do_fp_tsqrt(frB_I64, False /* not single precision*/, &fe_flag, &fg_flag);
8897          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
8898           * where fl_flag == 1 on ppc64.
8899           */
8900          assign( flags,
8901                  binop( Iop_Or32,
8902                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
8903                                binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
8904                         binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
8905          putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
8906          break;
8907       }
8908 
8909       default:
8910          vex_printf("dis_fp_tests(ppc)(opc2)\n");
8911          return False;
8912 
8913    }
8914    return True;
8915 }
8916 
8917 /*
8918   Floating Point Compare Instructions
8919 */
dis_fp_cmp(UInt theInstr)8920 static Bool dis_fp_cmp ( UInt theInstr )
8921 {
8922    /* X-Form */
8923    UChar opc1     = ifieldOPC(theInstr);
8924    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
8925    UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
8926    UChar frA_addr = ifieldRegA(theInstr);
8927    UChar frB_addr = ifieldRegB(theInstr);
8928    UInt  opc2     = ifieldOPClo10(theInstr);
8929    UChar b0       = ifieldBIT0(theInstr);
8930 
8931    IRTemp ccIR    = newTemp(Ity_I32);
8932    IRTemp ccPPC32 = newTemp(Ity_I32);
8933 
8934    IRTemp frA     = newTemp(Ity_F64);
8935    IRTemp frB     = newTemp(Ity_F64);
8936 
8937    if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) {
8938       vex_printf("dis_fp_cmp(ppc)(instr)\n");
8939       return False;
8940    }
8941 
8942    assign( frA, getFReg(frA_addr));
8943    assign( frB, getFReg(frB_addr));
8944 
8945    assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) );
8946 
8947    /* Map compare result from IR to PPC32 */
8948    /*
8949      FP cmp result | PPC | IR
8950      --------------------------
8951      UN            | 0x1 | 0x45
8952      EQ            | 0x2 | 0x40
8953      GT            | 0x4 | 0x00
8954      LT            | 0x8 | 0x01
8955    */
8956 
8957    // ccPPC32 = Shl(1, (~(ccIR>>5) & 2)
8958    //                    | ((ccIR ^ (ccIR>>6)) & 1)
8959    assign(
8960       ccPPC32,
8961       binop(
8962          Iop_Shl32,
8963          mkU32(1),
8964          unop(
8965             Iop_32to8,
8966             binop(
8967                Iop_Or32,
8968                binop(
8969                   Iop_And32,
8970                   unop(
8971                      Iop_Not32,
8972                      binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))
8973                   ),
8974                   mkU32(2)
8975                ),
8976                binop(
8977                   Iop_And32,
8978                   binop(
8979                      Iop_Xor32,
8980                      mkexpr(ccIR),
8981                      binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))
8982                   ),
8983                   mkU32(1)
8984                )
8985             )
8986          )
8987       )
8988    );
8989 
8990    putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
8991 
8992    /* CAB: TODO?: Support writing cc to FPSCR->FPCC ?
8993       putGST_field( PPC_GST_FPSCR, mkexpr(ccPPC32), 4 );
8994    */
8995    // XXX XXX XXX FIXME
8996    // Also write the result into FPRF (it's not entirely clear how)
8997 
8998    /* Note: Differences between fcmpu and fcmpo are only in exception
8999       flag settings, which aren't supported anyway. */
9000    switch (opc2) {
9001    case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403)
9002       DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
9003       break;
9004    case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402)
9005       DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
9006       break;
9007    default:
9008       vex_printf("dis_fp_cmp(ppc)(opc2)\n");
9009       return False;
9010    }
9011    return True;
9012 }
9013 
9014 
9015 
9016 /*
9017   Floating Point Rounding/Conversion Instructions
9018 */
dis_fp_round(UInt theInstr)9019 static Bool dis_fp_round ( UInt theInstr )
9020 {
9021    /* X-Form */
9022    UChar opc1     = ifieldOPC(theInstr);
9023    UChar b16to20  = ifieldRegA(theInstr);
9024    UChar frD_addr = ifieldRegDS(theInstr);
9025    UChar frB_addr = ifieldRegB(theInstr);
9026    UInt  opc2     = ifieldOPClo10(theInstr);
9027    UChar flag_rC  = ifieldBIT0(theInstr);
9028 
9029    IRTemp  frD     = newTemp(Ity_F64);
9030    IRTemp  frB     = newTemp(Ity_F64);
9031    IRTemp  r_tmp32 = newTemp(Ity_I32);
9032    IRTemp  r_tmp64 = newTemp(Ity_I64);
9033    IRExpr* rm      = get_IR_roundingmode();
9034 
9035    /* By default, we will examine the results of the operation and set
9036       fpscr[FPRF] accordingly. */
9037    Bool set_FPRF = True;
9038 
9039    /* By default, if flag_RC is set, we will clear cr1 after the
9040       operation.  In reality we should set cr1 to indicate the
9041       exception status of the operation, but since we're not
9042       simulating exceptions, the exception status will appear to be
9043       zero.  Hence cr1 should be cleared if this is a . form insn. */
9044    Bool clear_CR1 = True;
9045    if ((!(opc1 == 0x3F || opc1 == 0x3B)) || b16to20 != 0) {
9046       vex_printf("dis_fp_round(ppc)(instr)\n");
9047       return False;
9048    }
9049 
9050    assign( frB, getFReg(frB_addr));
9051    if (opc1 == 0x3B) {
9052       /* The fcfid[u]s instructions (from ISA 2.06) are a bit odd because
9053        * they're very similar to the other instructions handled here, but have
9054        * a different primary opcode.
9055        */
9056       switch (opc2) {
9057          case 0x34E: // fcfids (Float convert from signed DWord to single precision)
9058             DIP("fcfids%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9059             assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
9060             assign( frD, binop( Iop_RoundF64toF32, rm, binop( Iop_I64StoF64, rm,
9061                                                               mkexpr( r_tmp64 ) ) ) );
9062             goto putFR;
9063 
9064          case 0x3Ce: // fcfidus (Float convert from unsigned DWord to single precision)
9065             DIP("fcfidus%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9066             assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
9067             assign( frD, unop( Iop_F32toF64, binop( Iop_I64UtoF32, rm, mkexpr( r_tmp64 ) ) ) );
9068             goto putFR;
9069       }
9070    }
9071 
9072 
9073    switch (opc2) {
9074    case 0x00C: // frsp (Float Round to Single, PPC32 p423)
9075       DIP("frsp%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9076       assign( frD, binop( Iop_RoundF64toF32, rm, mkexpr(frB) ));
9077       break;
9078 
9079    case 0x00E: // fctiw (Float Conv to Int, PPC32 p404)
9080       DIP("fctiw%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9081       assign( r_tmp32,
9082               binop(Iop_F64toI32S, rm, mkexpr(frB)) );
9083       assign( frD, unop( Iop_ReinterpI64asF64,
9084                          unop( Iop_32Uto64, mkexpr(r_tmp32))));
9085       /* FPRF is undefined after fctiw.  Leave unchanged. */
9086       set_FPRF = False;
9087       break;
9088 
9089    case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405)
9090       DIP("fctiwz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9091       assign( r_tmp32,
9092               binop(Iop_F64toI32S, mkU32(Irrm_ZERO), mkexpr(frB) ));
9093       assign( frD, unop( Iop_ReinterpI64asF64,
9094                          unop( Iop_32Uto64, mkexpr(r_tmp32))));
9095       /* FPRF is undefined after fctiwz.  Leave unchanged. */
9096       set_FPRF = False;
9097       break;
9098 
9099    case 0x08F: case 0x08E: // fctiwu[z]
9100       DIP("fctiwu%s%s fr%u,fr%u\n", opc2 == 0x08F ? "z" : "",
9101                flag_rC ? ".":"", frD_addr, frB_addr);
9102       assign( r_tmp32,
9103               binop( Iop_F64toI32U,
9104                      opc2 == 0x08F ? mkU32( Irrm_ZERO ) : rm,
9105                      mkexpr( frB ) ) );
9106       assign( frD, unop( Iop_ReinterpI64asF64,
9107                          unop( Iop_32Uto64, mkexpr(r_tmp32))));
9108       /* FPRF is undefined after fctiwz.  Leave unchanged. */
9109       set_FPRF = False;
9110       break;
9111 
9112 
9113    case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437)
9114       DIP("fctid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9115       assign( r_tmp64,
9116               binop(Iop_F64toI64S, rm, mkexpr(frB)) );
9117       assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
9118       /* FPRF is undefined after fctid.  Leave unchanged. */
9119       set_FPRF = False;
9120       break;
9121 
9122    case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437)
9123       DIP("fctidz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9124       assign( r_tmp64,
9125               binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
9126       assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
9127       /* FPRF is undefined after fctidz.  Leave unchanged. */
9128       set_FPRF = False;
9129       break;
9130 
9131    case 0x3AE: case 0x3AF: // fctidu[z] (Float Conv to Int DWord Unsigned [Round to Zero])
9132    {
9133       DIP("fctidu%s%s fr%u,fr%u\n", opc2 == 0x3AE ? "" : "z",
9134                flag_rC ? ".":"", frD_addr, frB_addr);
9135       assign( r_tmp64,
9136               binop(Iop_F64toI64U, opc2 == 0x3AE ? rm : mkU32(Irrm_ZERO), mkexpr(frB)) );
9137       assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
9138       /* FPRF is undefined after fctidz.  Leave unchanged. */
9139       set_FPRF = False;
9140       break;
9141    }
9142    case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434)
9143       DIP("fcfid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9144       assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
9145       assign( frD,
9146               binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) );
9147       break;
9148 
9149    case 0x3CE: // fcfidu (Float convert from unsigned DWord)
9150       DIP("fcfidu%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9151       assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
9152       assign( frD, binop( Iop_I64UtoF64, rm, mkexpr( r_tmp64 ) ) );
9153       break;
9154 
9155    case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim
9156       switch(opc2) {
9157       case 0x188: // frin (Floating Round to Integer Nearest)
9158          DIP("frin%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9159          assign( r_tmp64,
9160                  binop(Iop_F64toI64S, mkU32(Irrm_NEAREST), mkexpr(frB)) );
9161          break;
9162       case 0x1A8: // friz (Floating Round to Integer Toward Zero)
9163          DIP("friz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9164          assign( r_tmp64,
9165                  binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
9166          break;
9167       case 0x1C8: // frip (Floating Round to Integer Plus)
9168          DIP("frip%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9169          assign( r_tmp64,
9170                  binop(Iop_F64toI64S, mkU32(Irrm_PosINF), mkexpr(frB)) );
9171          break;
9172       case 0x1E8: // frim (Floating Round to Integer Minus)
9173          DIP("frim%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9174          assign( r_tmp64,
9175                  binop(Iop_F64toI64S, mkU32(Irrm_NegINF), mkexpr(frB)) );
9176          break;
9177       }
9178 
9179       /* don't use the rounded integer if frB is outside -9e18..9e18 */
9180       /* F64 has only log10(2**52) significant digits anyway */
9181       /* need to preserve sign of zero */
9182       /*   frD = (fabs(frB) > 9e18) ? frB :
9183                (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64  */
9184       assign(frD, IRExpr_ITE(
9185                      binop(Iop_CmpNE8,
9186                            unop(Iop_32to8,
9187                                 binop(Iop_CmpF64,
9188                                       IRExpr_Const(IRConst_F64(9e18)),
9189                                       unop(Iop_AbsF64, mkexpr(frB)))),
9190                            mkU8(0)),
9191                      mkexpr(frB),
9192                      IRExpr_ITE(
9193                         binop(Iop_CmpNE32,
9194                               binop(Iop_Shr32,
9195                                     unop(Iop_64HIto32,
9196                                          unop(Iop_ReinterpF64asI64,
9197                                               mkexpr(frB))),
9198                                     mkU8(31)),
9199                               mkU32(0)),
9200                         unop(Iop_NegF64,
9201                              unop( Iop_AbsF64,
9202                                    binop(Iop_I64StoF64, mkU32(0),
9203                                          mkexpr(r_tmp64)) )),
9204                         binop(Iop_I64StoF64, mkU32(0), mkexpr(r_tmp64) )
9205                      )
9206       ));
9207       break;
9208 
9209    default:
9210       vex_printf("dis_fp_round(ppc)(opc2)\n");
9211       return False;
9212    }
9213 putFR:
9214    putFReg( frD_addr, mkexpr(frD) );
9215 
9216    if (set_FPRF) {
9217       // XXX XXX XXX FIXME
9218       // set FPRF from frD
9219    }
9220 
9221    if (flag_rC && clear_CR1) {
9222       putCR321( 1, mkU8(0) );
9223       putCR0( 1, mkU8(0) );
9224    }
9225 
9226    return True;
9227 }
9228 
9229 /*
9230   Floating Point Pair Instructions
9231 */
dis_fp_pair(UInt theInstr)9232 static Bool dis_fp_pair ( UInt theInstr )
9233 {
9234    /* X-Form/DS-Form */
9235    UChar  opc1         = ifieldOPC(theInstr);
9236    UChar  frT_hi_addr  = ifieldRegDS(theInstr);
9237    UChar  frT_lo_addr  = frT_hi_addr + 1;
9238    UChar  rA_addr      = ifieldRegA(theInstr);
9239    UChar  rB_addr      = ifieldRegB(theInstr);
9240    UInt  uimm16        = ifieldUIMM16(theInstr);
9241    Int    simm16       = extend_s_16to32(uimm16);
9242    UInt   opc2         = ifieldOPClo10(theInstr);
9243    IRType ty           = mode64 ? Ity_I64 : Ity_I32;
9244    IRTemp EA_hi        = newTemp(ty);
9245    IRTemp EA_lo        = newTemp(ty);
9246    IRTemp frT_hi       = newTemp(Ity_F64);
9247    IRTemp frT_lo       = newTemp(Ity_F64);
9248    UChar b0            = ifieldBIT0(theInstr);
9249    Bool is_load        = 0;
9250 
9251    if ((frT_hi_addr %2) != 0) {
9252       vex_printf("dis_fp_pair(ppc) : odd frT register\n");
9253       return False;
9254    }
9255 
9256    switch (opc1) {
9257    case 0x1F: // register offset
9258       switch(opc2) {
9259       case 0x317:     // lfdpx (FP Load Double Pair X-form, ISA 2.05  p125)
9260          DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
9261          is_load = 1;
9262          break;
9263       case 0x397:     // stfdpx (FP STORE Double Pair X-form, ISA 2.05  p125)
9264          DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
9265          break;
9266       default:
9267          vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n");
9268          return False;
9269       }
9270 
9271       if (b0 != 0) {
9272          vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n");
9273          return False;
9274       }
9275       assign( EA_hi, ea_rAor0_idxd( rA_addr, rB_addr ) );
9276       break;
9277    case 0x39: // lfdp (FP Load Double Pair DS-form, ISA 2.05  p125)
9278       DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
9279       assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
9280       is_load = 1;
9281       break;
9282    case 0x3d: // stfdp (FP Store Double Pair DS-form, ISA 2.05  p125)
9283       DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
9284       assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
9285       break;
9286    default:   // immediate offset
9287       vex_printf("dis_fp_pair(ppc)(instr)\n");
9288       return False;
9289    }
9290 
9291    if (mode64)
9292       assign( EA_lo, binop(Iop_Add64, mkexpr(EA_hi), mkU64(8)) );
9293    else
9294       assign( EA_lo, binop(Iop_Add32, mkexpr(EA_hi), mkU32(8)) );
9295 
9296    assign( frT_hi, getFReg(frT_hi_addr) );
9297    assign( frT_lo, getFReg(frT_lo_addr) );
9298 
9299    if (is_load) {
9300       putFReg( frT_hi_addr, load(Ity_F64, mkexpr(EA_hi)) );
9301       putFReg( frT_lo_addr, load(Ity_F64, mkexpr(EA_lo)) );
9302    } else {
9303       store( mkexpr(EA_hi), mkexpr(frT_hi) );
9304       store( mkexpr(EA_lo), mkexpr(frT_lo) );
9305    }
9306 
9307    return True;
9308 }
9309 
9310 
9311 /*
9312   Floating Point Merge Instructions
9313 */
dis_fp_merge(UInt theInstr)9314 static Bool dis_fp_merge ( UInt theInstr )
9315 {
9316    /* X-Form */
9317    UInt  opc2     = ifieldOPClo10(theInstr);
9318    UChar frD_addr = ifieldRegDS(theInstr);
9319    UChar frA_addr = ifieldRegA(theInstr);
9320    UChar frB_addr = ifieldRegB(theInstr);
9321 
9322    IRTemp frD = newTemp(Ity_F64);
9323    IRTemp frA = newTemp(Ity_F64);
9324    IRTemp frB = newTemp(Ity_F64);
9325 
9326    assign( frA, getFReg(frA_addr));
9327    assign( frB, getFReg(frB_addr));
9328 
9329    switch (opc2) {
9330    case 0x3c6: // fmrgew floating merge even word
9331       DIP("fmrgew fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr);
9332 
9333       assign( frD, unop( Iop_ReinterpI64asF64,
9334                          binop( Iop_32HLto64,
9335                                 unop( Iop_64HIto32,
9336                                       unop( Iop_ReinterpF64asI64,
9337                                             mkexpr(frA) ) ),
9338                                 unop( Iop_64HIto32,
9339                                       unop( Iop_ReinterpF64asI64,
9340                                             mkexpr(frB) ) ) ) ) );
9341    break;
9342 
9343    case 0x346: // fmrgow floating merge odd word
9344       DIP("fmrgow fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr);
9345 
9346       assign( frD, unop( Iop_ReinterpI64asF64,
9347                          binop( Iop_32HLto64,
9348                                 unop( Iop_64to32,
9349                                       unop( Iop_ReinterpF64asI64,
9350                                             mkexpr(frA) ) ),
9351                                 unop( Iop_64to32,
9352                                       unop( Iop_ReinterpF64asI64,
9353                                             mkexpr(frB) ) ) ) ) );
9354    break;
9355 
9356    default:
9357       vex_printf("dis_fp_merge(ppc)(opc2)\n");
9358       return False;
9359    }
9360 
9361    putFReg( frD_addr, mkexpr(frD) );
9362    return True;
9363 }
9364 
9365 /*
9366   Floating Point Move Instructions
9367 */
dis_fp_move(UInt theInstr)9368 static Bool dis_fp_move ( UInt theInstr )
9369 {
9370    /* X-Form */
9371    UChar opc1     = ifieldOPC(theInstr);
9372    UChar frD_addr = ifieldRegDS(theInstr);
9373    UChar frA_addr = ifieldRegA(theInstr);
9374    UChar frB_addr = ifieldRegB(theInstr);
9375    UInt  opc2     = ifieldOPClo10(theInstr);
9376    UChar flag_rC  = ifieldBIT0(theInstr);
9377 
9378    IRTemp frD = newTemp(Ity_F64);
9379    IRTemp frB = newTemp(Ity_F64);
9380    IRTemp itmpB = newTemp(Ity_F64);
9381    IRTemp frA;
9382    IRTemp signA;
9383    IRTemp hiD;
9384 
9385    if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) {
9386       vex_printf("dis_fp_move(ppc)(instr)\n");
9387       return False;
9388    }
9389 
9390    assign( frB, getFReg(frB_addr));
9391 
9392    switch (opc2) {
9393    case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126)
9394       DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frA_addr,
9395           frB_addr);
9396       signA = newTemp(Ity_I32);
9397       hiD = newTemp(Ity_I32);
9398       itmpB = newTemp(Ity_I64);
9399       frA = newTemp(Ity_F64);
9400       assign( frA, getFReg(frA_addr) );
9401 
9402       /* get A's sign bit */
9403       assign(signA, binop(Iop_And32,
9404                           unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64,
9405                                                   mkexpr(frA))),
9406                           mkU32(0x80000000)) );
9407 
9408       assign( itmpB, unop(Iop_ReinterpF64asI64, mkexpr(frB)) );
9409 
9410       /* mask off B's sign bit and or in A's sign bit */
9411       assign(hiD, binop(Iop_Or32,
9412                         binop(Iop_And32,
9413                               unop(Iop_64HIto32,
9414                                    mkexpr(itmpB)),  /* frB's high 32 bits */
9415                               mkU32(0x7fffffff)),
9416                         mkexpr(signA)) );
9417 
9418       /* combine hiD/loB into frD */
9419       assign( frD, unop(Iop_ReinterpI64asF64,
9420                         binop(Iop_32HLto64,
9421                               mkexpr(hiD),
9422                               unop(Iop_64to32,
9423                                    mkexpr(itmpB)))) );   /* frB's low 32 bits */
9424       break;
9425 
9426    case 0x028: // fneg (Floating Negate, PPC32 p416)
9427       DIP("fneg%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9428       assign( frD, unop( Iop_NegF64, mkexpr(frB) ));
9429       break;
9430 
9431    case 0x048: // fmr (Floating Move Register, PPC32 p410)
9432       DIP("fmr%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9433       assign( frD, mkexpr(frB) );
9434       break;
9435 
9436    case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415)
9437       DIP("fnabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9438       assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) )));
9439       break;
9440 
9441    case 0x108: // fabs (Floating Absolute Value, PPC32 p399)
9442       DIP("fabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9443       assign( frD, unop( Iop_AbsF64, mkexpr(frB) ));
9444       break;
9445 
9446    default:
9447       vex_printf("dis_fp_move(ppc)(opc2)\n");
9448       return False;
9449    }
9450 
9451    putFReg( frD_addr, mkexpr(frD) );
9452 
9453    /* None of these change FPRF.  cr1 is set in the usual way though,
9454       if flag_rC is set. */
9455 
9456    if (flag_rC) {
9457       putCR321( 1, mkU8(0) );
9458       putCR0( 1, mkU8(0) );
9459    }
9460 
9461    return True;
9462 }
9463 
9464 
9465 
9466 /*
9467   Floating Point Status/Control Register Instructions
9468 */
dis_fp_scr(UInt theInstr,Bool GX_level)9469 static Bool dis_fp_scr ( UInt theInstr, Bool GX_level )
9470 {
9471    /* Many forms - see each switch case */
9472    UChar opc1    = ifieldOPC(theInstr);
9473    UInt  opc2    = ifieldOPClo10(theInstr);
9474    UChar flag_rC = ifieldBIT0(theInstr);
9475 
9476    if (opc1 != 0x3F) {
9477       vex_printf("dis_fp_scr(ppc)(instr)\n");
9478       return False;
9479    }
9480 
9481    switch (opc2) {
9482    case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479)
9483       // Bit crbD of the FPSCR is set.
9484       UChar crbD    = ifieldRegDS(theInstr);
9485       UInt  b11to20 = IFIELD(theInstr, 11, 10);
9486 
9487       if (b11to20 != 0) {
9488          vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n");
9489          return False;
9490       }
9491       DIP("mtfsb1%s crb%d \n", flag_rC ? ".":"", crbD);
9492       putGST_masked( PPC_GST_FPSCR, mkU64( 1 <<( 31 - crbD ) ),
9493 		     1ULL << ( 31 - crbD ) );
9494       break;
9495    }
9496 
9497    case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465)
9498       UChar   crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
9499       UChar   b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) );
9500       UChar   crfS    = toUChar( IFIELD( theInstr, 18, 3 ) );
9501       UChar   b11to17 = toUChar( IFIELD( theInstr, 11, 7 ) );
9502       IRTemp  tmp     = newTemp(Ity_I32);
9503       IRExpr* fpscr_all;
9504       if (b21to22 != 0 || b11to17 != 0 || flag_rC != 0) {
9505          vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n");
9506          return False;
9507       }
9508       DIP("mcrfs crf%d,crf%d\n", crfD, crfS);
9509       vassert(crfD < 8);
9510       vassert(crfS < 8);
9511       fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
9512       assign( tmp, binop(Iop_And32,
9513                          binop(Iop_Shr32,fpscr_all,mkU8(4 * (7-crfS))),
9514                         mkU32(0xF)) );
9515       putGST_field( PPC_GST_CR, mkexpr(tmp), crfD );
9516       break;
9517    }
9518 
9519    case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478)
9520       // Bit crbD of the FPSCR is cleared.
9521       UChar crbD    = ifieldRegDS(theInstr);
9522       UInt  b11to20 = IFIELD(theInstr, 11, 10);
9523 
9524       if (b11to20 != 0) {
9525          vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n");
9526          return False;
9527       }
9528       DIP("mtfsb0%s crb%d\n", flag_rC ? ".":"", crbD);
9529       putGST_masked( PPC_GST_FPSCR, mkU64( 0 ), 1ULL << ( 31 - crbD ) );
9530       break;
9531    }
9532 
9533    case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481)
9534       UInt crfD     = IFIELD( theInstr, 23, 3 );
9535       UChar b16to22 = toUChar( IFIELD( theInstr, 16, 7 ) );
9536       UChar IMM     = toUChar( IFIELD( theInstr, 12, 4 ) );
9537       UChar b11     = toUChar( IFIELD( theInstr, 11, 1 ) );
9538       UChar Wbit;
9539 
9540       if (b16to22 != 0 || b11 != 0) {
9541          vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n");
9542          return False;
9543       }
9544       DIP("mtfsfi%s crf%u,%d\n", flag_rC ? ".":"", crfD, IMM);
9545       if (GX_level) {
9546          /* This implies that Decimal Floating Point is supported, and the
9547           * FPSCR must be managed as a 64-bit register.
9548           */
9549          Wbit = toUChar( IFIELD(theInstr, 16, 1) );
9550       } else {
9551          Wbit = 0;
9552       }
9553       crfD = crfD + (8 * (1 - Wbit) );
9554       putGST_field( PPC_GST_FPSCR, mkU32( IMM ), crfD );
9555       break;
9556    }
9557 
9558    case 0x247: { // mffs (Move from FPSCR, PPC32 p468)
9559       UChar   frD_addr  = ifieldRegDS(theInstr);
9560       UInt    b11to20   = IFIELD(theInstr, 11, 10);
9561       IRExpr* fpscr_lower = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
9562       IRExpr* fpscr_upper = getGST_masked_upper( PPC_GST_FPSCR,
9563                                                  MASK_FPSCR_DRN );
9564 
9565       if (b11to20 != 0) {
9566          vex_printf("dis_fp_scr(ppc)(instr,mffs)\n");
9567          return False;
9568       }
9569       DIP("mffs%s fr%u\n", flag_rC ? ".":"", frD_addr);
9570       putFReg( frD_addr,
9571           unop( Iop_ReinterpI64asF64,
9572                 binop( Iop_32HLto64, fpscr_upper, fpscr_lower ) ) );
9573       break;
9574    }
9575 
9576    case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480)
9577       UChar b25      = toUChar( IFIELD(theInstr, 25, 1) );
9578       UChar FM       = toUChar( IFIELD(theInstr, 17, 8) );
9579       UChar frB_addr = ifieldRegB(theInstr);
9580       IRTemp frB   = newTemp(Ity_F64);
9581       IRTemp rB_64 = newTemp( Ity_I64 );
9582       Int i;
9583       ULong mask;
9584       UChar Wbit;
9585 #define BFP_MASK_SEED 0x3000000000000000ULL
9586 #define DFP_MASK_SEED 0x7000000000000000ULL
9587 
9588       if (GX_level) {
9589          /* This implies that Decimal Floating Point is supported, and the
9590           * FPSCR must be managed as a 64-bit register.
9591           */
9592          Wbit = toUChar( IFIELD(theInstr, 16, 1) );
9593       } else {
9594          Wbit = 0;
9595       }
9596 
9597       if (b25 == 1) {
9598          /* new 64 bit move variant for power 6.  If L field (bit 25) is
9599           * a one do a full 64 bit move.  Note, the FPSCR is not really
9600           * properly modeled.  This instruciton only changes the value of
9601           * the rounding mode.  The HW exception bits do not get set in
9602           * the simulator.  1/12/09
9603           */
9604          DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC ? ".":"", FM, frB_addr);
9605          mask = 0xFF;
9606 
9607       } else {
9608          DIP("mtfsf%s %d,fr%u\n", flag_rC ? ".":"", FM, frB_addr);
9609          // Build 32bit mask from FM:
9610          mask = 0;
9611          for (i=0; i<8; i++) {
9612             if ((FM & (1<<(7-i))) == 1) {
9613                /* FPSCR field k is set to the contents of the corresponding
9614                 * field of register FRB, where k = i+8x(1-W).  In the Power
9615                 * ISA, register field numbering is from left to right, so field
9616                 * 15 is the least significant field in a 64-bit register.  To
9617                 * generate the mask, we set all the appropriate rounding mode
9618                 * bits in the highest order nibble (field 0) and shift right
9619                 * 'k x nibble length'.
9620                 */
9621                if (Wbit)
9622                   mask |= DFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) );
9623                else
9624                   mask |= BFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) );
9625             }
9626          }
9627       }
9628       assign( frB, getFReg(frB_addr));
9629       assign( rB_64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
9630       putGST_masked( PPC_GST_FPSCR, mkexpr( rB_64 ), mask );
9631       break;
9632    }
9633 
9634    default:
9635       vex_printf("dis_fp_scr(ppc)(opc2)\n");
9636       return False;
9637    }
9638    return True;
9639 }
9640 
9641 /*------------------------------------------------------------*/
9642 /*--- Decimal Floating Point (DFP)  Helper functions       ---*/
9643 /*------------------------------------------------------------*/
9644 #define DFP_LONG  1
9645 #define DFP_EXTND 2
9646 #define DFP_LONG_BIAS   398
9647 #define DFP_LONG_ENCODED_FIELD_MASK  0x1F00
9648 #define DFP_EXTND_BIAS  6176
9649 #define DFP_EXTND_ENCODED_FIELD_MASK 0x1F000
9650 #define DFP_LONG_EXP_MSK   0XFF
9651 #define DFP_EXTND_EXP_MSK  0XFFF
9652 
9653 #define DFP_G_FIELD_LONG_MASK     0x7FFC0000  // upper 32-bits only
9654 #define DFP_LONG_GFIELD_RT_SHIFT  (63 - 13 - 32) // adj for upper 32-bits
9655 #define DFP_G_FIELD_EXTND_MASK    0x7FFFC000  // upper 32-bits only
9656 #define DFP_EXTND_GFIELD_RT_SHIFT (63 - 17 - 32) //adj for upper 32 bits
9657 #define DFP_T_FIELD_LONG_MASK     0x3FFFF  // mask for upper 32-bits
9658 #define DFP_T_FIELD_EXTND_MASK    0x03FFFF // mask for upper 32-bits
9659 #define DFP_LONG_EXP_MAX          369      // biased max
9660 #define DFP_LONG_EXP_MIN          0        // biased min
9661 #define DFP_EXTND_EXP_MAX         6111     // biased max
9662 #define DFP_EXTND_EXP_MIN         0        // biased min
9663 #define DFP_LONG_MAX_SIG_DIGITS   16
9664 #define DFP_EXTND_MAX_SIG_DIGITS  34
9665 #define MAX_DIGITS_IN_STRING      8
9666 
9667 
9668 #define  AND(x, y) binop( Iop_And32, x, y )
9669 #define AND4(w, x, y, z) AND( AND( w, x ), AND( y, z ) )
9670 #define   OR(x, y) binop( Iop_Or32,  x, y )
9671 #define  OR3(x, y, z)    OR( x, OR( y, z ) )
9672 #define  OR4(w, x, y, z) OR( OR( w, x ), OR( y, z ) )
9673 #define  NOT(x) unop( Iop_1Uto32, unop( Iop_Not1, unop( Iop_32to1,  mkexpr( x ) ) ) )
9674 
9675 #define  SHL(value, by) binop( Iop_Shl32, value, mkU8( by ) )
9676 #define  SHR(value, by) binop( Iop_Shr32, value, mkU8( by ) )
9677 
9678 #define BITS5(_b4,_b3,_b2,_b1,_b0) \
9679    (((_b4) << 4) | ((_b3) << 3) | ((_b2) << 2) | \
9680     ((_b1) << 1) | ((_b0) << 0))
9681 
Gfield_encoding(IRExpr * lmexp,IRExpr * lmd32)9682 static IRExpr * Gfield_encoding( IRExpr * lmexp, IRExpr * lmd32 )
9683 {
9684    IRTemp lmd_07_mask   = newTemp( Ity_I32 );
9685    IRTemp lmd_8_mask    = newTemp( Ity_I32 );
9686    IRTemp lmd_9_mask    = newTemp( Ity_I32 );
9687    IRTemp lmexp_00_mask = newTemp( Ity_I32 );
9688    IRTemp lmexp_01_mask = newTemp( Ity_I32 );
9689    IRTemp lmexp_10_mask = newTemp( Ity_I32 );
9690    IRTemp lmd_07_val    = newTemp( Ity_I32 );
9691    IRTemp lmd_8_val     = newTemp( Ity_I32 );
9692    IRTemp lmd_9_val     = newTemp( Ity_I32 );
9693 
9694    /* The encodig is as follows:
9695     * lmd - left most digit
9696     * lme - left most 2-bits of the exponent
9697     *
9698     *    lmd
9699     *   0 - 7    (lmexp << 3) | lmd
9700     *     8      0b11000 (24 decimal) if lme=0b00;
9701     *            0b11010 (26 decimal) if lme=0b01;
9702     *            0b11100 (28 decimal) if lme=0b10;
9703     *     9      0b11001 (25 decimal) if lme=0b00;
9704     *            0b11011 (27 decimal) if lme=0b01;
9705     *            0b11101 (29 decimal) if lme=0b10;
9706     */
9707 
9708    /* Generate the masks for each condition */
9709    assign( lmd_07_mask,
9710            unop( Iop_1Sto32, binop( Iop_CmpLE32U, lmd32, mkU32( 7 ) ) ) );
9711    assign( lmd_8_mask,
9712            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 8 ) ) ) );
9713    assign( lmd_9_mask,
9714            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 9 ) ) ) );
9715    assign( lmexp_00_mask,
9716            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 0 ) ) ) );
9717    assign( lmexp_01_mask,
9718            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 1 ) ) ) );
9719    assign( lmexp_10_mask,
9720            unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 2 ) ) ) );
9721 
9722    /* Generate the values for each LMD condition, assuming the condition
9723     * is TRUE.
9724     */
9725    assign( lmd_07_val,
9726            binop( Iop_Or32, binop( Iop_Shl32, lmexp, mkU8( 3 ) ), lmd32 ) );
9727    assign( lmd_8_val,
9728            binop( Iop_Or32,
9729                   binop( Iop_Or32,
9730                          binop( Iop_And32,
9731                                 mkexpr( lmexp_00_mask ),
9732                                 mkU32( 24 ) ),
9733                          binop( Iop_And32,
9734                                 mkexpr( lmexp_01_mask ),
9735                                 mkU32( 26 ) ) ),
9736                   binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 28 ) ) ) );
9737    assign( lmd_9_val,
9738            binop( Iop_Or32,
9739                   binop( Iop_Or32,
9740                          binop( Iop_And32,
9741                                 mkexpr( lmexp_00_mask ),
9742                                 mkU32( 25 ) ),
9743                          binop( Iop_And32,
9744                                 mkexpr( lmexp_01_mask ),
9745                                 mkU32( 27 ) ) ),
9746                   binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 29 ) ) ) );
9747 
9748    /* generate the result from the possible LMD values */
9749    return binop( Iop_Or32,
9750                  binop( Iop_Or32,
9751                         binop( Iop_And32,
9752                                mkexpr( lmd_07_mask ),
9753                                mkexpr( lmd_07_val ) ),
9754                         binop( Iop_And32,
9755                                mkexpr( lmd_8_mask ),
9756                                mkexpr( lmd_8_val ) ) ),
9757                  binop( Iop_And32, mkexpr( lmd_9_mask ), mkexpr( lmd_9_val ) ) );
9758 }
9759 
Get_lmd(IRTemp * lmd,IRExpr * gfield_0_4)9760 static void Get_lmd( IRTemp * lmd, IRExpr * gfield_0_4 )
9761 {
9762    /* Extract the exponent and the left most digit of the mantissa
9763     * from the G field bits [0:4].
9764     */
9765    IRTemp lmd_07_mask   = newTemp( Ity_I32 );
9766    IRTemp lmd_8_00_mask = newTemp( Ity_I32 );
9767    IRTemp lmd_8_01_mask = newTemp( Ity_I32 );
9768    IRTemp lmd_8_10_mask = newTemp( Ity_I32 );
9769    IRTemp lmd_9_00_mask = newTemp( Ity_I32 );
9770    IRTemp lmd_9_01_mask = newTemp( Ity_I32 );
9771    IRTemp lmd_9_10_mask = newTemp( Ity_I32 );
9772 
9773    IRTemp lmd_07_val = newTemp( Ity_I32 );
9774    IRTemp lmd_8_val  = newTemp( Ity_I32 );
9775    IRTemp lmd_9_val  = newTemp( Ity_I32 );
9776 
9777    /* The left most digit (LMD) encoding is as follows:
9778     *    lmd
9779     *   0 - 7    (lmexp << 3) | lmd
9780     *     8      0b11000 (24 decimal) if lme=0b00;
9781     *            0b11010 (26 decimal) if lme=0b01;
9782     *            0b11100 (28 decimal) if lme=0b10
9783     *     9      0b11001 (25 decimal) if lme=0b00;
9784     *            0b11011 (27 decimal) if lme=0b01;
9785     *            0b11101 (29 decimal) if lme=0b10;
9786     */
9787 
9788    /* Generate the masks for each condition of LMD and exponent bits */
9789    assign( lmd_07_mask,
9790            unop( Iop_1Sto32, binop( Iop_CmpLE32U,
9791                                     gfield_0_4,
9792                                     mkU32( BITS5(1,0,1,1,1) ) ) ) );
9793    assign( lmd_8_00_mask,
9794            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9795                                     gfield_0_4,
9796                                     mkU32( BITS5(1,1,0,0,0) ) ) ) );
9797    assign( lmd_8_01_mask,
9798            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9799                                     gfield_0_4,
9800                                     mkU32( BITS5(1,1,0,1,0) ) ) ) );
9801    assign( lmd_8_10_mask,
9802            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9803                                     gfield_0_4,
9804                                     mkU32( BITS5(1,1,1,0,0) ) ) ) );
9805    assign( lmd_9_00_mask,
9806            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9807                                     gfield_0_4,
9808                                     mkU32( BITS5(1,1,0,0,1) ) ) ) );
9809    assign( lmd_9_01_mask,
9810            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9811                                     gfield_0_4,
9812                                     mkU32( BITS5(1,1,0,1,1) ) ) ) );
9813    assign( lmd_9_10_mask,
9814            unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9815                                     gfield_0_4,
9816                                     mkU32( BITS5(1,1,1,0,1) ) ) ) );
9817 
9818    /* Generate the values for each LMD condition, assuming the condition
9819     * is TRUE.
9820     */
9821    assign( lmd_07_val, binop( Iop_And32, gfield_0_4, mkU32( 0x7 ) ) );
9822    assign( lmd_8_val, mkU32( 0x8 ) );
9823    assign( lmd_9_val, mkU32( 0x9 ) );
9824 
9825    assign( *lmd,
9826            OR( OR3 ( AND( mkexpr( lmd_07_mask ), mkexpr( lmd_07_val ) ),
9827                      AND( mkexpr( lmd_8_00_mask ), mkexpr( lmd_8_val ) ),
9828                      AND( mkexpr( lmd_8_01_mask ), mkexpr( lmd_8_val ) )),
9829                      OR4( AND( mkexpr( lmd_8_10_mask ), mkexpr( lmd_8_val ) ),
9830                           AND( mkexpr( lmd_9_00_mask ), mkexpr( lmd_9_val ) ),
9831                           AND( mkexpr( lmd_9_01_mask ), mkexpr( lmd_9_val ) ),
9832                           AND( mkexpr( lmd_9_10_mask ), mkexpr( lmd_9_val ) )
9833                      ) ) );
9834 }
9835 
9836 #define DIGIT1_SHR 4    // shift digit 1 to bottom 4 bits
9837 #define DIGIT2_SHR 8    // shift digit 2 to bottom 4 bits
9838 #define DIGIT3_SHR 12
9839 #define DIGIT4_SHR 16
9840 #define DIGIT5_SHR 20
9841 #define DIGIT6_SHR 24
9842 #define DIGIT7_SHR 28
9843 
bcd_digit_inval(IRExpr * bcd_u,IRExpr * bcd_l)9844 static IRExpr * bcd_digit_inval( IRExpr * bcd_u, IRExpr * bcd_l )
9845 {
9846    /* 60-bit BCD string stored in two 32-bit values.  Check that each,
9847     * digit is a valid BCD number, i.e. less then 9.
9848     */
9849    IRTemp valid = newTemp( Ity_I32 );
9850 
9851    assign( valid,
9852            AND4( AND4 ( unop( Iop_1Sto32,
9853                               binop( Iop_CmpLE32U,
9854                                      binop( Iop_And32,
9855                                             bcd_l,
9856                                             mkU32 ( 0xF ) ),
9857                                       mkU32( 0x9 ) ) ),
9858                         unop( Iop_1Sto32,
9859                               binop( Iop_CmpLE32U,
9860                                      binop( Iop_And32,
9861                                             binop( Iop_Shr32,
9862                                                    bcd_l,
9863                                                    mkU8 ( DIGIT1_SHR ) ),
9864                                              mkU32 ( 0xF ) ),
9865                                       mkU32( 0x9 ) ) ),
9866                         unop( Iop_1Sto32,
9867                               binop( Iop_CmpLE32U,
9868                                      binop( Iop_And32,
9869                                             binop( Iop_Shr32,
9870                                                    bcd_l,
9871                                                    mkU8 ( DIGIT2_SHR ) ),
9872                                             mkU32 ( 0xF ) ),
9873                                       mkU32( 0x9 ) ) ),
9874                         unop( Iop_1Sto32,
9875                               binop( Iop_CmpLE32U,
9876                                      binop( Iop_And32,
9877                                             binop( Iop_Shr32,
9878                                                    bcd_l,
9879                                                    mkU8 ( DIGIT3_SHR ) ),
9880                                              mkU32 ( 0xF ) ),
9881                                       mkU32( 0x9 ) ) ) ),
9882                  AND4 ( unop( Iop_1Sto32,
9883                               binop( Iop_CmpLE32U,
9884                                      binop( Iop_And32,
9885                                             binop( Iop_Shr32,
9886                                                    bcd_l,
9887                                                    mkU8 ( DIGIT4_SHR ) ),
9888                                             mkU32 ( 0xF ) ),
9889                                      mkU32( 0x9 ) ) ),
9890                         unop( Iop_1Sto32,
9891                               binop( Iop_CmpLE32U,
9892                                      binop( Iop_And32,
9893                                             binop( Iop_Shr32,
9894                                                    bcd_l,
9895                                                    mkU8 ( DIGIT5_SHR ) ),
9896                                             mkU32 ( 0xF ) ),
9897                                      mkU32( 0x9 ) ) ),
9898                         unop( Iop_1Sto32,
9899                               binop( Iop_CmpLE32U,
9900                                      binop( Iop_And32,
9901                                             binop( Iop_Shr32,
9902                                                    bcd_l,
9903                                                    mkU8 ( DIGIT6_SHR ) ),
9904                                             mkU32 ( 0xF ) ),
9905                                      mkU32( 0x9 ) ) ),
9906                         unop( Iop_1Sto32,
9907                               binop( Iop_CmpLE32U,
9908                                      binop( Iop_And32,
9909                                             binop( Iop_Shr32,
9910                                                    bcd_l,
9911                                                    mkU8 ( DIGIT7_SHR ) ),
9912                                             mkU32 ( 0xF ) ),
9913                                      mkU32( 0x9 ) ) ) ),
9914                  AND4( unop( Iop_1Sto32,
9915                              binop( Iop_CmpLE32U,
9916                                     binop( Iop_And32,
9917                                            bcd_u,
9918                                            mkU32 ( 0xF ) ),
9919                                     mkU32( 0x9 ) ) ),
9920                        unop( Iop_1Sto32,
9921                              binop( Iop_CmpLE32U,
9922                                     binop( Iop_And32,
9923                                            binop( Iop_Shr32,
9924                                                   bcd_u,
9925                                                   mkU8 ( DIGIT1_SHR ) ),
9926                                            mkU32 ( 0xF ) ),
9927                                     mkU32( 0x9 ) ) ),
9928                        unop( Iop_1Sto32,
9929                              binop( Iop_CmpLE32U,
9930                                     binop( Iop_And32,
9931                                            binop( Iop_Shr32,
9932                                                   bcd_u,
9933                                                   mkU8 ( DIGIT2_SHR ) ),
9934                                            mkU32 ( 0xF ) ),
9935                                     mkU32( 0x9 ) ) ),
9936                        unop( Iop_1Sto32,
9937                              binop( Iop_CmpLE32U,
9938                                     binop( Iop_And32,
9939                                            binop( Iop_Shr32,
9940                                                   bcd_u,
9941                                                   mkU8 ( DIGIT3_SHR ) ),
9942                                            mkU32 ( 0xF ) ),
9943                                     mkU32( 0x9 ) ) ) ),
9944                  AND4( unop( Iop_1Sto32,
9945                              binop( Iop_CmpLE32U,
9946                                     binop( Iop_And32,
9947                                            binop( Iop_Shr32,
9948                                                   bcd_u,
9949                                                   mkU8 ( DIGIT4_SHR ) ),
9950                                            mkU32 ( 0xF ) ),
9951                                     mkU32( 0x9 ) ) ),
9952                        unop( Iop_1Sto32,
9953                              binop( Iop_CmpLE32U,
9954                                     binop( Iop_And32,
9955                                            binop( Iop_Shr32,
9956                                                   bcd_u,
9957                                                   mkU8 ( DIGIT5_SHR ) ),
9958                                            mkU32 ( 0xF ) ),
9959                                     mkU32( 0x9 ) ) ),
9960                        unop( Iop_1Sto32,
9961                              binop( Iop_CmpLE32U,
9962                                     binop( Iop_And32,
9963                                            binop( Iop_Shr32,
9964                                                   bcd_u,
9965                                                   mkU8 ( DIGIT6_SHR ) ),
9966                                            mkU32 ( 0xF ) ),
9967                                     mkU32( 0x9 ) ) ),
9968                        unop( Iop_1Sto32,
9969                              binop( Iop_CmpLE32U,
9970                                     binop( Iop_And32,
9971                                            binop( Iop_Shr32,
9972                                                   bcd_u,
9973                                                   mkU8 ( DIGIT7_SHR ) ),
9974                                            mkU32 ( 0xF ) ),
9975                                     mkU32( 0x9 ) ) ) ) ) );
9976 
9977    return unop( Iop_Not32, mkexpr( valid ) );
9978 }
9979 #undef DIGIT1_SHR
9980 #undef DIGIT2_SHR
9981 #undef DIGIT3_SHR
9982 #undef DIGIT4_SHR
9983 #undef DIGIT5_SHR
9984 #undef DIGIT6_SHR
9985 #undef DIGIT7_SHR
9986 
Generate_neg_sign_mask(IRExpr * sign)9987 static IRExpr * Generate_neg_sign_mask( IRExpr * sign )
9988 {
9989    return binop( Iop_Or32,
9990                  unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xB ) ) ),
9991                  unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xD ) ) )
9992                );
9993 }
9994 
Generate_pos_sign_mask(IRExpr * sign)9995 static IRExpr * Generate_pos_sign_mask( IRExpr * sign )
9996 {
9997    return binop( Iop_Or32,
9998                  binop( Iop_Or32,
9999                         unop( Iop_1Sto32,
10000                               binop( Iop_CmpEQ32, sign, mkU32( 0xA ) ) ),
10001                         unop( Iop_1Sto32,
10002                               binop( Iop_CmpEQ32, sign, mkU32( 0xC ) ) ) ),
10003                  binop( Iop_Or32,
10004                         unop( Iop_1Sto32,
10005                               binop( Iop_CmpEQ32, sign, mkU32( 0xE ) ) ),
10006                         unop( Iop_1Sto32,
10007                               binop( Iop_CmpEQ32, sign, mkU32( 0xF ) ) ) ) );
10008 }
10009 
Generate_sign_bit(IRExpr * pos_sign_mask,IRExpr * neg_sign_mask)10010 static IRExpr * Generate_sign_bit( IRExpr * pos_sign_mask,
10011                                    IRExpr * neg_sign_mask )
10012 {
10013    return binop( Iop_Or32,
10014                  binop( Iop_And32, neg_sign_mask, mkU32( 0x80000000 ) ),
10015                  binop( Iop_And32, pos_sign_mask, mkU32( 0x00000000 ) ) );
10016 }
10017 
Generate_inv_mask(IRExpr * invalid_bcd_mask,IRExpr * pos_sign_mask,IRExpr * neg_sign_mask)10018 static IRExpr * Generate_inv_mask( IRExpr * invalid_bcd_mask,
10019                                    IRExpr * pos_sign_mask,
10020                                    IRExpr * neg_sign_mask )
10021 /* first argument is all 1's if the BCD string had an invalid digit in it. */
10022 {
10023    return binop( Iop_Or32,
10024                  invalid_bcd_mask,
10025                  unop( Iop_1Sto32,
10026                        binop( Iop_CmpEQ32,
10027                               binop( Iop_Or32, pos_sign_mask, neg_sign_mask ),
10028                               mkU32( 0x0 ) ) ) );
10029 }
10030 
Generate_132_bit_bcd_string(IRExpr * frBI64_hi,IRExpr * frBI64_lo,IRTemp * top_12_l,IRTemp * mid_60_u,IRTemp * mid_60_l,IRTemp * low_60_u,IRTemp * low_60_l)10031 static void Generate_132_bit_bcd_string( IRExpr * frBI64_hi, IRExpr * frBI64_lo,
10032                                          IRTemp * top_12_l, IRTemp * mid_60_u,
10033                                          IRTemp * mid_60_l, IRTemp * low_60_u,
10034                                          IRTemp * low_60_l)
10035 {
10036    IRTemp tmplow60 = newTemp( Ity_I64 );
10037    IRTemp tmpmid60 = newTemp( Ity_I64 );
10038    IRTemp tmptop12 = newTemp( Ity_I64 );
10039    IRTemp low_50   = newTemp( Ity_I64 );
10040    IRTemp mid_50   = newTemp( Ity_I64 );
10041    IRTemp top_10   = newTemp( Ity_I64 );
10042    IRTemp top_12_u = newTemp( Ity_I32 ); // only needed for a dummy arg
10043 
10044    /* Convert the 110-bit densely packed BCD string to a 128-bit BCD string */
10045 
10046    /* low_50[49:0] = ((frBI64_lo[49:32]  << 14) | frBI64_lo[31:0]) */
10047    assign( low_50,
10048            binop( Iop_32HLto64,
10049                   binop( Iop_And32,
10050                          unop( Iop_64HIto32, frBI64_lo ),
10051                          mkU32( 0x3FFFF ) ),
10052                          unop( Iop_64to32, frBI64_lo ) ) );
10053 
10054    /* Convert the 50 bit densely packed BCD string to a 60 bit
10055     * BCD string.
10056     */
10057    assign( tmplow60, unop( Iop_DPBtoBCD, mkexpr( low_50 ) ) );
10058    assign( *low_60_u, unop( Iop_64HIto32, mkexpr( tmplow60 ) ) );
10059    assign( *low_60_l, unop( Iop_64to32, mkexpr( tmplow60 ) ) );
10060 
10061    /* mid_50[49:0] =  ((frBI64_hi[35:32] << 14) | frBI64_hi[31:18]) |
10062     *                 ((frBI64_hi[17:0]  << 14) | frBI64_lo[63:50])
10063     */
10064    assign( mid_50,
10065            binop( Iop_32HLto64,
10066                   binop( Iop_Or32,
10067                          binop( Iop_Shl32,
10068                                 binop( Iop_And32,
10069                                        unop( Iop_64HIto32, frBI64_hi ),
10070                                        mkU32( 0xF ) ),
10071                                 mkU8( 14 ) ),
10072                          binop( Iop_Shr32,
10073                                 unop( Iop_64to32, frBI64_hi ),
10074                                 mkU8( 18 ) ) ),
10075                   binop( Iop_Or32,
10076                          binop( Iop_Shl32,
10077                                 unop( Iop_64to32, frBI64_hi ),
10078                                 mkU8( 14 ) ),
10079                          binop( Iop_Shr32,
10080                                 unop( Iop_64HIto32, frBI64_lo ),
10081                                 mkU8( 18 ) ) ) ) );
10082 
10083    /* Convert the 50 bit densely packed BCD string to a 60 bit
10084     * BCD string.
10085     */
10086    assign( tmpmid60, unop( Iop_DPBtoBCD, mkexpr( mid_50 ) ) );
10087    assign( *mid_60_u, unop( Iop_64HIto32, mkexpr( tmpmid60 ) ) );
10088    assign( *mid_60_l, unop( Iop_64to32, mkexpr( tmpmid60 ) ) );
10089 
10090    /* top_10[49:0] = frBI64_hi[45:36]) |  */
10091    assign( top_10,
10092            binop( Iop_32HLto64,
10093                   mkU32( 0 ),
10094                   binop( Iop_And32,
10095                          binop( Iop_Shr32,
10096                                 unop( Iop_64HIto32, frBI64_hi ),
10097                                 mkU8( 4 ) ),
10098                          mkU32( 0x3FF ) ) ) );
10099 
10100    /* Convert the 10 bit densely packed BCD string to a 12 bit
10101     * BCD string.
10102     */
10103    assign( tmptop12, unop( Iop_DPBtoBCD, mkexpr( top_10 ) ) );
10104    assign( top_12_u, unop( Iop_64HIto32, mkexpr( tmptop12 ) ) );
10105    assign( *top_12_l, unop( Iop_64to32, mkexpr( tmptop12 ) ) );
10106 }
10107 
Count_zeros(int start,IRExpr * init_cnt,IRExpr * init_flag,IRTemp * final_cnt,IRTemp * final_flag,IRExpr * string)10108 static void Count_zeros( int start, IRExpr * init_cnt, IRExpr * init_flag,
10109                          IRTemp * final_cnt, IRTemp * final_flag,
10110                          IRExpr * string )
10111 {
10112    IRTemp cnt[MAX_DIGITS_IN_STRING + 1];IRTemp flag[MAX_DIGITS_IN_STRING+1];
10113    int digits = MAX_DIGITS_IN_STRING;
10114    int i;
10115 
10116    cnt[start-1] = newTemp( Ity_I8 );
10117    flag[start-1] = newTemp( Ity_I8 );
10118    assign( cnt[start-1], init_cnt);
10119    assign( flag[start-1], init_flag);
10120 
10121    for ( i = start; i <= digits; i++) {
10122       cnt[i] = newTemp( Ity_I8 );
10123       flag[i] = newTemp( Ity_I8 );
10124       assign( cnt[i],
10125               binop( Iop_Add8,
10126                      mkexpr( cnt[i-1] ),
10127                      binop(Iop_And8,
10128                            unop( Iop_1Uto8,
10129                                  binop(Iop_CmpEQ32,
10130                                        binop(Iop_And32,
10131                                              string,
10132                                              mkU32( 0xF <<
10133                                                     ( ( digits - i ) * 4) ) ),
10134                                        mkU32( 0 ) ) ),
10135                            binop( Iop_Xor8, /* complement flag */
10136                                   mkexpr( flag[i - 1] ),
10137                                   mkU8( 0xFF ) ) ) ) );
10138 
10139       /* set flag to 1 if digit was not a zero */
10140       assign( flag[i],
10141               binop(Iop_Or8,
10142                     unop( Iop_1Sto8,
10143                           binop(Iop_CmpNE32,
10144                                 binop(Iop_And32,
10145                                       string,
10146                                       mkU32( 0xF <<
10147                                              ( (digits - i) * 4) ) ),
10148                                 mkU32( 0 ) ) ),
10149                     mkexpr( flag[i - 1] ) ) );
10150    }
10151 
10152    *final_cnt = cnt[digits];
10153    *final_flag = flag[digits];
10154 }
10155 
Count_leading_zeros_60(IRExpr * lmd,IRExpr * upper_28,IRExpr * low_32)10156 static IRExpr * Count_leading_zeros_60( IRExpr * lmd, IRExpr * upper_28,
10157                                         IRExpr * low_32 )
10158 {
10159    IRTemp num_lmd    = newTemp( Ity_I8 );
10160    IRTemp num_upper  = newTemp( Ity_I8 );
10161    IRTemp num_low    = newTemp( Ity_I8 );
10162    IRTemp lmd_flag   = newTemp( Ity_I8 );
10163    IRTemp upper_flag = newTemp( Ity_I8 );
10164    IRTemp low_flag   = newTemp( Ity_I8 );
10165 
10166    assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) );
10167    assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) );
10168 
10169    Count_zeros( 2,
10170                 mkexpr( num_lmd ),
10171                 mkexpr( lmd_flag ),
10172                 &num_upper,
10173                 &upper_flag,
10174                 upper_28 );
10175 
10176    Count_zeros( 1,
10177                 mkexpr( num_upper ),
10178                 mkexpr( upper_flag ),
10179                 &num_low,
10180                 &low_flag,
10181                 low_32 );
10182 
10183    return mkexpr( num_low );
10184 }
10185 
Count_leading_zeros_128(IRExpr * lmd,IRExpr * top_12_l,IRExpr * mid_60_u,IRExpr * mid_60_l,IRExpr * low_60_u,IRExpr * low_60_l)10186 static IRExpr * Count_leading_zeros_128( IRExpr * lmd, IRExpr * top_12_l,
10187                                          IRExpr * mid_60_u, IRExpr * mid_60_l,
10188                                          IRExpr * low_60_u, IRExpr * low_60_l)
10189 {
10190    IRTemp num_lmd   = newTemp( Ity_I8 );
10191    IRTemp num_top   = newTemp( Ity_I8 );
10192    IRTemp num_mid_u = newTemp( Ity_I8 );
10193    IRTemp num_mid_l = newTemp( Ity_I8 );
10194    IRTemp num_low_u = newTemp( Ity_I8 );
10195    IRTemp num_low_l = newTemp( Ity_I8 );
10196 
10197    IRTemp lmd_flag   = newTemp( Ity_I8 );
10198    IRTemp top_flag   = newTemp( Ity_I8 );
10199    IRTemp mid_u_flag = newTemp( Ity_I8 );
10200    IRTemp mid_l_flag = newTemp( Ity_I8 );
10201    IRTemp low_u_flag = newTemp( Ity_I8 );
10202    IRTemp low_l_flag = newTemp( Ity_I8 );
10203 
10204    /* Check the LMD, digit 16, to see if it is zero. */
10205    assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) );
10206 
10207    assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) );
10208 
10209    Count_zeros( 6,
10210                 mkexpr( num_lmd ),
10211                 mkexpr( lmd_flag ),
10212                 &num_top,
10213                 &top_flag,
10214                 top_12_l );
10215 
10216    Count_zeros( 1,
10217                 mkexpr( num_top ),
10218                 mkexpr( top_flag ),
10219                 &num_mid_u,
10220                 &mid_u_flag,
10221                 binop( Iop_Or32,
10222                        binop( Iop_Shl32, mid_60_u, mkU8( 2 ) ),
10223                        binop( Iop_Shr32, mid_60_l, mkU8( 30 ) ) ) );
10224 
10225    Count_zeros( 2,
10226                 mkexpr( num_mid_u ),
10227                 mkexpr( mid_u_flag ),
10228                 &num_mid_l,
10229                 &mid_l_flag,
10230                 mid_60_l );
10231 
10232    Count_zeros( 1,
10233                 mkexpr( num_mid_l ),
10234                 mkexpr( mid_l_flag ),
10235                 &num_low_u,
10236                 &low_u_flag,
10237                 binop( Iop_Or32,
10238                        binop( Iop_Shl32, low_60_u, mkU8( 2 ) ),
10239                        binop( Iop_Shr32, low_60_l, mkU8( 30 ) ) ) );
10240 
10241    Count_zeros( 2,
10242                 mkexpr( num_low_u ),
10243                 mkexpr( low_u_flag ),
10244                 &num_low_l,
10245                 &low_l_flag,
10246                 low_60_l );
10247 
10248    return mkexpr( num_low_l );
10249 }
10250 
Check_unordered(IRExpr * val)10251 static IRExpr * Check_unordered(IRExpr * val)
10252 {
10253    IRTemp gfield0to5 = newTemp( Ity_I32 );
10254 
10255    /* Extract G[0:4] */
10256    assign( gfield0to5,
10257            binop( Iop_And32,
10258                   binop( Iop_Shr32, unop( Iop_64HIto32, val ), mkU8( 26 ) ),
10259                   mkU32( 0x1F ) ) );
10260 
10261    /* Check for unordered, return all 1'x if true */
10262    return binop( Iop_Or32, /* QNaN check */
10263                  unop( Iop_1Sto32,
10264                        binop( Iop_CmpEQ32,
10265                               mkexpr( gfield0to5 ),
10266                               mkU32( 0x1E ) ) ),
10267                               unop( Iop_1Sto32, /* SNaN check */
10268                                     binop( Iop_CmpEQ32,
10269                                            mkexpr( gfield0to5 ),
10270                                            mkU32( 0x1F ) ) ) );
10271 }
10272 
10273 #undef AND
10274 #undef AND4
10275 #undef OR
10276 #undef OR3
10277 #undef OR4
10278 #undef NOT
10279 #undef SHR
10280 #undef SHL
10281 #undef BITS5
10282 
10283 /*------------------------------------------------------------*/
10284 /*--- Decimal Floating Point (DFP) instruction translation ---*/
10285 /*------------------------------------------------------------*/
10286 
10287 /* DFP Arithmetic instructions */
dis_dfp_arith(UInt theInstr)10288 static Bool dis_dfp_arith(UInt theInstr)
10289 {
10290    UInt opc2 = ifieldOPClo10( theInstr );
10291    UChar frS_addr = ifieldRegDS( theInstr );
10292    UChar frA_addr = ifieldRegA( theInstr );
10293    UChar frB_addr = ifieldRegB( theInstr );
10294    UChar flag_rC = ifieldBIT0( theInstr );
10295 
10296    IRTemp frA = newTemp( Ity_D64 );
10297    IRTemp frB = newTemp( Ity_D64 );
10298    IRTemp frS = newTemp( Ity_D64 );
10299    IRExpr* round = get_IR_roundingmode_DFP();
10300 
10301    /* By default, if flag_RC is set, we will clear cr1 after the
10302     * operation.  In reality we should set cr1 to indicate the
10303     * exception status of the operation, but since we're not
10304     * simulating exceptions, the exception status will appear to be
10305     * zero.  Hence cr1 should be cleared if this is a . form insn.
10306     */
10307    Bool clear_CR1 = True;
10308 
10309    assign( frA, getDReg( frA_addr ) );
10310    assign( frB, getDReg( frB_addr ) );
10311 
10312    switch (opc2) {
10313    case 0x2: // dadd
10314       DIP( "dadd%s fr%u,fr%u,fr%u\n",
10315            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10316       assign( frS, triop( Iop_AddD64, round, mkexpr( frA ), mkexpr( frB ) ) );
10317       break;
10318    case 0x202: // dsub
10319       DIP( "dsub%s fr%u,fr%u,fr%u\n",
10320            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10321       assign( frS, triop( Iop_SubD64, round, mkexpr( frA ), mkexpr( frB ) ) );
10322       break;
10323    case 0x22: // dmul
10324       DIP( "dmul%s fr%u,fr%u,fr%u\n",
10325            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10326       assign( frS, triop( Iop_MulD64, round, mkexpr( frA ), mkexpr( frB ) ) );
10327       break;
10328    case 0x222: // ddiv
10329       DIP( "ddiv%s fr%u,fr%u,fr%u\n",
10330            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10331       assign( frS, triop( Iop_DivD64, round, mkexpr( frA ), mkexpr( frB ) ) );
10332       break;
10333    }
10334 
10335    putDReg( frS_addr, mkexpr( frS ) );
10336 
10337    if (flag_rC && clear_CR1) {
10338       putCR321( 1, mkU8( 0 ) );
10339       putCR0( 1, mkU8( 0 ) );
10340    }
10341 
10342    return True;
10343 }
10344 
10345 /* Quad DFP Arithmetic instructions */
dis_dfp_arithq(UInt theInstr)10346 static Bool dis_dfp_arithq(UInt theInstr)
10347 {
10348    UInt opc2 = ifieldOPClo10( theInstr );
10349    UChar frS_addr = ifieldRegDS( theInstr );
10350    UChar frA_addr = ifieldRegA( theInstr );
10351    UChar frB_addr = ifieldRegB( theInstr );
10352    UChar flag_rC = ifieldBIT0( theInstr );
10353 
10354    IRTemp frA = newTemp( Ity_D128 );
10355    IRTemp frB = newTemp( Ity_D128 );
10356    IRTemp frS = newTemp( Ity_D128 );
10357    IRExpr* round = get_IR_roundingmode_DFP();
10358 
10359    /* By default, if flag_RC is set, we will clear cr1 after the
10360     * operation.  In reality we should set cr1 to indicate the
10361     * exception status of the operation, but since we're not
10362     * simulating exceptions, the exception status will appear to be
10363     * zero.  Hence cr1 should be cleared if this is a . form insn.
10364     */
10365    Bool clear_CR1 = True;
10366 
10367    assign( frA, getDReg_pair( frA_addr ) );
10368    assign( frB, getDReg_pair( frB_addr ) );
10369 
10370    switch (opc2) {
10371    case 0x2: // daddq
10372       DIP( "daddq%s fr%u,fr%u,fr%u\n",
10373            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10374       assign( frS, triop( Iop_AddD128, round, mkexpr( frA ), mkexpr( frB ) ) );
10375       break;
10376    case 0x202: // dsubq
10377       DIP( "dsubq%s fr%u,fr%u,fr%u\n",
10378            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10379       assign( frS, triop( Iop_SubD128, round, mkexpr( frA ), mkexpr( frB ) ) );
10380       break;
10381    case 0x22: // dmulq
10382       DIP( "dmulq%s fr%u,fr%u,fr%u\n",
10383            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10384       assign( frS, triop( Iop_MulD128, round, mkexpr( frA ), mkexpr( frB ) ) );
10385       break;
10386    case 0x222: // ddivq
10387       DIP( "ddivq%s fr%u,fr%u,fr%u\n",
10388            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10389       assign( frS, triop( Iop_DivD128, round, mkexpr( frA ), mkexpr( frB ) ) );
10390       break;
10391    }
10392 
10393    putDReg_pair( frS_addr, mkexpr( frS ) );
10394 
10395    if (flag_rC && clear_CR1) {
10396       putCR321( 1, mkU8( 0 ) );
10397       putCR0( 1, mkU8( 0 ) );
10398    }
10399 
10400    return True;
10401 }
10402 
10403 /* DFP 64-bit logical shift instructions  */
dis_dfp_shift(UInt theInstr)10404 static Bool dis_dfp_shift(UInt theInstr) {
10405    UInt opc2       = ifieldOPClo9( theInstr );
10406    UChar frS_addr  = ifieldRegDS( theInstr );
10407    UChar frA_addr  = ifieldRegA( theInstr );
10408    UChar shift_val = IFIELD(theInstr, 10, 6);
10409    UChar flag_rC   = ifieldBIT0( theInstr );
10410 
10411    IRTemp frA = newTemp( Ity_D64 );
10412    IRTemp frS = newTemp( Ity_D64 );
10413    Bool clear_CR1 = True;
10414 
10415    assign( frA, getDReg( frA_addr ) );
10416 
10417    switch (opc2) {
10418    case 0x42: // dscli
10419       DIP( "dscli%s fr%u,fr%u,%u\n",
10420            flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
10421       assign( frS, binop( Iop_ShlD64, mkexpr( frA ), mkU8( shift_val ) ) );
10422       break;
10423    case 0x62: // dscri
10424       DIP( "dscri%s fr%u,fr%u,%u\n",
10425            flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
10426       assign( frS, binop( Iop_ShrD64, mkexpr( frA ), mkU8( shift_val ) ) );
10427       break;
10428    }
10429 
10430    putDReg( frS_addr, mkexpr( frS ) );
10431 
10432    if (flag_rC && clear_CR1) {
10433       putCR321( 1, mkU8( 0 ) );
10434       putCR0( 1, mkU8( 0 ) );
10435    }
10436 
10437    return True;
10438 }
10439 
10440 /* Quad DFP  logical shift instructions  */
dis_dfp_shiftq(UInt theInstr)10441 static Bool dis_dfp_shiftq(UInt theInstr) {
10442    UInt opc2       = ifieldOPClo9( theInstr );
10443    UChar frS_addr  = ifieldRegDS( theInstr );
10444    UChar frA_addr  = ifieldRegA( theInstr );
10445    UChar shift_val = IFIELD(theInstr, 10, 6);
10446    UChar flag_rC   = ifieldBIT0( theInstr );
10447 
10448    IRTemp frA = newTemp( Ity_D128 );
10449    IRTemp frS = newTemp( Ity_D128 );
10450    Bool clear_CR1 = True;
10451 
10452    assign( frA, getDReg_pair( frA_addr ) );
10453 
10454    switch (opc2) {
10455    case 0x42: // dscliq
10456       DIP( "dscliq%s fr%u,fr%u,%u\n",
10457            flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
10458       assign( frS, binop( Iop_ShlD128, mkexpr( frA ), mkU8( shift_val ) ) );
10459       break;
10460    case 0x62: // dscriq
10461       DIP( "dscriq%s fr%u,fr%u,%u\n",
10462            flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
10463       assign( frS, binop( Iop_ShrD128, mkexpr( frA ), mkU8( shift_val ) ) );
10464       break;
10465    }
10466 
10467    putDReg_pair( frS_addr, mkexpr( frS ) );
10468 
10469    if (flag_rC && clear_CR1) {
10470       putCR321( 1, mkU8( 0 ) );
10471       putCR0( 1, mkU8( 0 ) );
10472    }
10473 
10474    return True;
10475 }
10476 
10477 /* DFP 64-bit format conversion instructions */
dis_dfp_fmt_conv(UInt theInstr)10478 static Bool dis_dfp_fmt_conv(UInt theInstr) {
10479    UInt opc2      = ifieldOPClo10( theInstr );
10480    UChar frS_addr = ifieldRegDS( theInstr );
10481    UChar frB_addr = ifieldRegB( theInstr );
10482    IRExpr* round  = get_IR_roundingmode_DFP();
10483    UChar flag_rC  = ifieldBIT0( theInstr );
10484    IRTemp frB;
10485    IRTemp frS;
10486    Bool clear_CR1 = True;
10487 
10488    switch (opc2) {
10489    case 0x102: //dctdp
10490       DIP( "dctdp%s fr%u,fr%u\n",
10491            flag_rC ? ".":"", frS_addr, frB_addr );
10492 
10493       frB = newTemp( Ity_D32 );
10494       frS = newTemp( Ity_D64 );
10495       assign( frB, getDReg32( frB_addr ) );
10496       assign( frS, unop( Iop_D32toD64, mkexpr( frB ) ) );
10497       putDReg( frS_addr, mkexpr( frS ) );
10498       break;
10499    case 0x302: // drsp
10500       DIP( "drsp%s fr%u,fr%u\n",
10501            flag_rC ? ".":"", frS_addr, frB_addr );
10502       frB = newTemp( Ity_D64 );
10503       frS = newTemp( Ity_D32 );
10504       assign( frB, getDReg( frB_addr ) );
10505       assign( frS, binop( Iop_D64toD32, round, mkexpr( frB ) ) );
10506       putDReg32( frS_addr, mkexpr( frS ) );
10507       break;
10508    case 0x122: // dctfix
10509       {
10510          IRTemp tmp = newTemp( Ity_I64 );
10511 
10512          DIP( "dctfix%s fr%u,fr%u\n",
10513               flag_rC ? ".":"", frS_addr, frB_addr );
10514          frB = newTemp( Ity_D64 );
10515          frS = newTemp( Ity_D64 );
10516          assign( frB, getDReg( frB_addr ) );
10517          assign( tmp, binop( Iop_D64toI64S, round, mkexpr( frB ) ) );
10518          assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
10519          putDReg( frS_addr, mkexpr( frS ) );
10520       }
10521       break;
10522    case 0x322: // dcffix
10523       DIP( "dcffix%s fr%u,fr%u\n",
10524            flag_rC ? ".":"", frS_addr, frB_addr );
10525       frB = newTemp( Ity_D64 );
10526       frS = newTemp( Ity_D64 );
10527       assign( frB, getDReg( frB_addr ) );
10528       assign( frS, binop( Iop_I64StoD64,
10529                           round,
10530                           unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ) );
10531       putDReg( frS_addr, mkexpr( frS ) );
10532       break;
10533    }
10534 
10535    if (flag_rC && clear_CR1) {
10536       putCR321( 1, mkU8( 0 ) );
10537       putCR0( 1, mkU8( 0 ) );
10538    }
10539 
10540    return True;
10541 }
10542 
10543 /* Quad DFP format conversion instructions */
dis_dfp_fmt_convq(UInt theInstr)10544 static Bool dis_dfp_fmt_convq(UInt theInstr) {
10545    UInt opc2      = ifieldOPClo10( theInstr );
10546    UChar frS_addr = ifieldRegDS( theInstr );
10547    UChar frB_addr = ifieldRegB( theInstr );
10548    IRExpr* round  = get_IR_roundingmode_DFP();
10549    IRTemp frB64   = newTemp( Ity_D64 );
10550    IRTemp frB128  = newTemp( Ity_D128 );
10551    IRTemp frS64   = newTemp( Ity_D64 );
10552    IRTemp frS128  = newTemp( Ity_D128 );
10553    UChar flag_rC  = ifieldBIT0( theInstr );
10554    Bool clear_CR1 = True;
10555 
10556    switch (opc2) {
10557    case 0x102: // dctqpq
10558       DIP( "dctqpq%s fr%u,fr%u\n",
10559            flag_rC ? ".":"", frS_addr, frB_addr );
10560       assign( frB64, getDReg( frB_addr ) );
10561       assign( frS128, unop( Iop_D64toD128, mkexpr( frB64 ) ) );
10562       putDReg_pair( frS_addr, mkexpr( frS128 ) );
10563       break;
10564    case 0x122: // dctfixq
10565       {
10566          IRTemp tmp = newTemp( Ity_I64 );
10567 
10568          DIP( "dctfixq%s fr%u,fr%u\n",
10569               flag_rC ? ".":"", frS_addr, frB_addr );
10570          assign( frB128, getDReg_pair( frB_addr ) );
10571          assign( tmp, binop( Iop_D128toI64S, round, mkexpr( frB128 ) ) );
10572          assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
10573          putDReg( frS_addr, mkexpr( frS64 ) );
10574       }
10575       break;
10576    case 0x302: //drdpq
10577       DIP( "drdpq%s fr%u,fr%u\n",
10578            flag_rC ? ".":"", frS_addr, frB_addr );
10579       assign( frB128, getDReg_pair( frB_addr ) );
10580       assign( frS64, binop( Iop_D128toD64, round, mkexpr( frB128 ) ) );
10581       putDReg( frS_addr, mkexpr( frS64 ) );
10582       break;
10583    case 0x322: // dcffixq
10584      {
10585       /* Have to introduce an IOP for this instruction so it will work
10586        * on POWER 6 because emulating the instruction requires a POWER 7
10587        * DFP instruction in the emulation code.
10588        */
10589       DIP( "dcffixq%s fr%u,fr%u\n",
10590            flag_rC ? ".":"", frS_addr, frB_addr );
10591       assign( frB64, getDReg( frB_addr ) );
10592       assign( frS128, unop( Iop_I64StoD128,
10593                             unop( Iop_ReinterpD64asI64,
10594                                   mkexpr( frB64 ) ) ) );
10595       putDReg_pair( frS_addr, mkexpr( frS128 ) );
10596       break;
10597      }
10598    }
10599 
10600    if (flag_rC && clear_CR1) {
10601       putCR321( 1, mkU8( 0 ) );
10602       putCR0( 1, mkU8( 0 ) );
10603    }
10604 
10605    return True;
10606 }
10607 
dis_dfp_round(UInt theInstr)10608 static Bool dis_dfp_round( UInt theInstr ) {
10609    UChar frS_addr = ifieldRegDS(theInstr);
10610    UChar R        = IFIELD(theInstr, 16, 1);
10611    UChar RMC      = IFIELD(theInstr, 9, 2);
10612    UChar frB_addr = ifieldRegB( theInstr );
10613    UChar flag_rC  = ifieldBIT0( theInstr );
10614    IRTemp frB     = newTemp( Ity_D64 );
10615    IRTemp frS     = newTemp( Ity_D64 );
10616    UInt opc2      = ifieldOPClo8( theInstr );
10617    Bool clear_CR1 = True;
10618 
10619    switch (opc2) {
10620    /* drintn, is the same as drintx.  The only difference is this
10621     * instruction does not generate an exception for an inexact operation.
10622     * Currently not supporting inexact exceptions.
10623     */
10624    case 0x63: // drintx
10625    case 0xE3: // drintn
10626       DIP( "drintx/drintn%s fr%u,fr%u\n",
10627            flag_rC ? ".":"", frS_addr, frB_addr );
10628 
10629       /* NOTE, this instruction takes a DFP value and rounds to the
10630        * neares floating point integer value, i.e. fractional part
10631        * is zero.  The result is a floating point number.
10632        */
10633       /* pass the value of R and RMC in the same field */
10634       assign( frB, getDReg( frB_addr ) );
10635       assign( frS, binop( Iop_RoundD64toInt,
10636                           mkU32( ( R << 3 ) | RMC ),
10637                           mkexpr( frB ) ) );
10638       putDReg( frS_addr, mkexpr( frS ) );
10639       break;
10640    default:
10641       vex_printf("dis_dfp_round(ppc)(opc2)\n");
10642       return False;
10643    }
10644 
10645    if (flag_rC && clear_CR1) {
10646       putCR321( 1, mkU8( 0 ) );
10647       putCR0( 1, mkU8( 0 ) );
10648    }
10649 
10650    return True;
10651 }
10652 
dis_dfp_roundq(UInt theInstr)10653 static Bool dis_dfp_roundq(UInt theInstr) {
10654    UChar frS_addr = ifieldRegDS( theInstr );
10655    UChar frB_addr = ifieldRegB( theInstr );
10656    UChar R = IFIELD(theInstr, 16, 1);
10657    UChar RMC = IFIELD(theInstr, 9, 2);
10658    UChar flag_rC = ifieldBIT0( theInstr );
10659    IRTemp frB = newTemp( Ity_D128 );
10660    IRTemp frS = newTemp( Ity_D128 );
10661    Bool clear_CR1 = True;
10662    UInt opc2 = ifieldOPClo8( theInstr );
10663 
10664    switch (opc2) {
10665    /* drintnq, is the same as drintxq.  The only difference is this
10666     * instruction does not generate an exception for an inexact operation.
10667     * Currently not supporting inexact exceptions.
10668     */
10669    case 0x63: // drintxq
10670    case 0xE3: // drintnq
10671       DIP( "drintxq/drintnq%s fr%u,fr%u\n",
10672            flag_rC ? ".":"", frS_addr, frB_addr );
10673 
10674       /* pass the value of R and RMC in the same field */
10675       assign( frB, getDReg_pair( frB_addr ) );
10676       assign( frS, binop( Iop_RoundD128toInt,
10677                           mkU32( ( R << 3 ) | RMC ),
10678                           mkexpr( frB ) ) );
10679       putDReg_pair( frS_addr, mkexpr( frS ) );
10680       break;
10681    default:
10682       vex_printf("dis_dfp_roundq(ppc)(opc2)\n");
10683       return False;
10684    }
10685 
10686    if (flag_rC && clear_CR1) {
10687       putCR321( 1, mkU8( 0 ) );
10688       putCR0( 1, mkU8( 0 ) );
10689    }
10690 
10691    return True;
10692 }
10693 
dis_dfp_quantize_sig_rrnd(UInt theInstr)10694 static Bool dis_dfp_quantize_sig_rrnd(UInt theInstr) {
10695    UInt opc2 = ifieldOPClo8( theInstr );
10696    UChar frS_addr = ifieldRegDS( theInstr );
10697    UChar frA_addr = ifieldRegA( theInstr );
10698    UChar frB_addr = ifieldRegB( theInstr );
10699    UChar flag_rC = ifieldBIT0( theInstr );
10700    UInt TE_value = IFIELD(theInstr, 16, 4);
10701    UInt TE_sign  = IFIELD(theInstr, 20, 1);
10702    UInt RMC = IFIELD(theInstr, 9, 2);
10703    IRTemp frA = newTemp( Ity_D64 );
10704    IRTemp frB = newTemp( Ity_D64 );
10705    IRTemp frS = newTemp( Ity_D64 );
10706    Bool clear_CR1 = True;
10707 
10708    assign( frB, getDReg( frB_addr ) );
10709 
10710    switch (opc2) {
10711    case 0x43: // dquai
10712       DIP( "dquai%s fr%u,fr%u,fr%u\n",
10713            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10714       IRTemp TE_I64 = newTemp( Ity_I64 );
10715 
10716       /* Generate a reference DFP value frA with the desired exponent
10717        * given by TE using significand from frB.  Need to add the bias
10718        * 398 to TE.  TE is stored as a 2's complement number.
10719        */
10720       if (TE_sign == 1) {
10721          /* Take 2's complement of the 5-bit value and subtract from bias.
10722           *  Bias is adjusted for the +1 required when taking 2's complement.
10723           */
10724          assign( TE_I64,
10725                  unop( Iop_32Uto64,
10726                        binop( Iop_Sub32, mkU32( 397 ),
10727                               binop( Iop_And32, mkU32( 0xF ),
10728                                      unop( Iop_Not32, mkU32( TE_value ) )
10729                                      ) ) ) );
10730 
10731       } else {
10732           assign( TE_I64,
10733                   unop( Iop_32Uto64,
10734                         binop( Iop_Add32, mkU32( 398 ), mkU32( TE_value ) )
10735                         ) );
10736       }
10737 
10738       assign( frA, binop( Iop_InsertExpD64, mkexpr( TE_I64 ),
10739                           unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) );
10740 
10741       assign( frS, triop( Iop_QuantizeD64,
10742                           mkU32( RMC ),
10743                           mkexpr( frA ),
10744                           mkexpr( frB ) ) );
10745       break;
10746 
10747    case 0x3: // dqua
10748       DIP( "dqua%s fr%u,fr%u,fr%u\n",
10749            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10750       assign( frA, getDReg( frA_addr ) );
10751       assign( frS, triop( Iop_QuantizeD64,
10752                           mkU32( RMC ),
10753                           mkexpr( frA ),
10754                           mkexpr( frB ) ) );
10755       break;
10756    case 0x23: // drrnd
10757       {
10758          IRTemp tmp = newTemp( Ity_I8 );
10759 
10760          DIP( "drrnd%s fr%u,fr%u,fr%u\n",
10761               flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10762          assign( frA, getDReg( frA_addr ) );
10763          /* Iop_64to8 not supported in 32 bit mode, do it in two steps. */
10764          assign( tmp, unop( Iop_32to8,
10765                             unop( Iop_64to32,
10766                                   unop( Iop_ReinterpD64asI64,
10767                                         mkexpr( frA ) ) ) ) );
10768          assign( frS, triop( Iop_SignificanceRoundD64,
10769                              mkU32( RMC ),
10770                              mkexpr( tmp ),
10771                              mkexpr( frB ) ) );
10772       }
10773       break;
10774    default:
10775       vex_printf("dis_dfp_quantize_sig_rrnd(ppc)(opc2)\n");
10776       return False;
10777    }
10778    putDReg( frS_addr, mkexpr( frS ) );
10779 
10780    if (flag_rC && clear_CR1) {
10781       putCR321( 1, mkU8( 0 ) );
10782       putCR0( 1, mkU8( 0 ) );
10783    }
10784 
10785    return True;
10786 }
10787 
dis_dfp_quantize_sig_rrndq(UInt theInstr)10788 static Bool dis_dfp_quantize_sig_rrndq(UInt theInstr) {
10789    UInt opc2 = ifieldOPClo8( theInstr );
10790    UChar frS_addr = ifieldRegDS( theInstr );
10791    UChar frA_addr = ifieldRegA( theInstr );
10792    UChar frB_addr = ifieldRegB( theInstr );
10793    UChar flag_rC = ifieldBIT0( theInstr );
10794    UInt TE_value = IFIELD(theInstr, 16, 4);
10795    UInt TE_sign  = IFIELD(theInstr, 20, 1);
10796    UInt RMC = IFIELD(theInstr, 9, 2);
10797    IRTemp frA = newTemp( Ity_D128 );
10798    IRTemp frB = newTemp( Ity_D128 );
10799    IRTemp frS = newTemp( Ity_D128 );
10800    Bool clear_CR1 = True;
10801 
10802    assign( frB, getDReg_pair( frB_addr ) );
10803 
10804    switch (opc2) {
10805    case 0x43: // dquaiq
10806       DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
10807            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10808       IRTemp TE_I64 = newTemp( Ity_I64 );
10809 
10810       /* Generate a reference DFP value frA with the desired exponent
10811        * given by TE using significand of 1.  Need to add the bias
10812        * 6176 to TE.
10813        */
10814       if (TE_sign == 1) {
10815          /* Take 2's complement of the 5-bit value and subtract from bias.
10816           *  Bias adjusted for the +1 required when taking 2's complement.
10817           */
10818          assign( TE_I64,
10819                  unop( Iop_32Uto64,
10820                        binop( Iop_Sub32, mkU32( 6175 ),
10821                               binop( Iop_And32, mkU32( 0xF ),
10822                                      unop( Iop_Not32, mkU32( TE_value ) )
10823                                      ) ) ) );
10824 
10825       } else {
10826          assign( TE_I64,
10827                  unop( Iop_32Uto64,
10828                        binop( Iop_Add32,
10829                              mkU32( 6176 ),
10830                              mkU32( TE_value ) ) ) );
10831       }
10832 
10833       assign( frA,
10834               binop( Iop_InsertExpD128, mkexpr( TE_I64 ),
10835                      unop( Iop_D64toD128,
10836                            unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) ) );
10837       assign( frS, triop( Iop_QuantizeD128,
10838                           mkU32( RMC ),
10839                           mkexpr( frA ),
10840                           mkexpr( frB ) ) );
10841       break;
10842    case 0x3: // dquaq
10843       DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
10844            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10845       assign( frA, getDReg_pair( frA_addr ) );
10846       assign( frS, triop( Iop_QuantizeD128,
10847                           mkU32( RMC ),
10848                           mkexpr( frA ),
10849                           mkexpr( frB ) ) );
10850       break;
10851    case 0x23: // drrndq
10852       {
10853          IRTemp tmp = newTemp( Ity_I8 );
10854 
10855          DIP( "drrndq%s fr%u,fr%u,fr%u\n",
10856               flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10857          assign( frA, getDReg_pair( frA_addr ) );
10858          assign( tmp, unop( Iop_32to8,
10859                             unop( Iop_64to32,
10860                                   unop( Iop_ReinterpD64asI64,
10861                                         unop( Iop_D128HItoD64,
10862                                               mkexpr( frA ) ) ) ) ) );
10863          assign( frS, triop( Iop_SignificanceRoundD128,
10864                              mkU32( RMC ),
10865                              mkexpr( tmp ),
10866                              mkexpr( frB ) ) );
10867       }
10868       break;
10869    default:
10870       vex_printf("dis_dfp_quantize_sig_rrndq(ppc)(opc2)\n");
10871       return False;
10872    }
10873    putDReg_pair( frS_addr, mkexpr( frS ) );
10874 
10875    if (flag_rC && clear_CR1) {
10876       putCR321( 1, mkU8( 0 ) );
10877       putCR0( 1, mkU8( 0 ) );
10878    }
10879 
10880    return True;
10881 }
10882 
dis_dfp_extract_insert(UInt theInstr)10883 static Bool dis_dfp_extract_insert(UInt theInstr) {
10884    UInt opc2 = ifieldOPClo10( theInstr );
10885    UChar frS_addr = ifieldRegDS( theInstr );
10886    UChar frA_addr = ifieldRegA( theInstr );
10887    UChar frB_addr = ifieldRegB( theInstr );
10888    UChar flag_rC = ifieldBIT0( theInstr );
10889    Bool clear_CR1 = True;
10890 
10891    IRTemp frA = newTemp( Ity_D64 );
10892    IRTemp frB = newTemp( Ity_D64 );
10893    IRTemp frS = newTemp( Ity_D64 );
10894    IRTemp tmp = newTemp( Ity_I64 );
10895 
10896    assign( frA, getDReg( frA_addr ) );
10897    assign( frB, getDReg( frB_addr ) );
10898 
10899    switch (opc2) {
10900    case 0x162: // dxex
10901       DIP( "dxex%s fr%u,fr%u,fr%u\n",
10902            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10903       assign( tmp, unop( Iop_ExtractExpD64, mkexpr( frB ) ) );
10904       assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
10905       break;
10906    case 0x362: // diex
10907       DIP( "diex%s fr%u,fr%u,fr%u\n",
10908            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10909       assign( frS, binop( Iop_InsertExpD64,
10910                           unop( Iop_ReinterpD64asI64,
10911                                 mkexpr( frA ) ),
10912                           mkexpr( frB ) ) );
10913       break;
10914    default:
10915       vex_printf("dis_dfp_extract_insert(ppc)(opc2)\n");
10916       return False;
10917    }
10918 
10919    putDReg( frS_addr, mkexpr( frS ) );
10920 
10921    if (flag_rC && clear_CR1) {
10922       putCR321( 1, mkU8( 0 ) );
10923       putCR0( 1, mkU8( 0 ) );
10924    }
10925 
10926    return True;
10927 }
10928 
dis_dfp_extract_insertq(UInt theInstr)10929 static Bool dis_dfp_extract_insertq(UInt theInstr) {
10930    UInt opc2 = ifieldOPClo10( theInstr );
10931    UChar frS_addr = ifieldRegDS( theInstr );
10932    UChar frA_addr = ifieldRegA( theInstr );
10933    UChar frB_addr = ifieldRegB( theInstr );
10934    UChar flag_rC = ifieldBIT0( theInstr );
10935 
10936    IRTemp frA   = newTemp( Ity_D64 );
10937    IRTemp frB   = newTemp( Ity_D128 );
10938    IRTemp frS64 = newTemp( Ity_D64 );
10939    IRTemp frS   = newTemp( Ity_D128 );
10940    IRTemp tmp   = newTemp( Ity_I64 );
10941    Bool clear_CR1 = True;
10942 
10943    assign( frB, getDReg_pair( frB_addr ) );
10944 
10945    switch (opc2) {
10946    case 0x162:  // dxexq
10947       DIP( "dxexq%s fr%u,fr%u\n",
10948            flag_rC ? ".":"", frS_addr,  frB_addr );
10949       /* Instruction actually returns a 64-bit result.  So as to be
10950        * consistent and not have to add a new struct, the emulation returns
10951        * the 64-bit result in the upper and lower register.
10952        */
10953       assign( tmp, unop( Iop_ExtractExpD128, mkexpr( frB ) ) );
10954       assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
10955       putDReg( frS_addr, mkexpr( frS64 ) );
10956       break;
10957    case 0x362:  // diexq
10958       DIP( "diexq%s fr%u,fr%u,fr%u\n",
10959            flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10960       assign( frA, getDReg( frA_addr ) );
10961       assign( frS, binop( Iop_InsertExpD128,
10962                           unop( Iop_ReinterpD64asI64, mkexpr( frA ) ),
10963                           mkexpr( frB ) ) );
10964       putDReg_pair( frS_addr, mkexpr( frS ) );
10965       break;
10966    default:
10967       vex_printf("dis_dfp_extract_insertq(ppc)(opc2)\n");
10968       return False;
10969    }
10970 
10971    if (flag_rC && clear_CR1) {
10972       putCR321( 1, mkU8( 0 ) );
10973       putCR0( 1, mkU8( 0 ) );
10974    }
10975 
10976    return True;
10977 }
10978 
10979 /* DFP 64-bit comparison instructions */
dis_dfp_compare(UInt theInstr)10980 static Bool dis_dfp_compare(UInt theInstr) {
10981    /* X-Form */
10982    UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF
10983    UChar frA_addr = ifieldRegA( theInstr );
10984    UChar frB_addr = ifieldRegB( theInstr );
10985    UInt opc1 = ifieldOPC( theInstr );
10986    IRTemp frA;
10987    IRTemp frB;
10988 
10989    IRTemp ccIR = newTemp( Ity_I32 );
10990    IRTemp ccPPC32 = newTemp( Ity_I32 );
10991 
10992 
10993    /* Note: Differences between dcmpu and dcmpo are only in exception
10994     flag settings, which aren't supported anyway. */
10995    switch (opc1) {
10996    case 0x3B: /* dcmpo and dcmpu, DFP 64-bit */
10997       DIP( "dcmpo %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr );
10998       frA = newTemp( Ity_D64 );
10999       frB = newTemp( Ity_D64 );
11000 
11001       assign( frA, getDReg( frA_addr ) );
11002       assign( frB, getDReg( frB_addr ) );
11003 
11004       assign( ccIR, binop( Iop_CmpD64, mkexpr( frA ), mkexpr( frB ) ) );
11005       break;
11006    case 0x3F: /* dcmpoq and dcmpuq,DFP 128-bit */
11007       DIP( "dcmpoq %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr );
11008       frA = newTemp( Ity_D128 );
11009       frB = newTemp( Ity_D128 );
11010 
11011       assign( frA, getDReg_pair( frA_addr ) );
11012       assign( frB, getDReg_pair( frB_addr ) );
11013       assign( ccIR, binop( Iop_CmpD128, mkexpr( frA ), mkexpr( frB ) ) );
11014       break;
11015    default:
11016       vex_printf("dis_dfp_compare(ppc)(opc2)\n");
11017       return False;
11018    }
11019 
11020    /* Map compare result from IR to PPC32 */
11021    /*
11022     FP cmp result | PPC | IR
11023     --------------------------
11024     UN            | 0x1 | 0x45
11025     EQ            | 0x2 | 0x40
11026     GT            | 0x4 | 0x00
11027     LT            | 0x8 | 0x01
11028     */
11029 
11030    assign( ccPPC32,
11031            binop( Iop_Shl32,
11032                   mkU32( 1 ),
11033                   unop( Iop_32to8,
11034                         binop( Iop_Or32,
11035                                binop( Iop_And32,
11036                                       unop( Iop_Not32,
11037                                             binop( Iop_Shr32,
11038                                                    mkexpr( ccIR ),
11039                                                    mkU8( 5 ) ) ),
11040                                       mkU32( 2 ) ),
11041                                binop( Iop_And32,
11042                                       binop( Iop_Xor32,
11043                                              mkexpr( ccIR ),
11044                                              binop( Iop_Shr32,
11045                                                     mkexpr( ccIR ),
11046                                                     mkU8( 6 ) ) ),
11047                                       mkU32( 1 ) ) ) ) ) );
11048 
11049    putGST_field( PPC_GST_CR, mkexpr( ccPPC32 ), crfD );
11050    return True;
11051 }
11052 
11053 /* Test class/group/exponent/significance instructions. */
dis_dfp_exponent_test(UInt theInstr)11054 static Bool dis_dfp_exponent_test ( UInt theInstr )
11055 {
11056    UChar frA_addr   = ifieldRegA( theInstr );
11057    UChar frB_addr   = ifieldRegB( theInstr );
11058    UChar crfD       = toUChar( IFIELD( theInstr, 23, 3 ) );
11059    IRTemp frA       = newTemp( Ity_D64 );
11060    IRTemp frB       = newTemp( Ity_D64 );
11061    IRTemp frA128    = newTemp( Ity_D128 );
11062    IRTemp frB128    = newTemp( Ity_D128 );
11063    UInt opc1        = ifieldOPC( theInstr );
11064    IRTemp gfield_A  = newTemp( Ity_I32 );
11065    IRTemp gfield_B  = newTemp( Ity_I32 );
11066    IRTemp gfield_mask   = newTemp( Ity_I32 );
11067    IRTemp exponent_A    = newTemp( Ity_I32 );
11068    IRTemp exponent_B    = newTemp( Ity_I32 );
11069    IRTemp A_NaN_true    = newTemp( Ity_I32 );
11070    IRTemp B_NaN_true    = newTemp( Ity_I32 );
11071    IRTemp A_inf_true    = newTemp( Ity_I32 );
11072    IRTemp B_inf_true    = newTemp( Ity_I32 );
11073    IRTemp A_equals_B    = newTemp( Ity_I32 );
11074    IRTemp finite_number = newTemp( Ity_I32 );
11075    IRTemp cc0 = newTemp( Ity_I32 );
11076    IRTemp cc1 = newTemp( Ity_I32 );
11077    IRTemp cc2 = newTemp( Ity_I32 );
11078    IRTemp cc3 = newTemp( Ity_I32 );
11079 
11080    /* The dtstex and dtstexg instructions only differ in the size of the
11081     * exponent field.  The following switch statement takes care of the size
11082     * specific setup.  Once the value of the exponents, the G-field shift
11083     * and mask is setup the remaining code is identical.
11084     */
11085    switch (opc1) {
11086    case 0x3b: // dtstex       Extended instruction setup
11087       DIP("dtstex %u,r%u,r%d\n", crfD, frA_addr, frB_addr);
11088       assign( frA, getDReg( frA_addr ) );
11089       assign( frB, getDReg( frB_addr ) );
11090       assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) );
11091       assign(exponent_A, unop( Iop_64to32,
11092                                unop( Iop_ExtractExpD64,
11093                                      mkexpr( frA ) ) ) );
11094       assign(exponent_B, unop( Iop_64to32,
11095                                unop( Iop_ExtractExpD64,
11096                                      mkexpr( frB ) ) ) );
11097       break;
11098 
11099    case 0x3F: //  dtstexq      Quad instruction setup
11100       DIP("dtstexq %u,r%u,r%d\n", crfD, frA_addr, frB_addr);
11101       assign( frA128, getDReg_pair( frA_addr ) );
11102       assign( frB128, getDReg_pair( frB_addr ) );
11103       assign( frA, unop( Iop_D128HItoD64, mkexpr( frA128 ) ) );
11104       assign( frB, unop( Iop_D128HItoD64, mkexpr( frB128 ) ) );
11105       assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) );
11106       assign( exponent_A, unop( Iop_64to32,
11107                                 unop( Iop_ExtractExpD128,
11108                                       mkexpr( frA128 ) ) ) );
11109       assign( exponent_B, unop( Iop_64to32,
11110                                 unop( Iop_ExtractExpD128,
11111                                       mkexpr( frB128 ) ) ) );
11112       break;
11113    default:
11114       vex_printf("dis_dfp_exponent_test(ppc)(opc2)\n");
11115       return False;
11116    }
11117 
11118    /* Extract the Gfield */
11119    assign( gfield_A, binop( Iop_And32,
11120                             mkexpr( gfield_mask ),
11121                             unop( Iop_64HIto32,
11122                                   unop( Iop_ReinterpD64asI64,
11123                                         mkexpr(frA) ) ) ) );
11124 
11125    assign( gfield_B, binop( Iop_And32,
11126                             mkexpr( gfield_mask ),
11127                             unop( Iop_64HIto32,
11128                                   unop( Iop_ReinterpD64asI64,
11129                                         mkexpr(frB) ) ) ) );
11130 
11131    /* check for NAN */
11132    assign( A_NaN_true, binop(Iop_Or32,
11133                              unop( Iop_1Sto32,
11134                                    binop( Iop_CmpEQ32,
11135                                           mkexpr( gfield_A ),
11136                                           mkU32( 0x7C000000 ) ) ),
11137                              unop( Iop_1Sto32,
11138                                    binop( Iop_CmpEQ32,
11139                                           mkexpr( gfield_A ),
11140                                           mkU32( 0x7E000000 ) )
11141                                    ) ) );
11142    assign( B_NaN_true, binop(Iop_Or32,
11143                              unop( Iop_1Sto32,
11144                                    binop( Iop_CmpEQ32,
11145                                           mkexpr( gfield_B ),
11146                                           mkU32( 0x7C000000 ) ) ),
11147                              unop( Iop_1Sto32,
11148                                    binop( Iop_CmpEQ32,
11149                                           mkexpr( gfield_B ),
11150                                           mkU32( 0x7E000000 ) )
11151                              ) ) );
11152 
11153    /* check for infinity */
11154    assign( A_inf_true,
11155            unop( Iop_1Sto32,
11156                  binop( Iop_CmpEQ32,
11157                         mkexpr( gfield_A ),
11158                         mkU32( 0x78000000 ) ) ) );
11159 
11160    assign( B_inf_true,
11161            unop( Iop_1Sto32,
11162                  binop( Iop_CmpEQ32,
11163                         mkexpr( gfield_B ),
11164                         mkU32( 0x78000000 ) ) ) );
11165 
11166    assign( finite_number,
11167            unop( Iop_Not32,
11168                  binop( Iop_Or32,
11169                         binop( Iop_Or32,
11170                                mkexpr( A_NaN_true ),
11171                                mkexpr( B_NaN_true ) ),
11172                         binop( Iop_Or32,
11173                                mkexpr( A_inf_true ),
11174                                mkexpr( B_inf_true ) ) ) ) );
11175 
11176    /* Calculate the condition code bits
11177     * If QNaN,SNaN, +infinity, -infinity then cc0, cc1 and cc2 are zero
11178     * regardless of the value of the comparisons and cc3 is 1.  Otherwise,
11179     * cc0, cc1 and cc0 reflect the results of the comparisons.
11180     */
11181    assign( A_equals_B,
11182            binop( Iop_Or32,
11183                   unop( Iop_1Uto32,
11184                   binop( Iop_CmpEQ32,
11185                          mkexpr( exponent_A ),
11186                          mkexpr( exponent_B ) ) ),
11187                   binop( Iop_Or32,
11188                          binop( Iop_And32,
11189                                 mkexpr( A_inf_true ),
11190                                 mkexpr( B_inf_true ) ),
11191                          binop( Iop_And32,
11192                                 mkexpr( A_NaN_true ),
11193                                 mkexpr( B_NaN_true ) ) ) ) );
11194 
11195    assign( cc0, binop( Iop_And32,
11196                        mkexpr( finite_number ),
11197                        binop( Iop_Shl32,
11198                               unop( Iop_1Uto32,
11199                                     binop( Iop_CmpLT32U,
11200                                            mkexpr( exponent_A ),
11201                                            mkexpr( exponent_B ) ) ),
11202                                            mkU8( 3 ) ) ) );
11203 
11204    assign( cc1, binop( Iop_And32,
11205                        mkexpr( finite_number ),
11206                        binop( Iop_Shl32,
11207                               unop( Iop_1Uto32,
11208                                     binop( Iop_CmpLT32U,
11209                                            mkexpr( exponent_B ),
11210                                            mkexpr( exponent_A ) ) ),
11211                                            mkU8( 2 ) ) ) );
11212 
11213    assign( cc2, binop( Iop_Shl32,
11214                        binop( Iop_And32,
11215                               mkexpr( A_equals_B ),
11216                               mkU32( 1 ) ),
11217                               mkU8( 1 ) ) );
11218 
11219    assign( cc3, binop( Iop_And32,
11220                        unop( Iop_Not32, mkexpr( A_equals_B ) ),
11221                        binop( Iop_And32,
11222                               mkU32( 0x1 ),
11223                               binop( Iop_Or32,
11224                                      binop( Iop_Or32,
11225                                             mkexpr ( A_inf_true ),
11226                                             mkexpr ( B_inf_true ) ),
11227                                             binop( Iop_Or32,
11228                                                    mkexpr ( A_NaN_true ),
11229                                                    mkexpr ( B_NaN_true ) ) )
11230                               ) ) );
11231 
11232    /* store the condition code */
11233    putGST_field( PPC_GST_CR,
11234                  binop( Iop_Or32,
11235                         mkexpr( cc0 ),
11236                         binop( Iop_Or32,
11237                                mkexpr( cc1 ),
11238                                binop( Iop_Or32,
11239                                       mkexpr( cc2 ),
11240                                       mkexpr( cc3 ) ) ) ),
11241                  crfD );
11242    return True;
11243 }
11244 
11245 /* Test class/group/exponent/significance instructions. */
dis_dfp_class_test(UInt theInstr)11246 static Bool dis_dfp_class_test ( UInt theInstr )
11247 {
11248    UChar frA_addr   = ifieldRegA( theInstr );
11249    IRTemp frA       = newTemp( Ity_D64 );
11250    IRTemp abs_frA   = newTemp( Ity_D64 );
11251    IRTemp frAI64_hi = newTemp( Ity_I64 );
11252    IRTemp frAI64_lo = newTemp( Ity_I64 );
11253    UInt opc1        = ifieldOPC( theInstr );
11254    UInt opc2        = ifieldOPClo9( theInstr );
11255    UChar crfD       = toUChar( IFIELD( theInstr, 23, 3 ) );  // AKA BF
11256    UInt DCM         = IFIELD( theInstr, 10, 6 );
11257    IRTemp DCM_calc  = newTemp( Ity_I32 );
11258    UInt max_exp     = 0;
11259    UInt min_exp     = 0;
11260    IRTemp min_subnormalD64  = newTemp( Ity_D64 );
11261    IRTemp min_subnormalD128 = newTemp( Ity_D128 );
11262    IRTemp significand64  = newTemp( Ity_D64 );
11263    IRTemp significand128 = newTemp( Ity_D128 );
11264    IRTemp exp_min_normal = newTemp( Ity_I64 );
11265    IRTemp exponent       = newTemp( Ity_I32 );
11266 
11267    IRTemp infinity_true  = newTemp( Ity_I32 );
11268    IRTemp SNaN_true      = newTemp( Ity_I32 );
11269    IRTemp QNaN_true      = newTemp( Ity_I32 );
11270    IRTemp subnormal_true = newTemp( Ity_I32 );
11271    IRTemp normal_true    = newTemp( Ity_I32 );
11272    IRTemp extreme_true   = newTemp( Ity_I32 );
11273    IRTemp lmd            = newTemp( Ity_I32 );
11274    IRTemp lmd_zero_true  = newTemp( Ity_I32 );
11275    IRTemp zero_true      = newTemp( Ity_I32 );
11276    IRTemp sign           = newTemp( Ity_I32 );
11277    IRTemp field          = newTemp( Ity_I32 );
11278    IRTemp ccIR_zero      = newTemp( Ity_I32 );
11279    IRTemp ccIR_subnormal = newTemp( Ity_I32 );
11280 
11281    /* UInt size     = DFP_LONG;  JRS:unused */
11282    IRTemp gfield = newTemp( Ity_I32 );
11283    IRTemp gfield_0_4_shift  = newTemp( Ity_I8 );
11284    IRTemp gfield_mask       = newTemp( Ity_I32 );
11285    IRTemp dcm0 = newTemp( Ity_I32 );
11286    IRTemp dcm1 = newTemp( Ity_I32 );
11287    IRTemp dcm2 = newTemp( Ity_I32 );
11288    IRTemp dcm3 = newTemp( Ity_I32 );
11289    IRTemp dcm4 = newTemp( Ity_I32 );
11290    IRTemp dcm5 = newTemp( Ity_I32 );
11291 
11292    /* The only difference between the dtstdc and dtstdcq instructions is
11293     * size of the T and G fields.  The calculation of the 4 bit field
11294     * is the same.  Setup the parameters and values that are DFP size
11295     * specific.  The rest of the code is independent of the DFP size.
11296     *
11297     * The Io_CmpD64 is used below.  The instruction sets the ccIR values.
11298     * The interpretation of the ccIR values is as follows:
11299     *
11300     *    DFP cmp result | IR
11301     * --------------------------
11302     *	 UN             | 0x45
11303     *	 EQ             | 0x40
11304     *	 GT             | 0x00
11305     *	 LT             | 0x01
11306     */
11307 
11308    assign( frA, getDReg( frA_addr ) );
11309    assign( frAI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frA ) ) );
11310 
11311    assign( abs_frA, unop( Iop_ReinterpI64asD64,
11312                           binop( Iop_And64,
11313                                  unop( Iop_ReinterpD64asI64,
11314                                        mkexpr( frA ) ),
11315                                  mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ) );
11316    assign( gfield_0_4_shift, mkU8( 31 - 5 ) );  // G-field[0:4]
11317    switch (opc1) {
11318    case 0x3b: // dtstdc, dtstdg
11319       DIP("dtstd%s %u,r%u,%u\n", opc2 == 0xc2 ? "c" : "g",
11320                crfD, frA_addr, DCM);
11321       /* setup the parameters for the long format of the two instructions */
11322       assign( frAI64_lo, mkU64( 0 ) );
11323       assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) );
11324       max_exp = DFP_LONG_EXP_MAX;
11325       min_exp = DFP_LONG_EXP_MIN;
11326 
11327       assign( exponent, unop( Iop_64to32,
11328                               unop( Iop_ExtractExpD64,
11329                                     mkexpr( frA ) ) ) );
11330       assign( significand64,
11331               unop( Iop_ReinterpI64asD64,
11332                     mkU64( 0x2234000000000001ULL ) ) );  // dfp 1.0
11333       assign( exp_min_normal,mkU64( 398 - 383 ) );
11334       assign( min_subnormalD64,
11335               binop( Iop_InsertExpD64,
11336                      mkexpr( exp_min_normal ),
11337                      mkexpr( significand64 ) ) );
11338 
11339       assign( ccIR_subnormal,
11340               binop( Iop_CmpD64,
11341                      mkexpr( abs_frA ),
11342                      mkexpr( min_subnormalD64 ) ) );
11343 
11344       /* compare absolute value of frA with zero */
11345       assign( ccIR_zero,
11346               binop( Iop_CmpD64,
11347                      mkexpr( abs_frA ),
11348                      unop( Iop_ReinterpI64asD64,
11349                            mkU64( 0x2238000000000000ULL ) ) ) );
11350 
11351       /* size = DFP_LONG; JRS: unused */
11352       break;
11353 
11354    case 0x3F:   // dtstdcq, dtstdgq
11355       DIP("dtstd%sq %u,r%u,%u\n", opc2 == 0xc2 ? "c" : "g",
11356                crfD, frA_addr, DCM);
11357       /* setup the parameters for the extended format of the
11358        * two instructions
11359        */
11360       assign( frAI64_lo, unop( Iop_ReinterpD64asI64,
11361                                getDReg( frA_addr+1 ) ) );
11362 
11363       assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) );
11364       max_exp = DFP_EXTND_EXP_MAX;
11365       min_exp = DFP_EXTND_EXP_MIN;
11366       assign( exponent, unop( Iop_64to32,
11367                               unop( Iop_ExtractExpD128,
11368                                     getDReg_pair( frA_addr) ) ) );
11369 
11370       /* create quand exponent for minimum normal number */
11371       assign( exp_min_normal, mkU64( 6176 - 6143 ) );
11372       assign( significand128,
11373               unop( Iop_D64toD128,
11374                     unop( Iop_ReinterpI64asD64,
11375                           mkU64( 0x2234000000000001ULL ) ) ) );  // dfp 1.0
11376 
11377       assign( min_subnormalD128,
11378               binop( Iop_InsertExpD128,
11379                      mkexpr( exp_min_normal ),
11380                      mkexpr( significand128 ) ) );
11381 
11382       assign( ccIR_subnormal,
11383               binop( Iop_CmpD128,
11384                      binop( Iop_D64HLtoD128,
11385                             unop( Iop_ReinterpI64asD64,
11386                                   binop( Iop_And64,
11387                                          unop( Iop_ReinterpD64asI64,
11388                                                mkexpr( frA ) ),
11389                                          mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ),
11390                             getDReg( frA_addr+1 ) ),
11391                      mkexpr( min_subnormalD128 ) ) );
11392       assign( ccIR_zero,
11393               binop( Iop_CmpD128,
11394                      binop( Iop_D64HLtoD128,
11395                             mkexpr( abs_frA ),
11396                             getDReg( frA_addr+1 ) ),
11397                      unop( Iop_D64toD128,
11398                            unop( Iop_ReinterpI64asD64,
11399                                  mkU64( 0x0ULL ) ) ) ) );
11400 
11401       /* size = DFP_EXTND; JRS:unused */
11402       break;
11403    default:
11404       vex_printf("dis_dfp_class_test(ppc)(opc2)\n");
11405       return False;
11406    }
11407 
11408    /* The G-field is in the upper 32-bits.  The I64 logical operations
11409     * do not seem to be supported in 32-bit mode so keep things as 32-bit
11410     * operations.
11411     */
11412    assign( gfield, binop( Iop_And32,
11413                           mkexpr( gfield_mask ),
11414                           unop( Iop_64HIto32,
11415                                 mkexpr(frAI64_hi) ) ) );
11416 
11417    /* There is a lot of code that is the same to do the class and group
11418     * instructions.  Later there is an if statement to handle the specific
11419     * instruction.
11420     *
11421     * Will be using I32 values, compares, shifts and logical operations for
11422     * this code as the 64-bit compare, shifts, logical operations are not
11423     * supported in 32-bit mode.
11424     */
11425 
11426    /* Check the bits for Infinity, QNaN or Signaling NaN */
11427    assign( infinity_true,
11428            unop( Iop_1Sto32,
11429                  binop( Iop_CmpEQ32,
11430                         binop( Iop_And32,
11431                                mkU32( 0x7C000000 ),
11432                                mkexpr( gfield ) ),
11433                         mkU32( 0x78000000 ) ) ) );
11434 
11435    assign( SNaN_true,
11436            unop( Iop_1Sto32,
11437                  binop( Iop_CmpEQ32,
11438                         binop( Iop_And32,
11439                                mkU32( 0x7E000000 ),
11440                                mkexpr( gfield ) ),
11441                         mkU32( 0x7E000000 ) ) ) );
11442 
11443    assign( QNaN_true,
11444            binop( Iop_And32,
11445                   unop( Iop_1Sto32,
11446                        binop( Iop_CmpEQ32,
11447                               binop( Iop_And32,
11448                                      mkU32( 0x7E000000 ),
11449                                      mkexpr( gfield ) ),
11450                               mkU32( 0x7C000000 ) ) ),
11451                   unop( Iop_Not32,
11452                         mkexpr( SNaN_true ) ) ) );
11453 
11454    assign( zero_true,
11455            binop( Iop_And32,
11456                   unop(Iop_1Sto32,
11457                        binop( Iop_CmpEQ32,
11458                               mkexpr( ccIR_zero ),
11459                               mkU32( 0x40 ) ) ),  // ccIR code for Equal
11460                   unop( Iop_Not32,
11461                         binop( Iop_Or32,
11462                                mkexpr( infinity_true ),
11463                                binop( Iop_Or32,
11464                                       mkexpr( QNaN_true ),
11465                                       mkexpr( SNaN_true ) ) ) ) ) );
11466 
11467    /* Do compare of frA the minimum normal value.  Comparison is size
11468     * depenent and was done above to get the ccIR value.
11469     */
11470    assign( subnormal_true,
11471            binop( Iop_And32,
11472                   binop( Iop_Or32,
11473                          unop( Iop_1Sto32,
11474                                binop( Iop_CmpEQ32,
11475                                       mkexpr( ccIR_subnormal ),
11476                                       mkU32( 0x40 ) ) ), // ccIR code for Equal
11477                          unop( Iop_1Sto32,
11478                                binop( Iop_CmpEQ32,
11479                                       mkexpr( ccIR_subnormal ),
11480                                       mkU32( 0x1 ) ) ) ), // ccIR code for LT
11481            unop( Iop_Not32,
11482                  binop( Iop_Or32,
11483                         binop( Iop_Or32,
11484                                mkexpr( infinity_true ),
11485                                mkexpr( zero_true) ),
11486                         binop( Iop_Or32,
11487                                mkexpr( QNaN_true ),
11488                                mkexpr( SNaN_true ) ) ) ) ) );
11489 
11490    /* Normal number is not subnormal, infinity, NaN or Zero */
11491    assign( normal_true,
11492            unop( Iop_Not32,
11493                  binop( Iop_Or32,
11494                         binop( Iop_Or32,
11495                                mkexpr( infinity_true ),
11496                                mkexpr( zero_true ) ),
11497                         binop( Iop_Or32,
11498                                mkexpr( subnormal_true ),
11499                                binop( Iop_Or32,
11500                                       mkexpr( QNaN_true ),
11501                                       mkexpr( SNaN_true ) ) ) ) ) );
11502 
11503    /* Calculate the DCM bit field based on the tests for the specific
11504     * instruction
11505     */
11506    if (opc2 == 0xC2) {    // dtstdc, dtstdcq
11507       /* DCM[0:5] Bit   Data Class definition
11508        *   0   Zero
11509        *   1   Subnormal
11510        *   2   Normal
11511        *   3   Infinity
11512        *   4   Quiet NaN
11513        *   5   Signaling NaN
11514        */
11515 
11516       assign( dcm0, binop( Iop_Shl32,
11517                            mkexpr( zero_true ),
11518                            mkU8( 5 ) ) );
11519       assign( dcm1, binop( Iop_Shl32,
11520                            binop( Iop_And32,
11521                                   mkexpr( subnormal_true ),
11522                                   mkU32( 1 ) ),
11523                            mkU8( 4 ) ) );
11524       assign( dcm2, binop( Iop_Shl32,
11525                            binop( Iop_And32,
11526                                   mkexpr( normal_true ),
11527                                   mkU32( 1 ) ),
11528                            mkU8( 3 ) ) );
11529       assign( dcm3, binop( Iop_Shl32,
11530                            binop( Iop_And32,
11531                                   mkexpr( infinity_true),
11532                                   mkU32( 1 ) ),
11533                            mkU8( 2 ) ) );
11534       assign( dcm4, binop( Iop_Shl32,
11535                            binop( Iop_And32,
11536                                   mkexpr( QNaN_true ),
11537                                   mkU32( 1 ) ),
11538                            mkU8( 1 ) ) );
11539       assign( dcm5, binop( Iop_And32, mkexpr( SNaN_true), mkU32( 1 ) ) );
11540 
11541    } else if (opc2 == 0xE2) {   // dtstdg, dtstdgq
11542       /* check if the exponent is extreme */
11543       assign( extreme_true, binop( Iop_Or32,
11544                                    unop( Iop_1Sto32,
11545                                          binop( Iop_CmpEQ32,
11546                                                 mkexpr( exponent ),
11547                                                 mkU32( max_exp ) ) ),
11548                                    unop( Iop_1Sto32,
11549                                          binop( Iop_CmpEQ32,
11550                                                 mkexpr( exponent ),
11551                                                 mkU32( min_exp ) ) ) ) );
11552 
11553       /* Check if LMD is zero */
11554       Get_lmd( &lmd, binop( Iop_Shr32,
11555                             mkexpr( gfield ), mkU8( 31 - 5 ) ) );
11556 
11557       assign( lmd_zero_true, unop( Iop_1Sto32,
11558                                    binop( Iop_CmpEQ32,
11559                                           mkexpr( lmd ),
11560                                           mkU32( 0 ) ) ) );
11561 
11562       /* DCM[0:5] Bit   Data Class definition
11563        *  0   Zero with non-extreme exponent
11564        *  1   Zero with extreme exponent
11565        *  2   Subnormal or (Normal with extreme exponent)
11566        *  3   Normal with non-extreme exponent and
11567        *      leftmost zero digit in significand
11568        *  4   Normal with non-extreme exponent and
11569        *      leftmost nonzero digit in significand
11570        *  5   Special symbol (Infinity, QNaN, or SNaN)
11571        */
11572       assign( dcm0, binop( Iop_Shl32,
11573                            binop( Iop_And32,
11574                                   binop( Iop_And32,
11575                                          unop( Iop_Not32,
11576                                                mkexpr( extreme_true ) ),
11577                                          mkexpr( zero_true ) ),
11578                                   mkU32( 0x1 ) ),
11579                            mkU8( 5 ) ) );
11580 
11581       assign( dcm1, binop( Iop_Shl32,
11582                            binop( Iop_And32,
11583                                   binop( Iop_And32,
11584                                          mkexpr( extreme_true ),
11585                                          mkexpr( zero_true ) ),
11586                                   mkU32( 0x1 ) ),
11587                            mkU8( 4 ) ) );
11588 
11589       assign( dcm2, binop( Iop_Shl32,
11590                            binop( Iop_And32,
11591                                   binop( Iop_Or32,
11592                                          binop( Iop_And32,
11593                                                 mkexpr( extreme_true ),
11594                                                 mkexpr( normal_true ) ),
11595                                          mkexpr( subnormal_true ) ),
11596                                   mkU32( 0x1 ) ),
11597                            mkU8( 3 ) ) );
11598 
11599       assign( dcm3, binop( Iop_Shl32,
11600                            binop( Iop_And32,
11601                                   binop( Iop_And32,
11602                                          binop( Iop_And32,
11603                                                 unop( Iop_Not32,
11604                                                       mkexpr( extreme_true ) ),
11605                                                       mkexpr( normal_true ) ),
11606                                          unop( Iop_1Sto32,
11607                                                binop( Iop_CmpEQ32,
11608                                                       mkexpr( lmd ),
11609                                                       mkU32( 0 ) ) ) ),
11610                                   mkU32( 0x1 ) ),
11611                            mkU8( 2 ) ) );
11612 
11613       assign( dcm4, binop( Iop_Shl32,
11614                            binop( Iop_And32,
11615                                   binop( Iop_And32,
11616                                          binop( Iop_And32,
11617                                                 unop( Iop_Not32,
11618                                                       mkexpr( extreme_true ) ),
11619                                                 mkexpr( normal_true ) ),
11620                                           unop( Iop_1Sto32,
11621                                                 binop( Iop_CmpNE32,
11622                                                        mkexpr( lmd ),
11623                                                        mkU32( 0 ) ) ) ),
11624                                   mkU32( 0x1 ) ),
11625                            mkU8( 1 ) ) );
11626 
11627       assign( dcm5, binop( Iop_And32,
11628                            binop( Iop_Or32,
11629                                   mkexpr( SNaN_true),
11630                                   binop( Iop_Or32,
11631                                          mkexpr( QNaN_true),
11632                                          mkexpr( infinity_true) ) ),
11633                            mkU32( 0x1 ) ) );
11634    }
11635 
11636    /* create DCM field */
11637    assign( DCM_calc,
11638            binop( Iop_Or32,
11639                   mkexpr( dcm0 ),
11640                   binop( Iop_Or32,
11641                          mkexpr( dcm1 ),
11642                          binop( Iop_Or32,
11643                                 mkexpr( dcm2 ),
11644                                 binop( Iop_Or32,
11645                                        mkexpr( dcm3 ),
11646                                        binop( Iop_Or32,
11647                                               mkexpr( dcm4 ),
11648                                               mkexpr( dcm5 ) ) ) ) ) ) );
11649 
11650    /* Get the sign of the DFP number, ignore sign for QNaN */
11651    assign( sign,
11652            unop( Iop_1Uto32,
11653                  binop( Iop_CmpEQ32,
11654                         binop( Iop_Shr32,
11655                                unop( Iop_64HIto32, mkexpr( frAI64_hi ) ),
11656                                mkU8( 63 - 32 ) ),
11657                         mkU32( 1 ) ) ) );
11658 
11659    /* This instruction generates a four bit field to be stored in the
11660     * condition code register.  The condition code register consists of 7
11661     * fields.  The field to be written to is specified by the BF (AKA crfD)
11662     * field.
11663     *
11664     * The field layout is as follows:
11665     *
11666     *      Field          Meaning
11667     *      0000           Operand positive with no match
11668     *      0100           Operand positive with at least one match
11669     *      0001           Operand negative with no match
11670     *      0101           Operand negative with at least one match
11671     */
11672    assign( field, binop( Iop_Or32,
11673                          binop( Iop_Shl32,
11674                                 mkexpr( sign ),
11675                                 mkU8( 3 ) ),
11676                                 binop( Iop_Shl32,
11677                                        unop( Iop_1Uto32,
11678                                              binop( Iop_CmpNE32,
11679                                                     binop( Iop_And32,
11680                                                            mkU32( DCM ),
11681                                                            mkexpr( DCM_calc ) ),
11682                                                      mkU32( 0 ) ) ),
11683                                        mkU8( 1 ) ) ) );
11684 
11685    putGST_field( PPC_GST_CR, mkexpr( field ), crfD );
11686    return True;
11687 }
11688 
dis_dfp_bcd(UInt theInstr)11689 static Bool dis_dfp_bcd(UInt theInstr) {
11690    UInt opc2        = ifieldOPClo10( theInstr );
11691    ULong sp         = IFIELD(theInstr, 19, 2);
11692    ULong s          = IFIELD(theInstr, 20, 1);
11693    UChar frT_addr   = ifieldRegDS( theInstr );
11694    UChar frB_addr   = ifieldRegB( theInstr );
11695    IRTemp frB       = newTemp( Ity_D64 );
11696    IRTemp frBI64    = newTemp( Ity_I64 );
11697    IRTemp result    = newTemp( Ity_I64 );
11698    IRTemp resultD64 = newTemp( Ity_D64 );
11699    IRTemp bcd64     = newTemp( Ity_I64 );
11700    IRTemp bcd_u     = newTemp( Ity_I32 );
11701    IRTemp bcd_l     = newTemp( Ity_I32 );
11702    IRTemp dbcd_u    = newTemp( Ity_I32 );
11703    IRTemp dbcd_l    = newTemp( Ity_I32 );
11704    IRTemp lmd       = newTemp( Ity_I32 );
11705 
11706    assign( frB, getDReg( frB_addr ) );
11707    assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) );
11708 
11709    switch ( opc2 ) {
11710    case 0x142: // ddedpd   DFP Decode DPD to BCD
11711       DIP( "ddedpd %llu,r%u,r%u\n", sp, frT_addr, frB_addr );
11712 
11713          assign( bcd64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) );
11714          assign( bcd_u, unop( Iop_64HIto32, mkexpr( bcd64 ) ) );
11715          assign( bcd_l, unop( Iop_64to32, mkexpr( bcd64 ) ) );
11716 
11717       if ( ( sp == 0 ) || ( sp == 1 ) ) {
11718          /* Unsigned BCD string */
11719          Get_lmd( &lmd,
11720                   binop( Iop_Shr32,
11721                          unop( Iop_64HIto32, mkexpr( frBI64 ) ),
11722                          mkU8( 31 - 5 ) ) ); // G-field[0:4]
11723 
11724          assign( result,
11725                  binop( Iop_32HLto64,
11726                         binop( Iop_Or32,
11727                                binop( Iop_Shl32, mkexpr( lmd ), mkU8( 28 ) ),
11728                                mkexpr( bcd_u ) ),
11729                         mkexpr( bcd_l ) ) );
11730 
11731       } else {
11732          /* Signed BCD string, the cases for sp 2 and 3 only differ in how
11733           * the positive and negative values are encoded in the least
11734           * significant bits.
11735           */
11736          IRTemp sign = newTemp( Ity_I32 );
11737 
11738          if (sp == 2) {
11739             /* Positive sign = 0xC, negative sign = 0xD */
11740 
11741             assign( sign,
11742                     binop( Iop_Or32,
11743                            binop( Iop_Shr32,
11744                                   unop( Iop_64HIto32, mkexpr( frBI64 ) ),
11745                                   mkU8( 31 ) ),
11746                            mkU32( 0xC ) ) );
11747 
11748          } else if ( sp == 3 ) {
11749             /* Positive sign = 0xF, negative sign = 0xD */
11750             IRTemp tmp32 = newTemp( Ity_I32 );
11751 
11752             /* Complement sign bit then OR into bit position 1 */
11753             assign( tmp32,
11754                     binop( Iop_Xor32,
11755                            binop( Iop_Shr32,
11756                                   unop( Iop_64HIto32, mkexpr( frBI64 ) ),
11757                                   mkU8( 30 ) ),
11758                            mkU32( 0x2 ) ) );
11759 
11760             assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) );
11761 
11762          } else {
11763             vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
11764          }
11765 
11766          /* Put sign in bottom 4 bits, move most significant 4-bits from
11767           * bcd_l to bcd_u.
11768           */
11769          assign( result,
11770                  binop( Iop_32HLto64,
11771                         binop( Iop_Or32,
11772                                binop( Iop_Shr32,
11773                                       mkexpr( bcd_l ),
11774                                       mkU8( 28 ) ),
11775                                binop( Iop_Shl32,
11776                                       mkexpr( bcd_u ),
11777                                       mkU8( 4 ) ) ),
11778                         binop( Iop_Or32,
11779                                       mkexpr( sign ),
11780                                binop( Iop_Shl32,
11781                                       mkexpr( bcd_l ),
11782                                       mkU8( 4 ) ) ) ) );
11783       }
11784 
11785       putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result ) ) );
11786       break;
11787 
11788    case 0x342: // denbcd   DFP Encode BCD to DPD
11789    {
11790       IRTemp valid_mask   = newTemp( Ity_I32 );
11791       IRTemp invalid_mask = newTemp( Ity_I32 );
11792       IRTemp without_lmd  = newTemp( Ity_I64 );
11793       IRTemp tmp64        = newTemp( Ity_I64 );
11794       IRTemp dbcd64       = newTemp( Ity_I64 );
11795       IRTemp left_exp     = newTemp( Ity_I32 );
11796       IRTemp g0_4         = newTemp( Ity_I32 );
11797 
11798       DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr );
11799 
11800       if ( s == 0 ) {
11801          /* Unsigned BCD string */
11802          assign( dbcd64, unop( Iop_BCDtoDPB, mkexpr(frBI64 ) ) );
11803          assign( dbcd_u, unop( Iop_64HIto32, mkexpr( dbcd64 ) ) );
11804          assign( dbcd_l, unop( Iop_64to32, mkexpr( dbcd64 ) ) );
11805 
11806          assign( lmd,
11807                  binop( Iop_Shr32,
11808                         binop( Iop_And32,
11809                                unop( Iop_64HIto32, mkexpr( frBI64 ) ),
11810                                mkU32( 0xF0000000 ) ),
11811                         mkU8( 28 ) ) );
11812 
11813          assign( invalid_mask,
11814                  bcd_digit_inval( unop( Iop_64HIto32, mkexpr( frBI64 ) ),
11815                                   unop( Iop_64to32, mkexpr( frBI64 ) ) ) );
11816          assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
11817 
11818          assign( without_lmd,
11819                  unop( Iop_ReinterpD64asI64,
11820                        binop( Iop_InsertExpD64,
11821                               mkU64( DFP_LONG_BIAS ),
11822                               unop( Iop_ReinterpI64asD64,
11823                                     binop( Iop_32HLto64,
11824                                            mkexpr( dbcd_u ),
11825                                            mkexpr( dbcd_l ) ) ) ) ) );
11826          assign( left_exp,
11827                  binop( Iop_Shr32,
11828                         binop( Iop_And32,
11829                                unop( Iop_64HIto32, mkexpr( without_lmd ) ),
11830                                mkU32( 0x60000000 ) ),
11831                         mkU8( 29 ) ) );
11832 
11833          assign( g0_4,
11834                  binop( Iop_Shl32,
11835                         Gfield_encoding( mkexpr( left_exp ), mkexpr( lmd ) ),
11836                         mkU8( 26 ) ) );
11837 
11838          assign( tmp64,
11839                  binop( Iop_32HLto64,
11840                         binop( Iop_Or32,
11841                                binop( Iop_And32,
11842                                       unop( Iop_64HIto32,
11843                                             mkexpr( without_lmd ) ),
11844                                       mkU32( 0x83FFFFFF ) ),
11845                                mkexpr( g0_4 ) ),
11846                         unop( Iop_64to32, mkexpr( without_lmd ) ) ) );
11847 
11848       } else if ( s == 1 ) {
11849          IRTemp sign = newTemp( Ity_I32 );
11850          IRTemp sign_bit = newTemp( Ity_I32 );
11851          IRTemp pos_sign_mask = newTemp( Ity_I32 );
11852          IRTemp neg_sign_mask = newTemp( Ity_I32 );
11853          IRTemp tmp = newTemp( Ity_I64 );
11854 
11855          /* Signed BCD string, least significant 4 bits are sign bits
11856           * positive sign = 0xC, negative sign = 0xD
11857           */
11858          assign( tmp, unop( Iop_BCDtoDPB,
11859                             binop( Iop_32HLto64,
11860                                    binop( Iop_Shr32,
11861                                           unop( Iop_64HIto32,
11862                                                 mkexpr( frBI64 ) ),
11863                                                 mkU8( 4 ) ),
11864                                    binop( Iop_Or32,
11865                                           binop( Iop_Shr32,
11866                                                  unop( Iop_64to32,
11867                                                        mkexpr( frBI64 ) ),
11868                                                   mkU8( 4 ) ),
11869                                           binop( Iop_Shl32,
11870                                                  unop( Iop_64HIto32,
11871                                                        mkexpr( frBI64 ) ),
11872                                                        mkU8( 28 ) ) ) ) ) );
11873 
11874          assign( dbcd_u, unop( Iop_64HIto32, mkexpr( tmp ) ) );
11875          assign( dbcd_l, unop( Iop_64to32, mkexpr( tmp ) ) );
11876 
11877          /* Get the sign of the BCD string. */
11878          assign( sign,
11879                  binop( Iop_And32,
11880                         unop( Iop_64to32, mkexpr( frBI64 ) ),
11881                         mkU32( 0xF ) ) );
11882 
11883          assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) );
11884          assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) );
11885          assign( sign_bit,
11886                  Generate_sign_bit( mkexpr( pos_sign_mask ),
11887                                     mkexpr( neg_sign_mask ) ) );
11888 
11889          /* Check for invalid sign and BCD digit.  Don't check the bottom
11890           * four bits of bcd_l as that is the sign value.
11891           */
11892          assign( invalid_mask,
11893                  Generate_inv_mask(
11894                                    bcd_digit_inval( unop( Iop_64HIto32,
11895                                                           mkexpr( frBI64 ) ),
11896                                                     binop( Iop_Shr32,
11897                                                            unop( Iop_64to32,
11898                                                                  mkexpr( frBI64 ) ),
11899                                                            mkU8( 4 ) ) ),
11900                                    mkexpr( pos_sign_mask ),
11901                                    mkexpr( neg_sign_mask ) ) );
11902 
11903          assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
11904 
11905          /* Generate the result assuming the sign value was valid. */
11906          assign( tmp64,
11907                  unop( Iop_ReinterpD64asI64,
11908                        binop( Iop_InsertExpD64,
11909                               mkU64( DFP_LONG_BIAS ),
11910                               unop( Iop_ReinterpI64asD64,
11911                                     binop( Iop_32HLto64,
11912                                            binop( Iop_Or32,
11913                                                   mkexpr( dbcd_u ),
11914                                                   mkexpr( sign_bit ) ),
11915                                            mkexpr( dbcd_l ) ) ) ) ) );
11916       }
11917 
11918       /* Generate the value to store depending on the validity of the
11919        * sign value and the validity of the BCD digits.
11920        */
11921       assign( resultD64,
11922               unop( Iop_ReinterpI64asD64,
11923                     binop( Iop_32HLto64,
11924                            binop( Iop_Or32,
11925                                   binop( Iop_And32,
11926                                          mkexpr( valid_mask ),
11927                                          unop( Iop_64HIto32,
11928                                                mkexpr( tmp64 ) ) ),
11929                                   binop( Iop_And32,
11930                                          mkU32( 0x7C000000 ),
11931                                          mkexpr( invalid_mask ) ) ),
11932                            binop( Iop_Or32,
11933                                   binop( Iop_And32,
11934                                          mkexpr( valid_mask ),
11935                                          unop( Iop_64to32, mkexpr( tmp64 ) ) ),
11936                                   binop( Iop_And32,
11937                                          mkU32( 0x0 ),
11938                                          mkexpr( invalid_mask ) ) ) ) ) );
11939       putDReg( frT_addr, mkexpr( resultD64 ) );
11940    }
11941    break;
11942    default:
11943       vpanic( "ERROR: dis_dfp_bcd(ppc), undefined opc2 case " );
11944       return False;
11945    }
11946    return True;
11947 }
11948 
dis_dfp_bcdq(UInt theInstr)11949 static Bool dis_dfp_bcdq( UInt theInstr )
11950 {
11951    UInt opc2        = ifieldOPClo10( theInstr );
11952    ULong sp         = IFIELD(theInstr, 19, 2);
11953    ULong s          = IFIELD(theInstr, 20, 1);
11954    IRTemp frB_hi    = newTemp( Ity_D64 );
11955    IRTemp frB_lo    = newTemp( Ity_D64 );
11956    IRTemp frBI64_hi = newTemp( Ity_I64 );
11957    IRTemp frBI64_lo = newTemp( Ity_I64 );
11958    UChar frT_addr   = ifieldRegDS( theInstr );
11959    UChar frB_addr   = ifieldRegB( theInstr );
11960 
11961    IRTemp lmd       = newTemp( Ity_I32 );
11962    IRTemp result_hi = newTemp( Ity_I64 );
11963    IRTemp result_lo = newTemp( Ity_I64 );
11964 
11965    assign( frB_hi, getDReg( frB_addr ) );
11966    assign( frB_lo, getDReg( frB_addr + 1 ) );
11967    assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) );
11968    assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) );
11969 
11970    switch ( opc2 ) {
11971    case 0x142: // ddedpdq   DFP Decode DPD to BCD
11972    {
11973       IRTemp low_60_u = newTemp( Ity_I32 );
11974       IRTemp low_60_l = newTemp( Ity_I32 );
11975       IRTemp mid_60_u = newTemp( Ity_I32 );
11976       IRTemp mid_60_l = newTemp( Ity_I32 );
11977       IRTemp top_12_l = newTemp( Ity_I32 );
11978 
11979       DIP( "ddedpdq %llu,r%u,r%u\n", sp, frT_addr, frB_addr );
11980 
11981       /* Note, instruction only stores the lower 32 BCD digits in
11982        * the result
11983        */
11984       Generate_132_bit_bcd_string( mkexpr( frBI64_hi ),
11985                                    mkexpr( frBI64_lo ),
11986                                    &top_12_l,
11987                                    &mid_60_u,
11988                                    &mid_60_l,
11989                                    &low_60_u,
11990                                    &low_60_l );
11991 
11992       if ( ( sp == 0 ) || ( sp == 1 ) ) {
11993          /* Unsigned BCD string */
11994          assign( result_hi,
11995                  binop( Iop_32HLto64,
11996                         binop( Iop_Or32,
11997                                binop( Iop_Shl32,
11998                                       mkexpr( top_12_l ),
11999                                       mkU8( 24 ) ),
12000                                binop( Iop_Shr32,
12001                                       mkexpr( mid_60_u ),
12002                                       mkU8( 4 ) ) ),
12003                         binop( Iop_Or32,
12004                                binop( Iop_Shl32,
12005                                       mkexpr( mid_60_u ),
12006                                       mkU8( 28 ) ),
12007                                binop( Iop_Shr32,
12008                                       mkexpr( mid_60_l ),
12009                                       mkU8( 4 ) ) ) ) );
12010 
12011          assign( result_lo,
12012                  binop( Iop_32HLto64,
12013                         binop( Iop_Or32,
12014                                binop( Iop_Shl32,
12015                                       mkexpr( mid_60_l ),
12016                                       mkU8( 28 ) ),
12017                                mkexpr( low_60_u ) ),
12018                         mkexpr( low_60_l ) ) );
12019 
12020       } else {
12021          /* Signed BCD string, the cases for sp 2 and 3 only differ in how
12022           * the positive and negative values are encoded in the least
12023           * significant bits.
12024           */
12025          IRTemp sign = newTemp( Ity_I32 );
12026 
12027          if ( sp == 2 ) {
12028             /* Positive sign = 0xC, negative sign = 0xD */
12029             assign( sign,
12030                     binop( Iop_Or32,
12031                            binop( Iop_Shr32,
12032                                   unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
12033                                   mkU8( 31 ) ),
12034                            mkU32( 0xC ) ) );
12035 
12036          } else if ( sp == 3 ) {
12037             IRTemp tmp32 = newTemp( Ity_I32 );
12038 
12039             /* Positive sign = 0xF, negative sign = 0xD.
12040              * Need to complement sign bit then OR into bit position 1.
12041              */
12042             assign( tmp32,
12043                     binop( Iop_Xor32,
12044                            binop( Iop_Shr32,
12045                                   unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
12046                                   mkU8( 30 ) ),
12047                            mkU32( 0x2 ) ) );
12048 
12049             assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) );
12050 
12051          } else {
12052             vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
12053          }
12054 
12055          assign( result_hi,
12056                  binop( Iop_32HLto64,
12057                         binop( Iop_Or32,
12058                                binop( Iop_Shl32,
12059                                       mkexpr( top_12_l ),
12060                                       mkU8( 28 ) ),
12061                                mkexpr( mid_60_u ) ),
12062                         mkexpr( mid_60_l ) ) );
12063 
12064          assign( result_lo,
12065                  binop( Iop_32HLto64,
12066                         binop( Iop_Or32,
12067                                binop( Iop_Shl32,
12068                                       mkexpr( low_60_u ),
12069                                       mkU8( 4 ) ),
12070                                binop( Iop_Shr32,
12071                                       mkexpr( low_60_l ),
12072                                       mkU8( 28 ) ) ),
12073                         binop( Iop_Or32,
12074                                binop( Iop_Shl32,
12075                                       mkexpr( low_60_l ),
12076                                       mkU8( 4 ) ),
12077                                mkexpr( sign ) ) ) );
12078       }
12079 
12080       putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) );
12081       putDReg( frT_addr + 1,
12082                unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) );
12083    }
12084    break;
12085    case 0x342: // denbcdq   DFP Encode BCD to DPD
12086    {
12087       IRTemp valid_mask      = newTemp( Ity_I32 );
12088       IRTemp invalid_mask    = newTemp( Ity_I32 );
12089       IRTemp result128       = newTemp( Ity_D128 );
12090       IRTemp dfp_significand = newTemp( Ity_D128 );
12091       IRTemp tmp_hi          = newTemp( Ity_I64 );
12092       IRTemp tmp_lo          = newTemp( Ity_I64 );
12093       IRTemp dbcd_top_l      = newTemp( Ity_I32 );
12094       IRTemp dbcd_mid_u      = newTemp( Ity_I32 );
12095       IRTemp dbcd_mid_l      = newTemp( Ity_I32 );
12096       IRTemp dbcd_low_u      = newTemp( Ity_I32 );
12097       IRTemp dbcd_low_l      = newTemp( Ity_I32 );
12098       IRTemp bcd_top_8       = newTemp( Ity_I64 );
12099       IRTemp bcd_mid_60      = newTemp( Ity_I64 );
12100       IRTemp bcd_low_60      = newTemp( Ity_I64 );
12101       IRTemp sign_bit        = newTemp( Ity_I32 );
12102       IRTemp tmptop10        = newTemp( Ity_I64 );
12103       IRTemp tmpmid50        = newTemp( Ity_I64 );
12104       IRTemp tmplow50        = newTemp( Ity_I64 );
12105       IRTemp inval_bcd_digit_mask = newTemp( Ity_I32 );
12106 
12107       DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr );
12108 
12109       if ( s == 0 ) {
12110          /* Unsigned BCD string */
12111          assign( sign_bit, mkU32( 0 ) ); // set to zero for unsigned string
12112 
12113          assign( bcd_top_8,
12114                  binop( Iop_32HLto64,
12115                         mkU32( 0 ),
12116                         binop( Iop_And32,
12117                                binop( Iop_Shr32,
12118                                       unop( Iop_64HIto32,
12119                                             mkexpr( frBI64_hi ) ),
12120                                       mkU8( 24 ) ),
12121                                mkU32( 0xFF ) ) ) );
12122          assign( bcd_mid_60,
12123                  binop( Iop_32HLto64,
12124                         binop( Iop_Or32,
12125                                binop( Iop_Shr32,
12126                                       unop( Iop_64to32,
12127                                             mkexpr( frBI64_hi ) ),
12128                                       mkU8( 28 ) ),
12129                                binop( Iop_Shl32,
12130                                       unop( Iop_64HIto32,
12131                                             mkexpr( frBI64_hi ) ),
12132                                       mkU8( 4 ) ) ),
12133                         binop( Iop_Or32,
12134                                binop( Iop_Shl32,
12135                                       unop( Iop_64to32,
12136                                             mkexpr( frBI64_hi ) ),
12137                                       mkU8( 4 ) ),
12138                                binop( Iop_Shr32,
12139                                       unop( Iop_64HIto32,
12140                                             mkexpr( frBI64_lo ) ),
12141                                       mkU8( 28 ) ) ) ) );
12142 
12143          /* Note, the various helper functions ignores top 4-bits */
12144          assign( bcd_low_60, mkexpr( frBI64_lo ) );
12145 
12146          assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr( bcd_top_8 ) ) );
12147          assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) );
12148 
12149          assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr( bcd_mid_60 ) ) );
12150          assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) );
12151          assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) );
12152 
12153          assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) );
12154          assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) );
12155          assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) );
12156 
12157          /* The entire BCD string fits in lower 110-bits.  The LMD = 0,
12158           * value is not part of the final result. Only the right most
12159           * BCD digits are stored.
12160           */
12161          assign( lmd, mkU32( 0 ) );
12162 
12163          assign( invalid_mask,
12164                  binop( Iop_Or32,
12165                         bcd_digit_inval( mkU32( 0 ),
12166                                          unop( Iop_64to32,
12167                                                mkexpr( bcd_top_8 ) ) ),
12168                         binop( Iop_Or32,
12169                                bcd_digit_inval( unop( Iop_64HIto32,
12170                                                       mkexpr( bcd_mid_60 ) ),
12171                                                 unop( Iop_64to32,
12172                                                       mkexpr( bcd_mid_60 ) ) ),
12173                                bcd_digit_inval( unop( Iop_64HIto32,
12174                                                       mkexpr( bcd_low_60 ) ),
12175                                                 unop( Iop_64to32,
12176                                                       mkexpr( bcd_low_60 ) )
12177                                                 ) ) ) );
12178 
12179       } else if ( s == 1 ) {
12180          IRTemp sign          = newTemp( Ity_I32 );
12181          IRTemp zero          = newTemp( Ity_I32 );
12182          IRTemp pos_sign_mask = newTemp( Ity_I32 );
12183          IRTemp neg_sign_mask = newTemp( Ity_I32 );
12184 
12185          /* The sign of the BCD string is stored in lower 4 bits */
12186          assign( sign,
12187                  binop( Iop_And32,
12188                         unop( Iop_64to32, mkexpr( frBI64_lo ) ),
12189                         mkU32( 0xF ) ) );
12190          assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) );
12191          assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) );
12192          assign( sign_bit,
12193                  Generate_sign_bit( mkexpr( pos_sign_mask ),
12194                                     mkexpr( neg_sign_mask ) ) );
12195 
12196          /* Generate the value assuminig the sign and BCD digits are vaild */
12197          assign( bcd_top_8,
12198                  binop( Iop_32HLto64,
12199                         mkU32( 0x0 ),
12200                         binop( Iop_Shr32,
12201                                unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
12202                                mkU8( 28 ) ) ) );
12203 
12204          /* The various helper routines ignore the upper 4-bits */
12205          assign( bcd_mid_60, mkexpr( frBI64_hi ) );
12206 
12207          /* Remove bottom four sign bits */
12208          assign( bcd_low_60,
12209                  binop( Iop_32HLto64,
12210                         binop( Iop_Shr32,
12211                                unop( Iop_64HIto32,
12212                                      mkexpr( frBI64_lo ) ),
12213                                mkU8( 4 ) ),
12214                                binop( Iop_Or32,
12215                                       binop( Iop_Shl32,
12216                                              unop( Iop_64HIto32,
12217                                                    mkexpr( frBI64_lo ) ),
12218                                              mkU8( 28 ) ),
12219                                       binop( Iop_Shr32,
12220                                              unop( Iop_64to32,
12221                                                    mkexpr( frBI64_lo ) ),
12222                                              mkU8( 4 ) ) ) ) );
12223          assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr(bcd_top_8 ) ) );
12224          assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) );
12225 
12226          assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr(bcd_mid_60 ) ) );
12227          assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) );
12228          assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) );
12229 
12230          assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) );
12231          assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) );
12232          assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) );
12233 
12234          /* The entire BCD string fits in lower 110-bits.  The LMD value
12235           * is not stored in the final result for the DFP Long instruction.
12236           */
12237          assign( lmd, mkU32( 0 ) );
12238 
12239          /* Check for invalid sign and invalid BCD digit.  Don't check the
12240           *  bottom four bits of frBI64_lo as that is the sign value.
12241           */
12242          assign( zero, mkU32( 0 ) );
12243          assign( inval_bcd_digit_mask,
12244                  binop( Iop_Or32,
12245                         bcd_digit_inval( mkexpr( zero ),
12246                                          unop( Iop_64to32,
12247                                                mkexpr( bcd_top_8 ) ) ),
12248                         binop( Iop_Or32,
12249                                bcd_digit_inval( unop( Iop_64HIto32,
12250                                                      mkexpr( bcd_mid_60 ) ),
12251                                                unop( Iop_64to32,
12252                                                      mkexpr( bcd_mid_60 ) ) ),
12253                                bcd_digit_inval( unop( Iop_64HIto32,
12254                                                      mkexpr( frBI64_lo ) ),
12255                                                binop( Iop_Shr32,
12256                                                       unop( Iop_64to32,
12257                                                             mkexpr( frBI64_lo ) ),
12258                                                         mkU8( 4 ) ) ) ) ) );
12259          assign( invalid_mask,
12260                  Generate_inv_mask( mkexpr( inval_bcd_digit_mask ),
12261                                     mkexpr( pos_sign_mask ),
12262                                     mkexpr( neg_sign_mask ) ) );
12263 
12264       }
12265 
12266       assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
12267 
12268       /* Calculate the value of the result assuming sign and BCD digits
12269        * are all valid.
12270        */
12271       assign( dfp_significand,
12272               binop( Iop_D64HLtoD128,
12273                      unop( Iop_ReinterpI64asD64,
12274                            binop( Iop_32HLto64,
12275                                   binop( Iop_Or32,
12276                                          mkexpr( sign_bit ),
12277                                          mkexpr( dbcd_top_l ) ),
12278                                   binop( Iop_Or32,
12279                                          binop( Iop_Shl32,
12280                                                 mkexpr( dbcd_mid_u ),
12281                                                 mkU8( 18 ) ),
12282                                          binop( Iop_Shr32,
12283                                                 mkexpr( dbcd_mid_l ),
12284                                                 mkU8( 14 ) ) ) ) ),
12285                      unop( Iop_ReinterpI64asD64,
12286                            binop( Iop_32HLto64,
12287                                   binop( Iop_Or32,
12288                                          mkexpr( dbcd_low_u ),
12289                                          binop( Iop_Shl32,
12290                                                 mkexpr( dbcd_mid_l ),
12291                                                 mkU8( 18 ) ) ),
12292                                   mkexpr( dbcd_low_l ) ) ) ) );
12293 
12294       /* Break the result back down to 32-bit chunks and replace chunks.
12295        * If there was an invalid BCD digit or invalid sign value, replace
12296        * the calculated result with the invalid bit string.
12297        */
12298       assign( result128,
12299               binop( Iop_InsertExpD128,
12300                      mkU64( DFP_EXTND_BIAS ),
12301                      mkexpr( dfp_significand ) ) );
12302 
12303       assign( tmp_hi,
12304               unop( Iop_ReinterpD64asI64,
12305                     unop( Iop_D128HItoD64, mkexpr( result128 ) ) ) );
12306 
12307       assign( tmp_lo,
12308               unop( Iop_ReinterpD64asI64,
12309                     unop( Iop_D128LOtoD64, mkexpr( result128 ) ) ) );
12310 
12311       assign( result_hi,
12312               binop( Iop_32HLto64,
12313                      binop( Iop_Or32,
12314                             binop( Iop_And32,
12315                                    mkexpr( valid_mask ),
12316                                    unop( Iop_64HIto32, mkexpr( tmp_hi ) ) ),
12317                             binop( Iop_And32,
12318                                    mkU32( 0x7C000000 ),
12319                                    mkexpr( invalid_mask ) ) ),
12320                      binop( Iop_Or32,
12321                             binop( Iop_And32,
12322                                    mkexpr( valid_mask ),
12323                                    unop( Iop_64to32, mkexpr( tmp_hi ) ) ),
12324                             binop( Iop_And32,
12325                                    mkU32( 0x0 ),
12326                                    mkexpr( invalid_mask ) ) ) ) );
12327 
12328       assign( result_lo,
12329               binop( Iop_32HLto64,
12330                      binop( Iop_Or32,
12331                             binop( Iop_And32,
12332                                    mkexpr( valid_mask ),
12333                                    unop( Iop_64HIto32, mkexpr( tmp_lo ) ) ),
12334                             binop( Iop_And32,
12335                                    mkU32( 0x0 ),
12336                                    mkexpr( invalid_mask ) ) ),
12337                      binop( Iop_Or32,
12338                             binop( Iop_And32,
12339                                    mkexpr( valid_mask ),
12340                                    unop( Iop_64to32, mkexpr( tmp_lo ) ) ),
12341                             binop( Iop_And32,
12342                                    mkU32( 0x0 ),
12343                                    mkexpr( invalid_mask ) ) ) ) );
12344 
12345       putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) );
12346       putDReg( frT_addr + 1,
12347                unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) );
12348 
12349    }
12350    break;
12351    default:
12352       vpanic( "ERROR: dis_dfp_bcdq(ppc), undefined opc2 case " );
12353       break;
12354    }
12355    return True;
12356 }
12357 
dis_dfp_significant_digits(UInt theInstr)12358 static Bool dis_dfp_significant_digits( UInt theInstr )
12359 {
12360    UChar frA_addr = ifieldRegA( theInstr );
12361    UChar frB_addr = ifieldRegB( theInstr );
12362    IRTemp frA     = newTemp( Ity_D64 );
12363    UInt opc1      = ifieldOPC( theInstr );
12364    IRTemp B_sig   = newTemp( Ity_I8 );
12365    IRTemp K       = newTemp( Ity_I8 );
12366    IRTemp lmd_B   = newTemp( Ity_I32 );
12367    IRTemp field   = newTemp( Ity_I32 );
12368    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF
12369    IRTemp Unordered_true     = newTemp( Ity_I32 );
12370    IRTemp Eq_true_mask       = newTemp( Ity_I32 );
12371    IRTemp Lt_true_mask       = newTemp( Ity_I32 );
12372    IRTemp Gt_true_mask       = newTemp( Ity_I32 );
12373    IRTemp KisZero_true_mask  = newTemp( Ity_I32 );
12374    IRTemp KisZero_false_mask = newTemp( Ity_I32 );
12375 
12376    /* Get the reference singificance stored in frA */
12377    assign( frA, getDReg( frA_addr ) );
12378 
12379    /* Convert from 64 bit to 8 bits in two steps.  The Iop_64to8 is not
12380     * supported in 32-bit mode.
12381     */
12382    assign( K, unop( Iop_32to8,
12383                     binop( Iop_And32,
12384                            unop( Iop_64to32,
12385                                  unop( Iop_ReinterpD64asI64,
12386                                        mkexpr( frA ) ) ),
12387                            mkU32( 0x3F ) ) ) );
12388 
12389    switch ( opc1 ) {
12390    case 0x3b: // dtstsf   DFP Test Significance
12391    {
12392       IRTemp frB     = newTemp( Ity_D64 );
12393       IRTemp frBI64  = newTemp( Ity_I64 );
12394       IRTemp B_bcd_u = newTemp( Ity_I32 );
12395       IRTemp B_bcd_l = newTemp( Ity_I32 );
12396       IRTemp tmp64   = newTemp( Ity_I64 );
12397 
12398       DIP( "dtstsf %u,r%u,r%u\n", crfD, frA_addr, frB_addr );
12399 
12400       assign( frB, getDReg( frB_addr ) );
12401       assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) );
12402 
12403       /* Get the BCD string for the value stored in a series of I32 values.
12404        * Count the number of leading zeros.  Subtract the number of leading
12405        * zeros from 16 (maximum number of significant digits in DFP
12406        * Long).
12407        */
12408       Get_lmd( &lmd_B,
12409                binop( Iop_Shr32,
12410                       unop( Iop_64HIto32, mkexpr( frBI64 ) ),
12411                       mkU8( 31 - 5 ) ) ); // G-field[0:4]
12412 
12413       assign( tmp64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) );
12414       assign( B_bcd_u, unop( Iop_64HIto32, mkexpr( tmp64 ) ) );
12415       assign( B_bcd_l, unop( Iop_64to32, mkexpr( tmp64 ) ) );
12416 
12417       assign( B_sig,
12418               binop( Iop_Sub8,
12419                      mkU8( DFP_LONG_MAX_SIG_DIGITS ),
12420                      Count_leading_zeros_60( mkexpr( lmd_B ),
12421                                              mkexpr( B_bcd_u ),
12422                                              mkexpr( B_bcd_l ) ) ) );
12423       assign( Unordered_true, Check_unordered( mkexpr( frBI64 ) ) );
12424    }
12425    break;
12426    case 0x3F: // dtstsfq     DFP Test Significance
12427    {
12428       IRTemp frB_hi     = newTemp( Ity_D64 );
12429       IRTemp frB_lo     = newTemp( Ity_D64 );
12430       IRTemp frBI64_hi  = newTemp( Ity_I64 );
12431       IRTemp frBI64_lo  = newTemp( Ity_I64 );
12432       IRTemp B_low_60_u = newTemp( Ity_I32 );
12433       IRTemp B_low_60_l = newTemp( Ity_I32 );
12434       IRTemp B_mid_60_u = newTemp( Ity_I32 );
12435       IRTemp B_mid_60_l = newTemp( Ity_I32 );
12436       IRTemp B_top_12_l = newTemp( Ity_I32 );
12437 
12438       DIP( "dtstsfq %u,r%u,r%u\n", crfD, frA_addr, frB_addr );
12439 
12440       assign( frB_hi, getDReg( frB_addr ) );
12441       assign( frB_lo, getDReg( frB_addr + 1 ) );
12442 
12443       assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) );
12444       assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) );
12445 
12446       /* Get the BCD string for the value stored in a series of I32 values.
12447        * Count the number of leading zeros.  Subtract the number of leading
12448        * zeros from 32 (maximum number of significant digits in DFP
12449        * extended).
12450        */
12451       Get_lmd( &lmd_B,
12452                binop( Iop_Shr32,
12453                       unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
12454                       mkU8( 31 - 5 ) ) ); // G-field[0:4]
12455 
12456       Generate_132_bit_bcd_string( mkexpr( frBI64_hi ),
12457                                    mkexpr( frBI64_lo ),
12458                                    &B_top_12_l,
12459                                    &B_mid_60_u,
12460                                    &B_mid_60_l,
12461                                    &B_low_60_u,
12462                                    &B_low_60_l );
12463 
12464       assign( B_sig,
12465               binop( Iop_Sub8,
12466                      mkU8( DFP_EXTND_MAX_SIG_DIGITS ),
12467                      Count_leading_zeros_128( mkexpr( lmd_B ),
12468                                               mkexpr( B_top_12_l ),
12469                                               mkexpr( B_mid_60_u ),
12470                                               mkexpr( B_mid_60_l ),
12471                                               mkexpr( B_low_60_u ),
12472                                               mkexpr( B_low_60_l ) ) ) );
12473 
12474       assign( Unordered_true, Check_unordered( mkexpr( frBI64_hi ) ) );
12475    }
12476    break;
12477    }
12478 
12479    /* Compare (16 - cnt[0]) against K and set the condition code field
12480     * accordingly.
12481     *
12482     * The field layout is as follows:
12483     *
12484     * bit[3:0]    Description
12485     *    3     K != 0 and K < Number of significant digits if FRB
12486     *    2     K != 0 and K > Number of significant digits if FRB OR K = 0
12487     *    1     K != 0 and K = Number of significant digits if FRB
12488     *    0     K ? Number of significant digits if FRB
12489     */
12490    assign( Eq_true_mask,
12491            unop( Iop_1Sto32,
12492                  binop( Iop_CmpEQ32,
12493                         unop( Iop_8Uto32, mkexpr( K ) ),
12494                         unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) );
12495    assign( Lt_true_mask,
12496            unop( Iop_1Sto32,
12497                  binop( Iop_CmpLT32U,
12498                         unop( Iop_8Uto32, mkexpr( K ) ),
12499                         unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) );
12500    assign( Gt_true_mask,
12501            unop( Iop_1Sto32,
12502                  binop( Iop_CmpLT32U,
12503                         unop( Iop_8Uto32, mkexpr( B_sig ) ),
12504                         unop( Iop_8Uto32, mkexpr( K ) ) ) ) );
12505 
12506    assign( KisZero_true_mask,
12507            unop( Iop_1Sto32,
12508                  binop( Iop_CmpEQ32,
12509                         unop( Iop_8Uto32, mkexpr( K ) ),
12510                         mkU32( 0 ) ) ) );
12511    assign( KisZero_false_mask,
12512            unop( Iop_1Sto32,
12513                  binop( Iop_CmpNE32,
12514                         unop( Iop_8Uto32, mkexpr( K ) ),
12515                         mkU32( 0 ) ) ) );
12516 
12517    assign( field,
12518            binop( Iop_Or32,
12519                   binop( Iop_And32,
12520                          mkexpr( KisZero_false_mask ),
12521                          binop( Iop_Or32,
12522                                 binop( Iop_And32,
12523                                        mkexpr( Lt_true_mask ),
12524                                        mkU32( 0x8 ) ),
12525                                 binop( Iop_Or32,
12526                                        binop( Iop_And32,
12527                                               mkexpr( Gt_true_mask ),
12528                                               mkU32( 0x4 ) ),
12529                                        binop( Iop_And32,
12530                                               mkexpr( Eq_true_mask ),
12531                                               mkU32( 0x2 ) ) ) ) ),
12532                   binop( Iop_And32,
12533                          mkexpr( KisZero_true_mask ),
12534                          mkU32( 0x4 ) ) ) );
12535 
12536    putGST_field( PPC_GST_CR,
12537                  binop( Iop_Or32,
12538                         binop( Iop_And32,
12539                                mkexpr( Unordered_true ),
12540                                mkU32( 0x1 ) ),
12541                         binop( Iop_And32,
12542                                unop( Iop_Not32, mkexpr( Unordered_true ) ),
12543                                mkexpr( field ) ) ),
12544                  crfD );
12545 
12546    return True;
12547 }
12548 
12549 /*------------------------------------------------------------*/
12550 /*--- AltiVec Instruction Translation                      ---*/
12551 /*------------------------------------------------------------*/
12552 
12553 /*
12554   Altivec Cache Control Instructions (Data Streams)
12555 */
dis_av_datastream(UInt theInstr)12556 static Bool dis_av_datastream ( UInt theInstr )
12557 {
12558    /* X-Form */
12559    UChar opc1     = ifieldOPC(theInstr);
12560    UChar flag_T   = toUChar( IFIELD( theInstr, 25, 1 ) );
12561    UChar flag_A   = flag_T;
12562    UChar b23to24  = toUChar( IFIELD( theInstr, 23, 2 ) );
12563    UChar STRM     = toUChar( IFIELD( theInstr, 21, 2 ) );
12564    UChar rA_addr  = ifieldRegA(theInstr);
12565    UChar rB_addr  = ifieldRegB(theInstr);
12566    UInt  opc2     = ifieldOPClo10(theInstr);
12567    UChar b0       = ifieldBIT0(theInstr);
12568 
12569    if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) {
12570       vex_printf("dis_av_datastream(ppc)(instr)\n");
12571       return False;
12572    }
12573 
12574    switch (opc2) {
12575    case 0x156: // dst (Data Stream Touch, AV p115)
12576       DIP("dst%s r%u,r%u,%d\n", flag_T ? "t" : "",
12577                                 rA_addr, rB_addr, STRM);
12578       break;
12579 
12580    case 0x176: // dstst (Data Stream Touch for Store, AV p117)
12581       DIP("dstst%s r%u,r%u,%d\n", flag_T ? "t" : "",
12582                                   rA_addr, rB_addr, STRM);
12583       break;
12584 
12585    case 0x336: // dss (Data Stream Stop, AV p114)
12586       if (rA_addr != 0 || rB_addr != 0) {
12587          vex_printf("dis_av_datastream(ppc)(opc2,dst)\n");
12588          return False;
12589       }
12590       if (flag_A == 0) {
12591          DIP("dss %d\n", STRM);
12592       } else {
12593          DIP("dssall\n");
12594       }
12595       break;
12596 
12597    default:
12598       vex_printf("dis_av_datastream(ppc)(opc2)\n");
12599       return False;
12600    }
12601    return True;
12602 }
12603 
12604 /*
12605   AltiVec Processor Control Instructions
12606 */
dis_av_procctl(UInt theInstr)12607 static Bool dis_av_procctl ( UInt theInstr )
12608 {
12609    /* VX-Form */
12610    UChar opc1    = ifieldOPC(theInstr);
12611    UChar vD_addr = ifieldRegDS(theInstr);
12612    UChar vA_addr = ifieldRegA(theInstr);
12613    UChar vB_addr = ifieldRegB(theInstr);
12614    UInt  opc2    = IFIELD( theInstr, 0, 11 );
12615 
12616    if (opc1 != 0x4) {
12617       vex_printf("dis_av_procctl(ppc)(instr)\n");
12618       return False;
12619    }
12620 
12621    switch (opc2) {
12622    case 0x604: // mfvscr (Move from VSCR, AV p129)
12623       if (vA_addr != 0 || vB_addr != 0) {
12624          vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
12625          return False;
12626       }
12627       DIP("mfvscr v%d\n", vD_addr);
12628       putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) );
12629       break;
12630 
12631    case 0x644: { // mtvscr (Move to VSCR, AV p130)
12632       IRTemp vB = newTemp(Ity_V128);
12633       if (vD_addr != 0 || vA_addr != 0) {
12634          vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
12635          return False;
12636       }
12637       DIP("mtvscr v%d\n", vB_addr);
12638       assign( vB, getVReg(vB_addr));
12639       putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) );
12640       break;
12641    }
12642    default:
12643       vex_printf("dis_av_procctl(ppc)(opc2)\n");
12644       return False;
12645    }
12646    return True;
12647 }
12648 
12649 /*
12650  * VSX scalar and vector convert instructions
12651  */
12652 static Bool
dis_vx_conv(UInt theInstr,UInt opc2)12653 dis_vx_conv ( UInt theInstr, UInt opc2 )
12654 {
12655    /* XX2-Form */
12656    UChar opc1 = ifieldOPC( theInstr );
12657    UChar XT = ifieldRegXT( theInstr );
12658    UChar XB = ifieldRegXB( theInstr );
12659    IRTemp xB, xB2;
12660    IRTemp b3, b2, b1, b0;
12661    xB = xB2 = IRTemp_INVALID;
12662 
12663    if (opc1 != 0x3C) {
12664       vex_printf( "dis_vx_conv(ppc)(instr)\n" );
12665       return False;
12666    }
12667 
12668    /* Create and assign temps only as needed for the given instruction. */
12669    switch (opc2) {
12670       // scalar double-precision floating point argument
12671       case 0x2B0: case 0x0b0: case 0x290: case 0x212: case 0x216: case 0x090:
12672          xB = newTemp(Ity_F64);
12673          assign( xB,
12674                  unop( Iop_ReinterpI64asF64,
12675                        unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
12676          break;
12677       // vector double-precision floating point arguments
12678       case 0x1b0: case 0x312: case 0x390: case 0x190: case 0x3B0:
12679 
12680          xB = newTemp(Ity_F64);
12681          xB2 = newTemp(Ity_F64);
12682          assign( xB,
12683                  unop( Iop_ReinterpI64asF64,
12684                        unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
12685          assign( xB2,
12686                  unop( Iop_ReinterpI64asF64,
12687                        unop( Iop_V128to64, getVSReg( XB ) ) ) );
12688          break;
12689       // vector single precision or [un]signed integer word arguments
12690       case 0x130: case 0x392: case 0x330: case 0x310: case 0x110:
12691       case 0x1f0: case 0x1d0:
12692          b3 = b2 = b1 = b0 = IRTemp_INVALID;
12693          breakV128to4x32(getVSReg(XB), &b3, &b2, &b1, &b0);
12694          break;
12695          // vector [un]signed integer doubleword argument
12696       case 0x3f0: case 0x370: case 0x3d0: case 0x350:
12697          xB = newTemp(Ity_I64);
12698          assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
12699          xB2 = newTemp(Ity_I64);
12700          assign( xB2, unop( Iop_V128to64, getVSReg( XB ) ) );
12701          break;
12702       // scalar [un]signed integer doubleword argument
12703       case 0x250: case 0x270: case 0x2D0: case 0x2F0:
12704          xB = newTemp(Ity_I64);
12705          assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
12706          break;
12707       // scalar single precision argument
12708       case 0x292: // xscvspdp
12709          xB  = newTemp(Ity_I32);
12710 
12711          assign( xB, handle_SNaN_to_QNaN_32(unop( Iop_64HIto32,
12712                                                   unop( Iop_V128HIto64,
12713                                                         getVSReg( XB ) ) ) ) );
12714          break;
12715       case 0x296: // xscvspdpn (non signaling version of xscvpdp)
12716          xB = newTemp(Ity_I32);
12717          assign( xB,
12718                  unop( Iop_64HIto32, unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
12719          break;
12720 
12721       /* Certain instructions have their complete implementation in the main switch statement
12722        * that follows this one; thus we have a "do nothing" case for those instructions here.
12723        */
12724       case 0x170: case 0x150:
12725          break; // do nothing
12726 
12727       default:
12728          vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
12729          return False;
12730    }
12731 
12732 
12733    switch (opc2) {
12734       case 0x2B0:
12735          // xscvdpsxds (VSX Scalar truncate Double-Precision to integer and Convert
12736          //             to Signed Integer Doubleword format with Saturate)
12737          DIP("xscvdpsxds v%u,v%u\n", XT, XB);
12738          putVSReg( XT,
12739                    binop( Iop_64HLtoV128, binop( Iop_F64toI64S,
12740                                                  mkU32( Irrm_ZERO ),
12741                                                  mkexpr( xB ) ), mkU64( 0 ) ) );
12742          break;
12743       case 0x0b0: // xscvdpsxws (VSX Scalar truncate Double-Precision to integer and
12744                   //             Convert to Signed Integer Word format with Saturate)
12745          DIP("xscvdpsxws v%u,v%u\n", XT, XB);
12746          putVSReg( XT,
12747                    binop( Iop_64HLtoV128,
12748                           unop( Iop_32Sto64,
12749                                 binop( Iop_F64toI32S,
12750                                        mkU32( Irrm_ZERO ),
12751                                        mkexpr( xB ) ) ),
12752                                        mkU64( 0ULL ) ) );
12753          break;
12754       case 0x290: // xscvdpuxds (VSX Scalar truncate Double-Precision integer and Convert
12755                   //             to Unsigned Integer Doubleword format with Saturate)
12756          DIP("xscvdpuxds v%u,v%u\n", XT, XB);
12757          putVSReg( XT,
12758                    binop( Iop_64HLtoV128,
12759                           binop( Iop_F64toI64U,
12760                                  mkU32( Irrm_ZERO ),
12761                                  mkexpr( xB ) ),
12762                                  mkU64( 0ULL ) ) );
12763          break;
12764       case 0x270:
12765          // xscvsxdsp (VSX Scalar Convert and round Signed Integer Doubleword
12766          //             to Single-Precision format)
12767          DIP("xscvsxdsp v%u,v%u\n", XT, XB);
12768          putVSReg( XT,
12769                    binop( Iop_64HLtoV128,
12770                           unop( Iop_ReinterpF64asI64,
12771                                 binop( Iop_RoundF64toF32,
12772                                        get_IR_roundingmode(),
12773                                        binop( Iop_I64StoF64,
12774                                               get_IR_roundingmode(),
12775                                               mkexpr( xB ) ) ) ),
12776                           mkU64( 0 ) ) );
12777          break;
12778       case 0x2F0:
12779          // xscvsxddp (VSX Scalar Convert and round Signed Integer Doubleword to
12780          //            Double-Precision format)
12781          DIP("xscvsxddp v%u,v%u\n", XT, XB);
12782          putVSReg( XT,
12783                    binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
12784                                                 binop( Iop_I64StoF64, get_IR_roundingmode(),
12785                                                        mkexpr( xB ) ) ),
12786                                                        mkU64( 0 ) ) );
12787          break;
12788       case 0x250:
12789          // xscvuxdsp (VSX Scalar Convert and round Unsigned Integer
12790          //            Doubleword to Singel-Precision format)
12791          DIP("xscvuxdsp v%u,v%u\n", XT, XB);
12792          putVSReg( XT,
12793                    binop( Iop_64HLtoV128,
12794                           unop( Iop_ReinterpF64asI64,
12795                                 binop( Iop_RoundF64toF32,
12796                                        get_IR_roundingmode(),
12797                                        binop( Iop_I64UtoF64,
12798                                               get_IR_roundingmode(),
12799                                               mkexpr( xB ) ) ) ),
12800                           mkU64( 0 ) ) );
12801          break;
12802       case 0x2D0:
12803          // xscvuxddp (VSX Scalar Convert and round Unsigned Integer Doubleword to
12804          //            Double-Precision format)
12805          DIP("xscvuxddp v%u,v%u\n", XT, XB);
12806          putVSReg( XT,
12807                    binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
12808                                                 binop( Iop_I64UtoF64, get_IR_roundingmode(),
12809                                                        mkexpr( xB ) ) ),
12810                                                        mkU64( 0 ) ) );
12811          break;
12812       case 0x1b0: // xvcvdpsxws (VSX Vector truncate Double-Precision to integer and Convert
12813                   //             to Signed Integer Word format with Saturate)
12814       {
12815          IRTemp hiResult_32 = newTemp(Ity_I32);
12816          IRTemp loResult_32 = newTemp(Ity_I32);
12817          IRExpr* rmZero = mkU32(Irrm_ZERO);
12818 
12819          DIP("xvcvdpsxws v%u,v%u\n",  XT, XB);
12820          assign(hiResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB)));
12821          assign(loResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB2)));
12822          putVSReg( XT,
12823                    binop( Iop_64HLtoV128,
12824                           unop( Iop_32Sto64, mkexpr( hiResult_32 ) ),
12825                           unop( Iop_32Sto64, mkexpr( loResult_32 ) ) ) );
12826          break;
12827       }
12828       case 0x130: case 0x110: // xvcvspsxws, xvcvspuxws
12829          //  (VSX Vector truncate Single-Precision to integer and
12830          //   Convert to [Un]signed Integer Word format with Saturate)
12831       {
12832          IRExpr * b0_result, * b1_result, * b2_result, * b3_result;
12833          IRTemp tempResult = newTemp(Ity_V128);
12834          IRTemp res0 = newTemp(Ity_I32);
12835          IRTemp res1 = newTemp(Ity_I32);
12836          IRTemp res2 = newTemp(Ity_I32);
12837          IRTemp res3 = newTemp(Ity_I32);
12838          IRTemp hi64 = newTemp(Ity_I64);
12839          IRTemp lo64 = newTemp(Ity_I64);
12840          Bool un_signed = (opc2 == 0x110);
12841          IROp op = un_signed ? Iop_QFtoI32Ux4_RZ : Iop_QFtoI32Sx4_RZ;
12842 
12843          DIP("xvcvsp%sxws v%u,v%u\n", un_signed ? "u" : "s", XT, XB);
12844          /* The xvcvsp{s|u}xws instruction is similar to vct{s|u}xs, except if src is a NaN,
12845           * then result is set to 0x80000000.  */
12846          assign(tempResult, unop(op, getVSReg(XB)));
12847          assign( hi64, unop(Iop_V128HIto64, mkexpr(tempResult)) );
12848          assign( lo64, unop(Iop_V128to64,   mkexpr(tempResult)) );
12849          assign( res3, unop(Iop_64HIto32, mkexpr(hi64)) );
12850          assign( res2, unop(Iop_64to32,   mkexpr(hi64)) );
12851          assign( res1, unop(Iop_64HIto32, mkexpr(lo64)) );
12852          assign( res0, unop(Iop_64to32,   mkexpr(lo64)) );
12853 
12854          b3_result = IRExpr_ITE(is_NaN_32(b3),
12855                                 // then: result is 0x{8|0}80000000
12856                                 mkU32(un_signed ? 0x00000000 : 0x80000000),
12857                                 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
12858                                 mkexpr(res3));
12859          b2_result = IRExpr_ITE(is_NaN_32(b2),
12860                                 // then: result is 0x{8|0}80000000
12861                                 mkU32(un_signed ? 0x00000000 : 0x80000000),
12862                                 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
12863                                 mkexpr(res2));
12864          b1_result = IRExpr_ITE(is_NaN_32(b1),
12865                                 // then: result is 0x{8|0}80000000
12866                                 mkU32(un_signed ? 0x00000000 : 0x80000000),
12867                                 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
12868                                 mkexpr(res1));
12869          b0_result = IRExpr_ITE(is_NaN_32(b0),
12870                                 // then: result is 0x{8|0}80000000
12871                                 mkU32(un_signed ? 0x00000000 : 0x80000000),
12872                                 // else: result is from the Iop_QFtoI32{s|u}x4_RZ
12873                                 mkexpr(res0));
12874 
12875          putVSReg( XT,
12876                    binop( Iop_64HLtoV128,
12877                           binop( Iop_32HLto64, b3_result, b2_result ),
12878                           binop( Iop_32HLto64, b1_result, b0_result ) ) );
12879          break;
12880       }
12881       case 0x212: // xscvdpsp (VSX Scalar round Double-Precision to single-precision and
12882                   //           Convert to Single-Precision format
12883          DIP("xscvdpsp v%u,v%u\n", XT, XB);
12884          putVSReg( XT,
12885                    binop( Iop_64HLtoV128,
12886                           binop( Iop_32HLto64,
12887                                  unop( Iop_ReinterpF32asI32,
12888                                        unop( Iop_TruncF64asF32,
12889                                              binop( Iop_RoundF64toF32,
12890                                                     get_IR_roundingmode(),
12891                                                     mkexpr( xB ) ) ) ),
12892                                  mkU32( 0 ) ),
12893                           mkU64( 0ULL ) ) );
12894          break;
12895       case 0x216: /* xscvdpspn (VSX Scalar convert scalar Single-Precision to
12896                               vector Single-Precision non-signalling */
12897          DIP("xscvdpspn v%u,v%u\n", XT, XB);
12898          putVSReg( XT,
12899                    binop( Iop_64HLtoV128,
12900                           binop( Iop_32HLto64,
12901                                  unop( Iop_ReinterpF32asI32,
12902                                        unop( Iop_TruncF64asF32,
12903                                              mkexpr( xB ) ) ),
12904                                  mkU32( 0 ) ),
12905                           mkU64( 0ULL ) ) );
12906          break;
12907       case 0x090: // xscvdpuxws (VSX Scalar truncate Double-Precision to integer
12908                   //             and Convert to Unsigned Integer Word format with Saturate)
12909          DIP("xscvdpuxws v%u,v%u\n", XT, XB);
12910          putVSReg( XT,
12911                    binop( Iop_64HLtoV128,
12912                           binop( Iop_32HLto64,
12913                                  mkU32( 0 ),
12914                                  binop( Iop_F64toI32U,
12915                                         mkU32( Irrm_ZERO ),
12916                                         mkexpr( xB ) ) ),
12917                           mkU64( 0ULL ) ) );
12918          break;
12919       case 0x292: // xscvspdp (VSX Scalar Convert Single-Precision to Double-Precision format, signaling)
12920          DIP("xscvspdp v%u,v%u\n", XT, XB);
12921          putVSReg( XT,
12922                    binop( Iop_64HLtoV128,
12923                           unop( Iop_ReinterpF64asI64,
12924                                 unop( Iop_F32toF64,
12925                                       unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
12926                           mkU64( 0ULL ) ) );
12927          break;
12928       case 0x296: // xscvspdpn (VSX Scalar Convert Single-Precision to Double-Precision format Non signaling)
12929          DIP("xscvspdpn v%u,v%u\n", XT, XB);
12930          putVSReg( XT,
12931                    binop( Iop_64HLtoV128,
12932                           unop( Iop_ReinterpF64asI64,
12933                                 unop( Iop_F32toF64,
12934                                       unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
12935                                       mkU64( 0ULL ) ) );
12936          break;
12937       case 0x312: // xvcvdpsp (VSX Vector round Double-Precision to single-precision
12938                   //           and Convert to Single-Precision format)
12939          DIP("xvcvdpsp v%u,v%u\n", XT, XB);
12940          putVSReg( XT,
12941                    binop( Iop_64HLtoV128,
12942                           binop( Iop_32HLto64,
12943                                  unop( Iop_ReinterpF32asI32,
12944                                        unop( Iop_TruncF64asF32,
12945                                              binop( Iop_RoundF64toF32,
12946                                                     get_IR_roundingmode(),
12947                                                     mkexpr( xB ) ) ) ),
12948                                  mkU32( 0 ) ),
12949                           binop( Iop_32HLto64,
12950                                  unop( Iop_ReinterpF32asI32,
12951                                        unop( Iop_TruncF64asF32,
12952                                              binop( Iop_RoundF64toF32,
12953                                                     get_IR_roundingmode(),
12954                                                     mkexpr( xB2 ) ) ) ),
12955                                  mkU32( 0 ) ) ) );
12956          break;
12957       case 0x390: // xvcvdpuxds (VSX Vector truncate Double-Precision to integer
12958                   //             and Convert to Unsigned Integer Doubleword format
12959                   //             with Saturate)
12960          DIP("xvcvdpuxds v%u,v%u\n", XT, XB);
12961          putVSReg( XT,
12962                    binop( Iop_64HLtoV128,
12963                           binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
12964                           binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
12965          break;
12966       case 0x190: // xvcvdpuxws (VSX Vector truncate Double-Precision to integer and
12967                   //             Convert to Unsigned Integer Word format with Saturate)
12968          DIP("xvcvdpuxws v%u,v%u\n", XT, XB);
12969          putVSReg( XT,
12970                    binop( Iop_64HLtoV128,
12971                           binop( Iop_32HLto64,
12972                                  binop( Iop_F64toI32U,
12973                                         mkU32( Irrm_ZERO ),
12974                                         mkexpr( xB ) ),
12975                                  mkU32( 0 ) ),
12976                           binop( Iop_32HLto64,
12977                                  binop( Iop_F64toI32U,
12978                                         mkU32( Irrm_ZERO ),
12979                                         mkexpr( xB2 ) ),
12980                                  mkU32( 0 ) ) ) );
12981          break;
12982       case 0x392: // xvcvspdp (VSX Vector Convert Single-Precision to Double-Precision format)
12983          DIP("xvcvspdp v%u,v%u\n", XT, XB);
12984          putVSReg( XT,
12985                    binop( Iop_64HLtoV128,
12986                           unop( Iop_ReinterpF64asI64,
12987                                 unop( Iop_F32toF64,
12988                                       unop( Iop_ReinterpI32asF32,
12989                                             handle_SNaN_to_QNaN_32( mkexpr( b3 ) ) ) ) ),
12990                           unop( Iop_ReinterpF64asI64,
12991                                 unop( Iop_F32toF64,
12992                                       unop( Iop_ReinterpI32asF32,
12993                                             handle_SNaN_to_QNaN_32( mkexpr( b1 ) ) ) ) ) ) );
12994          break;
12995       case 0x330: // xvcvspsxds (VSX Vector truncate Single-Precision to integer and
12996                   //           Convert to Signed Integer Doubleword format with Saturate)
12997          DIP("xvcvspsxds v%u,v%u\n", XT, XB);
12998          putVSReg( XT,
12999                    binop( Iop_64HLtoV128,
13000                           binop( Iop_F64toI64S,
13001                                  mkU32( Irrm_ZERO ),
13002                                  unop( Iop_F32toF64,
13003                                        unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
13004                           binop( Iop_F64toI64S,
13005                                  mkU32( Irrm_ZERO ),
13006                                  unop( Iop_F32toF64,
13007                                        unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
13008          break;
13009       case 0x310: // xvcvspuxds (VSX Vector truncate Single-Precision to integer and
13010                   //            Convert to Unsigned Integer Doubleword format with Saturate)
13011          DIP("xvcvspuxds v%u,v%u\n", XT, XB);
13012          putVSReg( XT,
13013                    binop( Iop_64HLtoV128,
13014                           binop( Iop_F64toI64U,
13015                                  mkU32( Irrm_ZERO ),
13016                                  unop( Iop_F32toF64,
13017                                        unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
13018                           binop( Iop_F64toI64U,
13019                                  mkU32( Irrm_ZERO ),
13020                                  unop( Iop_F32toF64,
13021                                        unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
13022          break;
13023       case 0x3B0: // xvcvdpsxds (VSX Vector truncate Double-Precision to integer and
13024                   //             Convert to Signed Integer Doubleword format with Saturate)
13025          DIP("xvcvdpsxds v%u,v%u\n", XT, XB);
13026          putVSReg( XT,
13027                    binop( Iop_64HLtoV128,
13028                           binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
13029                           binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
13030          break;
13031       case 0x3f0: // xvcvsxddp (VSX Vector Convert and round Signed Integer Doubleword
13032                   //            to Double-Precision format)
13033          DIP("xvcvsxddp v%u,v%u\n", XT, XB);
13034          putVSReg( XT,
13035                    binop( Iop_64HLtoV128,
13036                           unop( Iop_ReinterpF64asI64,
13037                                 binop( Iop_I64StoF64,
13038                                        get_IR_roundingmode(),
13039                                        mkexpr( xB ) ) ),
13040                           unop( Iop_ReinterpF64asI64,
13041                                 binop( Iop_I64StoF64,
13042                                        get_IR_roundingmode(),
13043                                        mkexpr( xB2 ) ) ) ) );
13044          break;
13045       case 0x3d0: // xvcvuxddp (VSX Vector Convert and round Unsigned Integer Doubleword
13046                   //            to Double-Precision format)
13047          DIP("xvcvuxddp v%u,v%u\n", XT, XB);
13048          putVSReg( XT,
13049                    binop( Iop_64HLtoV128,
13050                           unop( Iop_ReinterpF64asI64,
13051                                 binop( Iop_I64UtoF64,
13052                                        get_IR_roundingmode(),
13053                                        mkexpr( xB ) ) ),
13054                           unop( Iop_ReinterpF64asI64,
13055                                 binop( Iop_I64UtoF64,
13056                                        get_IR_roundingmode(),
13057                                        mkexpr( xB2 ) ) ) ) );
13058 
13059          break;
13060       case 0x370: // xvcvsxdsp (VSX Vector Convert and round Signed Integer Doubleword
13061                   //            to Single-Precision format)
13062          DIP("xvcvsxddp v%u,v%u\n",  XT, XB);
13063          putVSReg( XT,
13064                    binop( Iop_64HLtoV128,
13065                           binop( Iop_32HLto64,
13066                                  unop( Iop_ReinterpF32asI32,
13067                                        unop( Iop_TruncF64asF32,
13068                                              binop( Iop_RoundF64toF32,
13069                                                     get_IR_roundingmode(),
13070                                                     binop( Iop_I64StoF64,
13071                                                            get_IR_roundingmode(),
13072                                                            mkexpr( xB ) ) ) ) ),
13073                                  mkU32( 0 ) ),
13074                           binop( Iop_32HLto64,
13075                                  unop( Iop_ReinterpF32asI32,
13076                                        unop( Iop_TruncF64asF32,
13077                                              binop( Iop_RoundF64toF32,
13078                                                     get_IR_roundingmode(),
13079                                                     binop( Iop_I64StoF64,
13080                                                            get_IR_roundingmode(),
13081                                                            mkexpr( xB2 ) ) ) ) ),
13082                                  mkU32( 0 ) ) ) );
13083          break;
13084       case 0x350: // xvcvuxdsp (VSX Vector Convert and round Unsigned Integer Doubleword
13085                   //            to Single-Precision format)
13086          DIP("xvcvuxddp v%u,v%u\n", XT, XB);
13087          putVSReg( XT,
13088                    binop( Iop_64HLtoV128,
13089                           binop( Iop_32HLto64,
13090                                  unop( Iop_ReinterpF32asI32,
13091                                        unop( Iop_TruncF64asF32,
13092                                              binop( Iop_RoundF64toF32,
13093                                                     get_IR_roundingmode(),
13094                                                     binop( Iop_I64UtoF64,
13095                                                            get_IR_roundingmode(),
13096                                                            mkexpr( xB ) ) ) ) ),
13097                                  mkU32( 0 ) ),
13098                           binop( Iop_32HLto64,
13099                                  unop( Iop_ReinterpF32asI32,
13100                                        unop( Iop_TruncF64asF32,
13101                                              binop( Iop_RoundF64toF32,
13102                                                     get_IR_roundingmode(),
13103                                                     binop( Iop_I64UtoF64,
13104                                                            get_IR_roundingmode(),
13105                                                            mkexpr( xB2 ) ) ) ) ),
13106                                  mkU32( 0 ) ) ) );
13107          break;
13108 
13109       case 0x1f0: // xvcvsxwdp (VSX Vector Convert Signed Integer Word to Double-Precision format)
13110          DIP("xvcvsxwdp v%u,v%u\n",  XT, XB);
13111          putVSReg( XT,
13112                    binop( Iop_64HLtoV128,
13113                           unop( Iop_ReinterpF64asI64,
13114                                 binop( Iop_I64StoF64, get_IR_roundingmode(),
13115                                        unop( Iop_32Sto64, mkexpr( b3 ) ) ) ),
13116                           unop( Iop_ReinterpF64asI64,
13117                                 binop( Iop_I64StoF64, get_IR_roundingmode(),
13118                                        unop( Iop_32Sto64, mkexpr( b1 ) ) ) ) ) );
13119          break;
13120       case 0x1d0: // xvcvuxwdp (VSX Vector Convert Unsigned Integer Word to Double-Precision format)
13121          DIP("xvcvuxwdp v%u,v%u\n",  XT, XB);
13122          putVSReg( XT,
13123                    binop( Iop_64HLtoV128,
13124                           unop( Iop_ReinterpF64asI64,
13125                                 binop( Iop_I64UtoF64, get_IR_roundingmode(),
13126                                        unop( Iop_32Uto64, mkexpr( b3 ) ) ) ),
13127                           unop( Iop_ReinterpF64asI64,
13128                                 binop( Iop_I64UtoF64, get_IR_roundingmode(),
13129                                        unop( Iop_32Uto64, mkexpr( b1 ) ) ) ) ) );
13130          break;
13131       case 0x170: // xvcvsxwsp (VSX Vector Convert Signed Integer Word to Single-Precision format)
13132          DIP("xvcvsxwsp v%u,v%u\n",  XT, XB);
13133          putVSReg( XT, unop( Iop_I32StoFx4, getVSReg( XB ) ) );
13134          break;
13135       case 0x150: // xvcvuxwsp (VSX Vector Convert Unsigned Integer Word to Single-Precision format)
13136          DIP("xvcvuxwsp v%u,v%u\n",  XT, XB);
13137          putVSReg( XT, unop( Iop_I32UtoFx4, getVSReg( XB ) ) );
13138          break;
13139 
13140       default:
13141          vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
13142          return False;
13143    }
13144    return True;
13145 }
13146 
13147 /*
13148  * VSX vector Double Precision Floating Point Arithmetic Instructions
13149  */
13150 static Bool
dis_vxv_dp_arith(UInt theInstr,UInt opc2)13151 dis_vxv_dp_arith ( UInt theInstr, UInt opc2 )
13152 {
13153    /* XX3-Form */
13154    UChar opc1 = ifieldOPC( theInstr );
13155    UChar XT = ifieldRegXT( theInstr );
13156    UChar XA = ifieldRegXA( theInstr );
13157    UChar XB = ifieldRegXB( theInstr );
13158    IRExpr* rm = get_IR_roundingmode();
13159    IRTemp frA = newTemp(Ity_F64);
13160    IRTemp frB = newTemp(Ity_F64);
13161    IRTemp frA2 = newTemp(Ity_F64);
13162    IRTemp frB2 = newTemp(Ity_F64);
13163 
13164    if (opc1 != 0x3C) {
13165       vex_printf( "dis_vxv_dp_arith(ppc)(instr)\n" );
13166       return False;
13167    }
13168 
13169    assign(frA,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
13170    assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
13171    assign(frA2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XA ))));
13172    assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XB ))));
13173 
13174    switch (opc2) {
13175       case 0x1E0: // xvdivdp (VSX Vector Divide Double-Precision)
13176       case 0x1C0: // xvmuldp (VSX Vector Multiply Double-Precision)
13177       case 0x180: // xvadddp (VSX Vector Add Double-Precision)
13178       case 0x1A0: // xvsubdp (VSX Vector Subtract Double-Precision)
13179       {
13180          IROp mOp;
13181          const HChar * oper_name;
13182          switch (opc2) {
13183             case 0x1E0:
13184                mOp = Iop_DivF64;
13185                oper_name = "div";
13186                break;
13187             case 0x1C0:
13188                mOp = Iop_MulF64;
13189                oper_name = "mul";
13190                break;
13191             case 0x180:
13192                mOp = Iop_AddF64;
13193                oper_name = "add";
13194                break;
13195             case 0x1A0:
13196                mOp = Iop_SubF64;
13197                oper_name = "sub";
13198                break;
13199 
13200             default:
13201                vpanic("The impossible happened: dis_vxv_dp_arith(ppc)");
13202          }
13203          IRTemp hiResult = newTemp(Ity_I64);
13204          IRTemp loResult = newTemp(Ity_I64);
13205          DIP("xv%sdp v%d,v%d,v%d\n", oper_name, XT, XA, XB);
13206 
13207          assign( hiResult,
13208                  unop( Iop_ReinterpF64asI64,
13209                        triop( mOp, rm, mkexpr( frA ), mkexpr( frB ) ) ) );
13210          assign( loResult,
13211                  unop( Iop_ReinterpF64asI64,
13212                        triop( mOp, rm, mkexpr( frA2 ), mkexpr( frB2 ) ) ) );
13213          putVSReg( XT,
13214                    binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
13215          break;
13216       }
13217       case 0x196: // xvsqrtdp
13218       {
13219          IRTemp hiResult = newTemp(Ity_I64);
13220          IRTemp loResult = newTemp(Ity_I64);
13221          DIP("xvsqrtdp v%d,v%d\n", XT, XB);
13222 
13223          assign( hiResult,
13224                  unop( Iop_ReinterpF64asI64,
13225                        binop( Iop_SqrtF64, rm, mkexpr( frB ) ) ) );
13226          assign( loResult,
13227                  unop( Iop_ReinterpF64asI64,
13228                        binop( Iop_SqrtF64, rm, mkexpr( frB2 ) ) ) );
13229          putVSReg( XT,
13230                    binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
13231          break;
13232       }
13233       case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp (VSX Vector Multiply-Add Double-Precision)
13234       case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp (VSX Vector Multiply-Subtract Double-Precision)
13235       case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp (VSX Vector Negate Multiply-Add Double-Precision)
13236       case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp (VSX Vector Negate Multiply-Subtract Double-Precision)
13237       {
13238          /* xvm{add|sub}mdp XT,XA,XB is element-wise equivalent to fm{add|sub} FRT,FRA,FRC,FRB with . . .
13239           *    XT == FRC
13240           *    XA == FRA
13241           *    XB == FRB
13242           *
13243           * and for xvm{add|sub}adp . . .
13244           *    XT == FRB
13245           *    XA == FRA
13246           *    XB == FRC
13247           */
13248          Bool negate;
13249          IROp mOp = Iop_INVALID;
13250          const HChar * oper_name = NULL;
13251          Bool mdp = False;
13252 
13253          switch (opc2) {
13254             case 0x184: case 0x1A4:
13255             case 0x384: case 0x3A4:
13256                mOp = Iop_MAddF64;
13257                oper_name = "add";
13258                mdp = (opc2 & 0x0FF) == 0x0A4;
13259                break;
13260 
13261             case 0x1C4: case 0x1E4:
13262             case 0x3C4: case 0x3E4:
13263                mOp = Iop_MSubF64;
13264                oper_name = "sub";
13265                mdp = (opc2 & 0x0FF) == 0x0E4;
13266                break;
13267 
13268             default:
13269                vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
13270          }
13271 
13272          switch (opc2) {
13273             case 0x384: case 0x3A4:
13274             case 0x3C4: case 0x3E4:
13275                negate = True;
13276                break;
13277             default:
13278                negate = False;
13279          }
13280          IRTemp hiResult = newTemp(Ity_I64);
13281          IRTemp loResult = newTemp(Ity_I64);
13282          IRTemp frT = newTemp(Ity_F64);
13283          IRTemp frT2 = newTemp(Ity_F64);
13284          DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, mdp ? "mdp" : "adp",
13285              XT, XA, XB);
13286          assign(frT,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XT ) ) ) );
13287          assign(frT2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XT ) ) ) );
13288 
13289          assign( hiResult,
13290                  unop( Iop_ReinterpF64asI64,
13291                        qop( mOp,
13292                             rm,
13293                             mkexpr( frA ),
13294                             mkexpr( mdp ? frT : frB ),
13295                             mkexpr( mdp ? frB : frT ) ) ) );
13296          assign( loResult,
13297                  unop( Iop_ReinterpF64asI64,
13298                        qop( mOp,
13299                             rm,
13300                             mkexpr( frA2 ),
13301                             mkexpr( mdp ? frT2 : frB2 ),
13302                             mkexpr( mdp ? frB2 : frT2 ) ) ) );
13303          putVSReg( XT,
13304                    binop( Iop_64HLtoV128,
13305                           mkexpr( negate ? getNegatedResult( hiResult )
13306                                          : hiResult ),
13307                           mkexpr( negate ? getNegatedResult( loResult )
13308                                          : loResult ) ) );
13309          break;
13310       }
13311       case 0x1D4: // xvtsqrtdp (VSX Vector Test for software Square Root Double-Precision)
13312       {
13313          IRTemp frBHi_I64 = newTemp(Ity_I64);
13314          IRTemp frBLo_I64 = newTemp(Ity_I64);
13315          IRTemp flagsHi = newTemp(Ity_I32);
13316          IRTemp flagsLo = newTemp(Ity_I32);
13317          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
13318          IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
13319          fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
13320 
13321          DIP("xvtsqrtdp cr%d,v%d\n", crfD, XB);
13322          assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
13323          assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
13324          do_fp_tsqrt(frBHi_I64, False /*not single precision*/, &fe_flagHi, &fg_flagHi);
13325          do_fp_tsqrt(frBLo_I64, False /*not single precision*/, &fe_flagLo, &fg_flagLo);
13326          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
13327           * where fl_flag == 1 on ppc64.
13328           */
13329          assign( flagsHi,
13330                  binop( Iop_Or32,
13331                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
13332                                binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
13333                         binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
13334          assign( flagsLo,
13335                  binop( Iop_Or32,
13336                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
13337                                binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
13338                         binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
13339          putGST_field( PPC_GST_CR,
13340                        binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
13341                        crfD );
13342          break;
13343       }
13344       case 0x1F4: // xvtdivdp (VSX Vector Test for software Divide Double-Precision)
13345       {
13346          IRTemp frBHi_I64 = newTemp(Ity_I64);
13347          IRTemp frBLo_I64 = newTemp(Ity_I64);
13348          IRTemp frAHi_I64 = newTemp(Ity_I64);
13349          IRTemp frALo_I64 = newTemp(Ity_I64);
13350          IRTemp flagsHi = newTemp(Ity_I32);
13351          IRTemp flagsLo = newTemp(Ity_I32);
13352          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
13353          IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
13354          fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
13355 
13356          DIP("xvtdivdp cr%d,v%d,v%d\n", crfD, XA, XB);
13357          assign( frAHi_I64, unop(Iop_V128HIto64, getVSReg( XA )) );
13358          assign( frALo_I64, unop(Iop_V128to64, getVSReg( XA )) );
13359          assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
13360          assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
13361 
13362          _do_fp_tdiv(frAHi_I64, frBHi_I64, False/*dp*/, &fe_flagHi, &fg_flagHi);
13363          _do_fp_tdiv(frALo_I64, frBLo_I64, False/*dp*/, &fe_flagLo, &fg_flagLo);
13364          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
13365           * where fl_flag == 1 on ppc64.
13366           */
13367          assign( flagsHi,
13368                  binop( Iop_Or32,
13369                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
13370                                binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
13371                         binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
13372          assign( flagsLo,
13373                  binop( Iop_Or32,
13374                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
13375                                binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
13376                         binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
13377          putGST_field( PPC_GST_CR,
13378                        binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
13379                        crfD );
13380          break;
13381       }
13382 
13383       default:
13384          vex_printf( "dis_vxv_dp_arith(ppc)(opc2)\n" );
13385          return False;
13386    }
13387    return True;
13388 }
13389 
13390 /*
13391  * VSX vector Single Precision Floating Point Arithmetic Instructions
13392  */
13393 static Bool
dis_vxv_sp_arith(UInt theInstr,UInt opc2)13394 dis_vxv_sp_arith ( UInt theInstr, UInt opc2 )
13395 {
13396    /* XX3-Form */
13397    UChar opc1 = ifieldOPC( theInstr );
13398    UChar XT = ifieldRegXT( theInstr );
13399    UChar XA = ifieldRegXA( theInstr );
13400    UChar XB = ifieldRegXB( theInstr );
13401    IRExpr* rm = get_IR_roundingmode();
13402    IRTemp a3, a2, a1, a0;
13403    IRTemp b3, b2, b1, b0;
13404    IRTemp res0 = newTemp(Ity_I32);
13405    IRTemp res1 = newTemp(Ity_I32);
13406    IRTemp res2 = newTemp(Ity_I32);
13407    IRTemp res3 = newTemp(Ity_I32);
13408 
13409    a3 = a2 = a1 = a0 = IRTemp_INVALID;
13410    b3 = b2 = b1 = b0 = IRTemp_INVALID;
13411 
13412    if (opc1 != 0x3C) {
13413       vex_printf( "dis_vxv_sp_arith(ppc)(instr)\n" );
13414       return False;
13415    }
13416 
13417    switch (opc2) {
13418       case 0x100: // xvaddsp (VSX Vector Add Single-Precision)
13419          DIP("xvaddsp v%d,v%d,v%d\n", XT, XA, XB);
13420          // WARNING: BOGUS! The backend ignores rm on Iop_Add32Fx4
13421          putVSReg( XT, triop(Iop_Add32Fx4, rm,
13422                              getVSReg( XA ), getVSReg( XB )) );
13423          break;
13424 
13425       case 0x140: // xvmulsp (VSX Vector Multiply Single-Precision)
13426          DIP("xvmulsp v%d,v%d,v%d\n", XT, XA, XB);
13427          // WARNING: BOGUS! The backend ignores rm on Iop_Mul32Fx4
13428          putVSReg( XT, triop(Iop_Mul32Fx4, rm,
13429                              getVSReg( XA ), getVSReg( XB )) );
13430          break;
13431 
13432       case 0x120: // xvsubsp (VSX Vector Subtract Single-Precision)
13433          DIP("xvsubsp v%d,v%d,v%d\n", XT, XA, XB);
13434          // WARNING: BOGUS! The backend ignores rm on Iop_Sub32Fx4
13435          putVSReg( XT, triop(Iop_Sub32Fx4, rm,
13436                              getVSReg( XA ), getVSReg( XB )) );
13437          break;
13438 
13439       case 0x160: // xvdivsp (VSX Vector Divide Single-Precision)
13440       {
13441          /* Iop_Div32Fx4 is not implemented for ppc64 (in host_ppc_{isel|defs}.c.
13442           * So there are two choices:
13443           *   1. Implement the xvdivsp with a native insn; or
13444           *   2. Extract the 4 single precision floats from each vector
13445           *      register inputs and perform fdivs on each pair
13446           * I will do the latter, due to the general philosophy of
13447           * reusing existing implementations when practical.
13448           */
13449          DIP("xvdivsp v%d,v%d,v%d\n", XT, XA, XB);
13450          breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
13451          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
13452 
13453          assign( res0,
13454               unop( Iop_ReinterpF32asI32,
13455                     unop( Iop_TruncF64asF32,
13456                           triop( Iop_DivF64r32, rm, mkexpr( a0 ), mkexpr( b0 ) ) ) ) );
13457          assign( res1,
13458                  unop( Iop_ReinterpF32asI32,
13459                        unop( Iop_TruncF64asF32,
13460                              triop( Iop_DivF64r32, rm, mkexpr( a1 ), mkexpr( b1 ) ) ) ) );
13461          assign( res2,
13462                  unop( Iop_ReinterpF32asI32,
13463                        unop( Iop_TruncF64asF32,
13464                              triop( Iop_DivF64r32, rm, mkexpr( a2 ), mkexpr( b2 ) ) ) ) );
13465          assign( res3,
13466                  unop( Iop_ReinterpF32asI32,
13467                        unop( Iop_TruncF64asF32,
13468                              triop( Iop_DivF64r32, rm, mkexpr( a3 ), mkexpr( b3 ) ) ) ) );
13469 
13470          putVSReg( XT,
13471                    binop( Iop_64HLtoV128,
13472                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
13473                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
13474          break;
13475       }
13476       case 0x116: // xvsqrtsp (VSX Vector Square Root Single-Precision)
13477       {
13478          DIP("xvsqrtsp v%d,v%d\n", XT, XB);
13479          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
13480          /* Note: The native xvsqrtsp insruction does not always give the same precision
13481           * as what we get with Iop_SqrtF64.  But it doesn't seem worthwhile to implement
13482           * an Iop_SqrtF32 that would give us a lower precision result, albeit more true
13483           * to the actual instruction.
13484           */
13485 
13486          assign( res0,
13487                  unop( Iop_ReinterpF32asI32,
13488                        unop( Iop_TruncF64asF32,
13489                              binop(Iop_SqrtF64, rm, mkexpr( b0 ) ) ) ) );
13490          assign( res1,
13491                  unop( Iop_ReinterpF32asI32,
13492                        unop( Iop_TruncF64asF32,
13493                              binop(Iop_SqrtF64, rm, mkexpr( b1 ) ) ) ) );
13494          assign( res2,
13495                  unop( Iop_ReinterpF32asI32,
13496                        unop( Iop_TruncF64asF32,
13497                              binop(Iop_SqrtF64, rm, mkexpr( b2) ) ) ) );
13498          assign( res3,
13499                  unop( Iop_ReinterpF32asI32,
13500                        unop( Iop_TruncF64asF32,
13501                              binop(Iop_SqrtF64, rm, mkexpr( b3 ) ) ) ) );
13502 
13503          putVSReg( XT,
13504                    binop( Iop_64HLtoV128,
13505                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
13506                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
13507          break;
13508       }
13509 
13510       case 0x104: case 0x124: // xvmaddasp, xvmaddmsp (VSX Vector Multiply-Add Single-Precision)
13511       case 0x144: case 0x164: // xvmsubasp, xvmsubmsp (VSX Vector Multiply-Subtract Single-Precision)
13512       case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp (VSX Vector Negate Multiply-Add Single-Precision)
13513       case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp (VSX Vector Negate Multiply-Subtract Single-Precision)
13514       {
13515          IRTemp t3, t2, t1, t0;
13516          Bool msp = False;
13517          Bool negate;
13518          const HChar * oper_name = NULL;
13519          IROp mOp = Iop_INVALID;
13520          switch (opc2) {
13521             case 0x104: case 0x124:
13522             case 0x304: case 0x324:
13523                msp = (opc2 & 0x0FF) == 0x024;
13524                mOp = Iop_MAddF64r32;
13525                oper_name = "madd";
13526                break;
13527 
13528             case 0x144: case 0x164:
13529             case 0x344: case 0x364:
13530                msp = (opc2 & 0x0FF) == 0x064;
13531                mOp = Iop_MSubF64r32;
13532                oper_name = "sub";
13533                break;
13534 
13535             default:
13536                vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
13537          }
13538 
13539          switch (opc2) {
13540             case 0x304: case 0x324:
13541             case 0x344: case 0x364:
13542                negate = True;
13543                break;
13544 
13545             default:
13546                negate = False;
13547          }
13548 
13549          DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name,
13550              msp ? "msp" : "asp", XT, XA, XB);
13551 
13552          t3 = t2 = t1 = t0 = IRTemp_INVALID;
13553          breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
13554          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
13555          breakV128to4xF64( getVSReg( XT ), &t3, &t2, &t1, &t0 );
13556 
13557          assign( res0,
13558                  unop( Iop_ReinterpF32asI32,
13559                        unop( Iop_TruncF64asF32,
13560                              qop( mOp,
13561                                   rm,
13562                                   mkexpr( a0 ),
13563                                   mkexpr( msp ? t0 : b0 ),
13564                                   mkexpr( msp ? b0 : t0 ) ) ) ) );
13565          assign( res1,
13566                  unop( Iop_ReinterpF32asI32,
13567                        unop( Iop_TruncF64asF32,
13568                              qop( mOp,
13569                                   rm,
13570                                   mkexpr( a1 ),
13571                                   mkexpr( msp ? t1 : b1 ),
13572                                   mkexpr( msp ? b1 : t1 ) ) ) ) );
13573          assign( res2,
13574                  unop( Iop_ReinterpF32asI32,
13575                        unop( Iop_TruncF64asF32,
13576                              qop( mOp,
13577                                   rm,
13578                                   mkexpr( a2 ),
13579                                   mkexpr( msp ? t2 : b2 ),
13580                                   mkexpr( msp ? b2 : t2 ) ) ) ) );
13581          assign( res3,
13582                  unop( Iop_ReinterpF32asI32,
13583                        unop( Iop_TruncF64asF32,
13584                              qop( mOp,
13585                                   rm,
13586                                   mkexpr( a3 ),
13587                                   mkexpr( msp ? t3 : b3 ),
13588                                   mkexpr( msp ? b3 : t3 ) ) ) ) );
13589 
13590          putVSReg( XT,
13591                    binop( Iop_64HLtoV128,
13592                           binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res3 ) : res3 ),
13593                                  mkexpr( negate ? getNegatedResult_32( res2 ) : res2 ) ),
13594                           binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res1 ) : res1 ),
13595                                  mkexpr( negate ? getNegatedResult_32( res0 ) : res0 ) ) ) );
13596 
13597          break;
13598       }
13599       case 0x154: // xvtsqrtsp (VSX Vector Test for software Square Root Single-Precision)
13600       {
13601          IRTemp flags0 = newTemp(Ity_I32);
13602          IRTemp flags1 = newTemp(Ity_I32);
13603          IRTemp flags2 = newTemp(Ity_I32);
13604          IRTemp flags3 = newTemp(Ity_I32);
13605          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
13606          IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
13607          IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
13608          fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
13609          fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
13610          DIP("xvtsqrtsp cr%d,v%d\n", crfD, XB);
13611 
13612          breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
13613          do_fp_tsqrt(b0, True /* single precision*/, &fe_flag0, &fg_flag0);
13614          do_fp_tsqrt(b1, True /* single precision*/, &fe_flag1, &fg_flag1);
13615          do_fp_tsqrt(b2, True /* single precision*/, &fe_flag2, &fg_flag2);
13616          do_fp_tsqrt(b3, True /* single precision*/, &fe_flag3, &fg_flag3);
13617 
13618          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
13619           * where fl_flag == 1 on ppc64.
13620           */
13621          assign( flags0,
13622                  binop( Iop_Or32,
13623                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
13624                                binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
13625                         binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
13626          assign( flags1,
13627                  binop( Iop_Or32,
13628                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
13629                                binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
13630                         binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
13631          assign( flags2,
13632                  binop( Iop_Or32,
13633                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
13634                                binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
13635                         binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
13636          assign( flags3,
13637                  binop( Iop_Or32,
13638                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
13639                                binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
13640                         binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
13641          putGST_field( PPC_GST_CR,
13642                        binop( Iop_Or32,
13643                               mkexpr( flags0 ),
13644                               binop( Iop_Or32,
13645                                      mkexpr( flags1 ),
13646                                      binop( Iop_Or32,
13647                                             mkexpr( flags2 ),
13648                                             mkexpr( flags3 ) ) ) ),
13649                        crfD );
13650 
13651          break;
13652       }
13653       case 0x174: // xvtdivsp (VSX Vector Test for software Divide Single-Precision)
13654       {
13655          IRTemp flags0 = newTemp(Ity_I32);
13656          IRTemp flags1 = newTemp(Ity_I32);
13657          IRTemp flags2 = newTemp(Ity_I32);
13658          IRTemp flags3 = newTemp(Ity_I32);
13659          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
13660          IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
13661          IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
13662          fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
13663          fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
13664          DIP("xvtdivsp cr%d,v%d,v%d\n", crfD, XA, XB);
13665 
13666          breakV128to4x32( getVSReg( XA ), &a3, &a2, &a1, &a0 );
13667          breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
13668          _do_fp_tdiv(a0, b0, True /* single precision*/, &fe_flag0, &fg_flag0);
13669          _do_fp_tdiv(a1, b1, True /* single precision*/, &fe_flag1, &fg_flag1);
13670          _do_fp_tdiv(a2, b2, True /* single precision*/, &fe_flag2, &fg_flag2);
13671          _do_fp_tdiv(a3, b3, True /* single precision*/, &fe_flag3, &fg_flag3);
13672 
13673          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
13674           * where fl_flag == 1 on ppc64.
13675           */
13676          assign( flags0,
13677                  binop( Iop_Or32,
13678                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
13679                                binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
13680                         binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
13681          assign( flags1,
13682                  binop( Iop_Or32,
13683                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
13684                                binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
13685                         binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
13686          assign( flags2,
13687                  binop( Iop_Or32,
13688                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
13689                                binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
13690                         binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
13691          assign( flags3,
13692                  binop( Iop_Or32,
13693                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
13694                                binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
13695                         binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
13696          putGST_field( PPC_GST_CR,
13697                        binop( Iop_Or32,
13698                               mkexpr( flags0 ),
13699                               binop( Iop_Or32,
13700                                      mkexpr( flags1 ),
13701                                      binop( Iop_Or32,
13702                                             mkexpr( flags2 ),
13703                                             mkexpr( flags3 ) ) ) ),
13704                        crfD );
13705 
13706          break;
13707       }
13708 
13709       default:
13710          vex_printf( "dis_vxv_sp_arith(ppc)(opc2)\n" );
13711          return False;
13712    }
13713    return True;
13714 }
13715 
13716 /*
13717  * Vector Population Count/bit matrix transpose
13718  */
13719 static Bool
dis_av_count_bitTranspose(UInt theInstr,UInt opc2)13720 dis_av_count_bitTranspose ( UInt theInstr, UInt opc2 )
13721 {
13722    UChar vRB_addr = ifieldRegB(theInstr);
13723    UChar vRT_addr = ifieldRegDS(theInstr);
13724    UChar opc1 = ifieldOPC( theInstr );
13725    IRTemp vB = newTemp(Ity_V128);
13726    assign( vB, getVReg(vRB_addr));
13727 
13728    if (opc1 != 0x4) {
13729       vex_printf( "dis_av_count_bitTranspose(ppc)(instr)\n" );
13730       return False;
13731    }
13732 
13733    switch (opc2) {
13734       case 0x702:    // vclzb
13735          DIP("vclzb v%d,v%d\n", vRT_addr, vRB_addr);
13736          putVReg( vRT_addr, unop(Iop_Clz8x16, mkexpr( vB ) ) );
13737          break;
13738 
13739       case 0x742:    // vclzh
13740          DIP("vclzh v%d,v%d\n", vRT_addr, vRB_addr);
13741          putVReg( vRT_addr, unop(Iop_Clz16x8, mkexpr( vB ) ) );
13742          break;
13743 
13744       case 0x782:    // vclzw
13745          DIP("vclzw v%d,v%d\n", vRT_addr, vRB_addr);
13746          putVReg( vRT_addr, unop(Iop_Clz32x4, mkexpr( vB ) ) );
13747          break;
13748 
13749       case 0x7C2:    // vclzd
13750          DIP("vclzd v%d,v%d\n", vRT_addr, vRB_addr);
13751          putVReg( vRT_addr, unop(Iop_Clz64x2, mkexpr( vB ) ) );
13752          break;
13753 
13754       case 0x703:    // vpopcntb
13755       {
13756          /* Break vector into 32-bit words and do the population count
13757           * on byte in the words
13758           */
13759          IRType ty = Ity_I32;
13760          IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
13761          bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
13762          IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
13763          cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
13764 
13765          DIP("vpopcntb v%d,v%d\n", vRT_addr, vRB_addr);
13766          breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
13767          cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   BYTE);
13768          cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  BYTE);
13769          cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  BYTE);
13770          cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, BYTE);
13771 
13772          putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
13773                                          cnt_bits32_63, cnt_bits0_31) );
13774          break;
13775       }
13776 
13777       case 0x743:    // vpopcnth
13778       {
13779          /* Break vector into 32-bit words and do the population count
13780           * for each half word
13781           */
13782          IRType ty = Ity_I32;
13783          IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
13784          bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
13785          IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
13786          cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
13787 
13788          DIP("vpopcnth v%d,v%d\n", vRT_addr, vRB_addr);
13789          breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
13790 
13791          cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   HWORD);
13792          cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  HWORD);
13793          cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  HWORD);
13794          cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, HWORD);
13795 
13796          putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
13797                                          cnt_bits32_63, cnt_bits0_31) );
13798          break;
13799       }
13800 
13801       case 0x783:    // vpopcntw
13802       {
13803          /* Break vector into 32-bit words and do the population count
13804           * on each word.
13805           */
13806          IRType ty = Ity_I32;
13807          IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
13808          bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
13809          IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
13810          cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
13811 
13812          DIP("vpopcntw v%d,v%d\n", vRT_addr, vRB_addr);
13813          breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
13814 
13815          cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   WORD);
13816          cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  WORD);
13817          cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  WORD);
13818          cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, WORD);
13819 
13820          putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
13821                                          cnt_bits32_63, cnt_bits0_31) );
13822          break;
13823       }
13824 
13825       case 0x7C3:    // vpopcntd
13826       {
13827          if (mode64) {
13828             /* Break vector into 64-bit double words and do the population count
13829              * on each double word.
13830              */
13831             IRType ty = Ity_I64;
13832             IRTemp bits0_63   = newTemp(Ity_I64);
13833             IRTemp bits64_127 = newTemp(Ity_I64);
13834             IRTemp cnt_bits0_63   = newTemp(Ity_I64);
13835             IRTemp cnt_bits64_127 = newTemp(Ity_I64);
13836 
13837             DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr);
13838 
13839             assign(bits0_63,   unop( Iop_V128to64,   mkexpr( vB ) ) );
13840             assign(bits64_127, unop( Iop_V128HIto64, mkexpr( vB ) ) );
13841             cnt_bits0_63   = gen_POPCOUNT(ty, bits0_63,   DWORD);
13842             cnt_bits64_127 = gen_POPCOUNT(ty, bits64_127, DWORD);
13843 
13844             putVReg( vRT_addr, binop( Iop_64HLtoV128,
13845                                       mkexpr( cnt_bits64_127 ),
13846                                       mkexpr( cnt_bits0_63 ) ) );
13847          } else {
13848             /* Break vector into 32-bit words and do the population count
13849              * on each doubleword.
13850              */
13851             IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
13852             bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
13853             IRTemp cnt_bits0_63   = newTemp(Ity_I64);
13854             IRTemp cnt_bits64_127  = newTemp(Ity_I64);
13855 
13856             DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr);
13857             breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
13858 
13859             cnt_bits0_63   = gen_vpopcntd_mode32(bits0_31, bits32_63);
13860             cnt_bits64_127 = gen_vpopcntd_mode32(bits64_95, bits96_127);
13861 
13862             putVReg( vRT_addr, binop( Iop_64HLtoV128,
13863                                       mkexpr( cnt_bits64_127 ),
13864                                       mkexpr( cnt_bits0_63 ) ) );
13865          }
13866          break;
13867       }
13868 
13869       case 0x50C:  // vgbbd Vector Gather Bits by Bytes by Doubleword
13870          DIP("vgbbd v%d,v%d\n", vRT_addr, vRB_addr);
13871          putVReg( vRT_addr, unop( Iop_PwBitMtxXpose64x2, mkexpr( vB ) ) );
13872          break;
13873 
13874       default:
13875          vex_printf("dis_av_count_bitTranspose(ppc)(opc2)\n");
13876          return False;
13877       break;
13878    }
13879    return True;
13880 }
13881 
13882 typedef enum {
13883    PPC_CMP_EQ = 2,
13884    PPC_CMP_GT = 4,
13885    PPC_CMP_GE = 6,
13886    PPC_CMP_LT = 8
13887 } ppc_cmp_t;
13888 
13889 
13890 /*
13891   This helper function takes as input the IRExpr returned
13892   from a binop( Iop_CmpF64, fpA, fpB), whose result is returned
13893   in IR form.  This helper function converts it to PPC form.
13894 
13895   Map compare result from IR to PPC
13896 
13897   FP cmp result | PPC | IR
13898   --------------------------
13899   UN            | 0x1 | 0x45
13900   EQ            | 0x2 | 0x40
13901   GT            | 0x4 | 0x00
13902   LT            | 0x8 | 0x01
13903 
13904  condcode = Shl(1, (~(ccIR>>5) & 2)
13905                     | ((ccIR ^ (ccIR>>6)) & 1)
13906 */
13907 static IRTemp
get_fp_cmp_CR_val(IRExpr * ccIR_expr)13908 get_fp_cmp_CR_val (IRExpr * ccIR_expr)
13909 {
13910    IRTemp condcode = newTemp( Ity_I32 );
13911    IRTemp ccIR = newTemp( Ity_I32 );
13912 
13913    assign(ccIR, ccIR_expr);
13914    assign( condcode,
13915            binop( Iop_Shl32,
13916                   mkU32( 1 ),
13917                   unop( Iop_32to8,
13918                         binop( Iop_Or32,
13919                                binop( Iop_And32,
13920                                       unop( Iop_Not32,
13921                                             binop( Iop_Shr32,
13922                                                    mkexpr( ccIR ),
13923                                                    mkU8( 5 ) ) ),
13924                                       mkU32( 2 ) ),
13925                                binop( Iop_And32,
13926                                       binop( Iop_Xor32,
13927                                              mkexpr( ccIR ),
13928                                              binop( Iop_Shr32,
13929                                                     mkexpr( ccIR ),
13930                                                     mkU8( 6 ) ) ),
13931                                       mkU32( 1 ) ) ) ) ) );
13932    return condcode;
13933 }
13934 
13935 /*
13936  * Helper function for get_max_min_fp for ascertaining the max or min between two doubles
13937  * following these special rules:
13938  *   - The max/min of a QNaN and any value is that value
13939  *     (When two QNaNs are being compared, the frA QNaN is the return value.)
13940  *   - The max/min of any value and an SNaN is that SNaN converted to a QNaN
13941  *     (When two SNaNs are being compared, the frA SNaN is converted to a QNaN.)
13942  */
_get_maxmin_fp_NaN(IRTemp frA_I64,IRTemp frB_I64)13943 static IRExpr * _get_maxmin_fp_NaN(IRTemp frA_I64, IRTemp frB_I64)
13944 {
13945    IRTemp frA_isNaN = newTemp(Ity_I1);
13946    IRTemp frB_isNaN = newTemp(Ity_I1);
13947    IRTemp frA_isSNaN = newTemp(Ity_I1);
13948    IRTemp frB_isSNaN = newTemp(Ity_I1);
13949    IRTemp frA_isQNaN = newTemp(Ity_I1);
13950    IRTemp frB_isQNaN = newTemp(Ity_I1);
13951 
13952    assign( frA_isNaN, is_NaN( frA_I64 ) );
13953    assign( frB_isNaN, is_NaN( frB_I64 ) );
13954    // If operand is a NAN and bit 12 is '0', then it's an SNaN
13955    assign( frA_isSNaN,
13956            mkAND1( mkexpr(frA_isNaN),
13957                    binop( Iop_CmpEQ32,
13958                           binop( Iop_And32,
13959                                  unop( Iop_64HIto32, mkexpr( frA_I64 ) ),
13960                                  mkU32( 0x00080000 ) ),
13961                           mkU32( 0 ) ) ) );
13962    assign( frB_isSNaN,
13963            mkAND1( mkexpr(frB_isNaN),
13964                    binop( Iop_CmpEQ32,
13965                           binop( Iop_And32,
13966                                  unop( Iop_64HIto32, mkexpr( frB_I64 ) ),
13967                                  mkU32( 0x00080000 ) ),
13968                           mkU32( 0 ) ) ) );
13969    assign( frA_isQNaN,
13970            mkAND1( mkexpr( frA_isNaN ), unop( Iop_Not1, mkexpr( frA_isSNaN ) ) ) );
13971    assign( frB_isQNaN,
13972            mkAND1( mkexpr( frB_isNaN ), unop( Iop_Not1, mkexpr( frB_isSNaN ) ) ) );
13973 
13974    /* Based on the rules specified in the function prologue, the algorithm is as follows:
13975     *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
13976     *   if frA is a SNaN
13977     *     result = frA converted to QNaN
13978     *   else if frB is a SNaN
13979     *     result = frB converted to QNaN
13980     *   else if frB is a QNaN
13981     *     result = frA
13982     *   // One of frA or frB was a NaN in order for this function to be called, so
13983     *   // if we get to this point, we KNOW that frA must be a QNaN.
13984     *   else // frA is a QNaN
13985     *     result = frB
13986     *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
13987     */
13988 
13989 #define SNAN_MASK 0x0008000000000000ULL
13990    return
13991    IRExpr_ITE(mkexpr(frA_isSNaN),
13992               /* then: result = frA converted to QNaN */
13993               binop(Iop_Or64, mkexpr(frA_I64), mkU64(SNAN_MASK)),
13994               /* else:  if frB is a SNaN */
13995               IRExpr_ITE(mkexpr(frB_isSNaN),
13996                          /* then: result = frB converted to QNaN */
13997                          binop(Iop_Or64, mkexpr(frB_I64), mkU64(SNAN_MASK)),
13998                          /* else:  if frB is a QNaN */
13999                          IRExpr_ITE(mkexpr(frB_isQNaN),
14000                                     /* then: result = frA */
14001                                     mkexpr(frA_I64),
14002                                     /* else:  frA is a QNaN, so result = frB */
14003                                     mkexpr(frB_I64))));
14004 }
14005 
14006 /*
14007  * Helper function for get_max_min_fp.
14008  */
_get_maxmin_fp_cmp(IRTemp src1,IRTemp src2,Bool isMin)14009 static IRExpr * _get_maxmin_fp_cmp(IRTemp src1, IRTemp src2, Bool isMin)
14010 {
14011    IRTemp src1cmpsrc2 = get_fp_cmp_CR_val( binop( Iop_CmpF64,
14012                                                   unop( Iop_ReinterpI64asF64,
14013                                                         mkexpr( src1 ) ),
14014                                                   unop( Iop_ReinterpI64asF64,
14015                                                         mkexpr( src2 ) ) ) );
14016 
14017    return IRExpr_ITE( binop( Iop_CmpEQ32,
14018                                mkexpr( src1cmpsrc2 ),
14019                                mkU32( isMin ? PPC_CMP_LT : PPC_CMP_GT ) ),
14020                       /* then: use src1 */
14021                       mkexpr( src1 ),
14022                       /* else: use src2 */
14023                       mkexpr( src2 ) );
14024 }
14025 
14026 /*
14027  * Helper function for "Maximum/Minimum Double Precision" operations.
14028  * Arguments: frA and frb are Ity_I64
14029  * Returns Ity_I64 IRExpr that answers the "which is Maxiumum/Minimum" question
14030  */
get_max_min_fp(IRTemp frA_I64,IRTemp frB_I64,Bool isMin)14031 static IRExpr * get_max_min_fp(IRTemp frA_I64, IRTemp frB_I64, Bool isMin)
14032 {
14033    /* There are three special cases where get_fp_cmp_CR_val is not helpful
14034     * for ascertaining the maximum between two doubles:
14035     *   1. The max/min of +0 and -0 is +0.
14036     *   2. The max/min of a QNaN and any value is that value.
14037     *   3. The max/min of any value and an SNaN is that SNaN converted to a QNaN.
14038     * We perform the check for [+/-]0 here in this function and use the
14039     * _get_maxmin_fp_NaN helper for the two NaN cases; otherwise we call _get_maxmin_fp_cmp
14040     * to do the standard comparison function.
14041     */
14042    IRTemp anyNaN = newTemp(Ity_I1);
14043    IRTemp frA_isZero = newTemp(Ity_I1);
14044    IRTemp frB_isZero = newTemp(Ity_I1);
14045    assign(frA_isZero, is_Zero(frA_I64, False /*not single precision*/ ));
14046    assign(frB_isZero, is_Zero(frB_I64, False /*not single precision*/ ));
14047    assign(anyNaN, mkOR1(is_NaN(frA_I64), is_NaN(frB_I64)));
14048 #define MINUS_ZERO 0x8000000000000000ULL
14049 
14050    return IRExpr_ITE( /* If both arguments are zero . . . */
14051                      mkAND1( mkexpr( frA_isZero ), mkexpr( frB_isZero ) ),
14052                      /* then: if frA is -0 and isMin==True, return -0;
14053                       *     else if frA is +0 and isMin==False; return +0;
14054                       *     otherwise, simply return frB. */
14055                      IRExpr_ITE( binop( Iop_CmpEQ32,
14056                                         unop( Iop_64HIto32,
14057                                               mkexpr( frA_I64 ) ),
14058                                         mkU32( isMin ? 0x80000000 : 0 ) ),
14059                                  mkU64( isMin ? MINUS_ZERO : 0ULL ),
14060                                  mkexpr( frB_I64 ) ),
14061                      /* else: check if either input is a NaN*/
14062                      IRExpr_ITE( mkexpr( anyNaN ),
14063                                  /* then: use "NaN helper" */
14064                                  _get_maxmin_fp_NaN( frA_I64, frB_I64 ),
14065                                  /* else: use "comparison helper" */
14066                                  _get_maxmin_fp_cmp( frB_I64, frA_I64, isMin ) ));
14067 }
14068 
_get_vsx_rdpi_suffix(UInt opc2)14069 static const HChar * _get_vsx_rdpi_suffix(UInt opc2)
14070 {
14071    switch (opc2 & 0x7F) {
14072       case 0x72:
14073          return "m";
14074       case 0x52:
14075          return "p";
14076       case 0x56:
14077          return "c";
14078       case 0x32:
14079          return "z";
14080       case 0x12:
14081          return "";
14082 
14083       default: // Impossible to get here
14084          vex_printf("Unrecognized opcode %x\n", opc2);
14085          vpanic("_get_vsx_rdpi_suffix(ppc)(opc2)");
14086    }
14087 }
14088 
14089 /*
14090  * Helper function for vector/scalar double precision fp round to integer instructions.
14091  */
_do_vsx_fp_roundToInt(IRTemp frB_I64,UInt opc2)14092 static IRExpr * _do_vsx_fp_roundToInt(IRTemp frB_I64, UInt opc2)
14093 {
14094 
14095    /* The same rules apply for x{s|v}rdpi{m|p|c|z} as for floating point round operations (fri{m|n|p|z}). */
14096    IRTemp frB = newTemp(Ity_F64);
14097    IRTemp frD = newTemp(Ity_F64);
14098    IRTemp intermediateResult = newTemp(Ity_I64);
14099    IRTemp is_SNAN = newTemp(Ity_I1);
14100    IRExpr * hi32;
14101    IRExpr * rxpi_rm;
14102    switch (opc2 & 0x7F) {
14103       case 0x72:
14104          rxpi_rm = mkU32(Irrm_NegINF);
14105          break;
14106       case 0x52:
14107          rxpi_rm = mkU32(Irrm_PosINF);
14108          break;
14109       case 0x56:
14110          rxpi_rm = get_IR_roundingmode();
14111          break;
14112       case 0x32:
14113          rxpi_rm = mkU32(Irrm_ZERO);
14114          break;
14115       case 0x12:
14116          rxpi_rm = mkU32(Irrm_NEAREST);
14117          break;
14118 
14119       default: // Impossible to get here
14120          vex_printf("Unrecognized opcode %x\n", opc2);
14121          vpanic("_do_vsx_fp_roundToInt(ppc)(opc2)");
14122    }
14123    assign(frB, unop(Iop_ReinterpI64asF64, mkexpr(frB_I64)));
14124    assign( intermediateResult,
14125            binop( Iop_F64toI64S, rxpi_rm,
14126                   mkexpr( frB ) ) );
14127 
14128    /* don't use the rounded integer if frB is outside -9e18..9e18 */
14129    /* F64 has only log10(2**52) significant digits anyway */
14130    /* need to preserve sign of zero */
14131    /*   frD = (fabs(frB) > 9e18) ? frB :
14132             (sign(frB)) ? -fabs((double)intermediateResult) : (double)intermediateResult  */
14133    assign( frD,
14134            IRExpr_ITE(
14135               binop( Iop_CmpNE8,
14136                      unop( Iop_32to8,
14137                            binop( Iop_CmpF64,
14138                                   IRExpr_Const( IRConst_F64( 9e18 ) ),
14139                                   unop( Iop_AbsF64, mkexpr( frB ) ) ) ),
14140                      mkU8(0) ),
14141               mkexpr( frB ),
14142               IRExpr_ITE(
14143                  binop( Iop_CmpNE32,
14144                         binop( Iop_Shr32,
14145                                unop( Iop_64HIto32,
14146                                      mkexpr( frB_I64 ) ),
14147                                mkU8( 31 ) ),
14148                         mkU32(0) ),
14149                  unop( Iop_NegF64,
14150                        unop( Iop_AbsF64,
14151                              binop( Iop_I64StoF64,
14152                                     mkU32( 0 ),
14153                                     mkexpr( intermediateResult ) ) ) ),
14154                  binop( Iop_I64StoF64,
14155                         mkU32( 0 ),
14156                         mkexpr( intermediateResult ) )
14157               )
14158            )
14159    );
14160 
14161    /* See Appendix "Floating-Point Round to Integer Model" in ISA doc.
14162     * If frB is a SNAN, then frD <- frB, with bit 12 set to '1'.
14163     */
14164 #define SNAN_MASK 0x0008000000000000ULL
14165    hi32 = unop( Iop_64HIto32, mkexpr(frB_I64) );
14166    assign( is_SNAN,
14167            mkAND1( is_NaN( frB_I64 ),
14168                    binop( Iop_CmpEQ32,
14169                           binop( Iop_And32, hi32, mkU32( 0x00080000 ) ),
14170                           mkU32( 0 ) ) ) );
14171 
14172    return IRExpr_ITE( mkexpr( is_SNAN ),
14173                         unop( Iop_ReinterpI64asF64,
14174                               binop( Iop_Xor64,
14175                                      mkU64( SNAN_MASK ),
14176                                      mkexpr( frB_I64 ) ) ),
14177                       mkexpr( frD ));
14178 }
14179 
14180 /*
14181  * Miscellaneous VSX vector instructions
14182  */
14183 static Bool
dis_vxv_misc(UInt theInstr,UInt opc2)14184 dis_vxv_misc ( UInt theInstr, UInt opc2 )
14185 {
14186    /* XX3-Form */
14187    UChar opc1 = ifieldOPC( theInstr );
14188    UChar XT = ifieldRegXT( theInstr );
14189    UChar XB = ifieldRegXB( theInstr );
14190 
14191    if (opc1 != 0x3C) {
14192       vex_printf( "dis_vxv_misc(ppc)(instr)\n" );
14193       return False;
14194    }
14195 
14196    switch (opc2) {
14197       case 0x1B4:  // xvredp (VSX Vector Reciprocal Estimate Double-Precision)
14198       case 0x194:  // xvrsqrtedp (VSX Vector Reciprocal Square Root Estimate
14199                    //             Double-Precision)
14200       {
14201          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
14202          IRExpr* rm  = get_IR_roundingmode();
14203          IRTemp frB = newTemp(Ity_I64);
14204          IRTemp frB2 = newTemp(Ity_I64);
14205          Bool redp = opc2 == 0x1B4;
14206          IRTemp sqrtHi = newTemp(Ity_F64);
14207          IRTemp sqrtLo = newTemp(Ity_F64);
14208          assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
14209          assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
14210 
14211          DIP("%s v%d,v%d\n", redp ? "xvredp" : "xvrsqrtedp", XT, XB);
14212          if (!redp) {
14213             assign( sqrtHi,
14214                     binop( Iop_SqrtF64,
14215                            rm,
14216                            unop( Iop_ReinterpI64asF64, mkexpr( frB ) ) ) );
14217             assign( sqrtLo,
14218                     binop( Iop_SqrtF64,
14219                            rm,
14220                            unop( Iop_ReinterpI64asF64, mkexpr( frB2 ) ) ) );
14221          }
14222          putVSReg( XT,
14223                    binop( Iop_64HLtoV128,
14224                           unop( Iop_ReinterpF64asI64,
14225                                 triop( Iop_DivF64,
14226                                        rm,
14227                                        ieee_one,
14228                                        redp ? unop( Iop_ReinterpI64asF64,
14229                                                     mkexpr( frB ) )
14230                                             : mkexpr( sqrtHi ) ) ),
14231                           unop( Iop_ReinterpF64asI64,
14232                                 triop( Iop_DivF64,
14233                                        rm,
14234                                        ieee_one,
14235                                        redp ? unop( Iop_ReinterpI64asF64,
14236                                                     mkexpr( frB2 ) )
14237                                             : mkexpr( sqrtLo ) ) ) ) );
14238          break;
14239 
14240       }
14241       case 0x134: // xvresp (VSX Vector Reciprocal Estimate Single-Precision)
14242       case 0x114: // xvrsqrtesp (VSX Vector Reciprocal Square Root Estimate Single-Precision)
14243       {
14244          IRTemp b3, b2, b1, b0;
14245          IRTemp res0 = newTemp(Ity_I32);
14246          IRTemp res1 = newTemp(Ity_I32);
14247          IRTemp res2 = newTemp(Ity_I32);
14248          IRTemp res3 = newTemp(Ity_I32);
14249          IRTemp sqrt3 = newTemp(Ity_F64);
14250          IRTemp sqrt2 = newTemp(Ity_F64);
14251          IRTemp sqrt1 = newTemp(Ity_F64);
14252          IRTemp sqrt0 = newTemp(Ity_F64);
14253          IRExpr* rm  = get_IR_roundingmode();
14254          Bool resp = opc2 == 0x134;
14255 
14256          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
14257 
14258          b3 = b2 = b1 = b0 = IRTemp_INVALID;
14259          DIP("%s v%d,v%d\n", resp ? "xvresp" : "xvrsqrtesp", XT, XB);
14260          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
14261 
14262          if (!resp) {
14263             assign( sqrt3, binop( Iop_SqrtF64, rm, mkexpr( b3 ) ) );
14264             assign( sqrt2, binop( Iop_SqrtF64, rm, mkexpr( b2 ) ) );
14265             assign( sqrt1, binop( Iop_SqrtF64, rm, mkexpr( b1 ) ) );
14266             assign( sqrt0, binop( Iop_SqrtF64, rm, mkexpr( b0 ) ) );
14267          }
14268 
14269          assign( res0,
14270                  unop( Iop_ReinterpF32asI32,
14271                        unop( Iop_TruncF64asF32,
14272                              triop( Iop_DivF64r32,
14273                                     rm,
14274                                     ieee_one,
14275                                     resp ? mkexpr( b0 ) : mkexpr( sqrt0 ) ) ) ) );
14276          assign( res1,
14277                  unop( Iop_ReinterpF32asI32,
14278                        unop( Iop_TruncF64asF32,
14279                              triop( Iop_DivF64r32,
14280                                     rm,
14281                                     ieee_one,
14282                                     resp ? mkexpr( b1 ) : mkexpr( sqrt1 ) ) ) ) );
14283          assign( res2,
14284                  unop( Iop_ReinterpF32asI32,
14285                        unop( Iop_TruncF64asF32,
14286                              triop( Iop_DivF64r32,
14287                                     rm,
14288                                     ieee_one,
14289                                     resp ? mkexpr( b2 ) : mkexpr( sqrt2 ) ) ) ) );
14290          assign( res3,
14291                  unop( Iop_ReinterpF32asI32,
14292                        unop( Iop_TruncF64asF32,
14293                              triop( Iop_DivF64r32,
14294                                     rm,
14295                                     ieee_one,
14296                                     resp ? mkexpr( b3 ) : mkexpr( sqrt3 ) ) ) ) );
14297          putVSReg( XT,
14298                    binop( Iop_64HLtoV128,
14299                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
14300                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
14301          break;
14302       }
14303       case 0x300: // xvmaxsp (VSX Vector Maximum Single-Precision)
14304       case 0x320: // xvminsp (VSX Vector Minimum Single-Precision)
14305       {
14306          UChar XA = ifieldRegXA( theInstr );
14307          IRTemp a3, a2, a1, a0;
14308          IRTemp b3, b2, b1, b0;
14309          IRTemp res0 = newTemp( Ity_I32 );
14310          IRTemp res1 = newTemp( Ity_I32 );
14311          IRTemp res2 = newTemp( Ity_I32 );
14312          IRTemp res3 = newTemp( Ity_I32 );
14313          IRTemp a0_I64 = newTemp( Ity_I64 );
14314          IRTemp a1_I64 = newTemp( Ity_I64 );
14315          IRTemp a2_I64 = newTemp( Ity_I64 );
14316          IRTemp a3_I64 = newTemp( Ity_I64 );
14317          IRTemp b0_I64 = newTemp( Ity_I64 );
14318          IRTemp b1_I64 = newTemp( Ity_I64 );
14319          IRTemp b2_I64 = newTemp( Ity_I64 );
14320          IRTemp b3_I64 = newTemp( Ity_I64 );
14321 
14322          Bool isMin = opc2 == 0x320 ? True : False;
14323 
14324          a3 = a2 = a1 = a0 = IRTemp_INVALID;
14325          b3 = b2 = b1 = b0 = IRTemp_INVALID;
14326          DIP("%s v%d,v%d v%d\n", isMin ? "xvminsp" : "xvmaxsp", XT, XA, XB);
14327          breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
14328          breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
14329          assign( a0_I64, unop( Iop_ReinterpF64asI64, mkexpr( a0 ) ) );
14330          assign( b0_I64, unop( Iop_ReinterpF64asI64, mkexpr( b0 ) ) );
14331          assign( a1_I64, unop( Iop_ReinterpF64asI64, mkexpr( a1 ) ) );
14332          assign( b1_I64, unop( Iop_ReinterpF64asI64, mkexpr( b1 ) ) );
14333          assign( a2_I64, unop( Iop_ReinterpF64asI64, mkexpr( a2 ) ) );
14334          assign( b2_I64, unop( Iop_ReinterpF64asI64, mkexpr( b2 ) ) );
14335          assign( a3_I64, unop( Iop_ReinterpF64asI64, mkexpr( a3 ) ) );
14336          assign( b3_I64, unop( Iop_ReinterpF64asI64, mkexpr( b3 ) ) );
14337          assign( res0,
14338                  unop( Iop_ReinterpF32asI32,
14339                        unop( Iop_TruncF64asF32,
14340                              unop( Iop_ReinterpI64asF64,
14341                                    get_max_min_fp( a0_I64, b0_I64, isMin ) ) ) ) );
14342          assign( res1,
14343                  unop( Iop_ReinterpF32asI32,
14344                        unop( Iop_TruncF64asF32,
14345                              unop( Iop_ReinterpI64asF64,
14346                                    get_max_min_fp( a1_I64, b1_I64, isMin ) ) ) ) );
14347          assign( res2,
14348                  unop( Iop_ReinterpF32asI32,
14349                        unop( Iop_TruncF64asF32,
14350                              unop( Iop_ReinterpI64asF64,
14351                                    get_max_min_fp( a2_I64, b2_I64, isMin ) ) ) ) );
14352          assign( res3,
14353                  unop( Iop_ReinterpF32asI32,
14354                        unop( Iop_TruncF64asF32,
14355                              unop( Iop_ReinterpI64asF64,
14356                                    get_max_min_fp( a3_I64, b3_I64, isMin ) ) ) ) );
14357          putVSReg( XT,
14358                    binop( Iop_64HLtoV128,
14359                           binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
14360                           binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
14361          break;
14362       }
14363       case 0x380: // xvmaxdp (VSX Vector Maximum Double-Precision)
14364       case 0x3A0: // xvmindp (VSX Vector Minimum Double-Precision)
14365       {
14366          UChar XA = ifieldRegXA( theInstr );
14367          IRTemp frA = newTemp(Ity_I64);
14368          IRTemp frB = newTemp(Ity_I64);
14369          IRTemp frA2 = newTemp(Ity_I64);
14370          IRTemp frB2 = newTemp(Ity_I64);
14371          Bool isMin = opc2 == 0x3A0 ? True : False;
14372 
14373          assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
14374          assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
14375          assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
14376          assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
14377          DIP("%s v%d,v%d v%d\n", isMin ? "xvmindp" : "xvmaxdp", XT, XA, XB);
14378          putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), get_max_min_fp(frA2, frB2, isMin) ) );
14379 
14380          break;
14381       }
14382       case 0x3c0: // xvcpsgndp (VSX Vector Copy Sign Double-Precision)
14383       {
14384          UChar XA = ifieldRegXA( theInstr );
14385          IRTemp frA = newTemp(Ity_I64);
14386          IRTemp frB = newTemp(Ity_I64);
14387          IRTemp frA2 = newTemp(Ity_I64);
14388          IRTemp frB2 = newTemp(Ity_I64);
14389          assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
14390          assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
14391          assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
14392          assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
14393 
14394          DIP("xvcpsgndp v%d,v%d,v%d\n", XT, XA, XB);
14395          putVSReg( XT,
14396                    binop( Iop_64HLtoV128,
14397                           binop( Iop_Or64,
14398                                  binop( Iop_And64,
14399                                         mkexpr( frA ),
14400                                         mkU64( SIGN_BIT ) ),
14401                                  binop( Iop_And64,
14402                                         mkexpr( frB ),
14403                                         mkU64( SIGN_MASK ) ) ),
14404                           binop( Iop_Or64,
14405                                  binop( Iop_And64,
14406                                         mkexpr( frA2 ),
14407                                         mkU64( SIGN_BIT ) ),
14408                                  binop( Iop_And64,
14409                                         mkexpr( frB2 ),
14410                                         mkU64( SIGN_MASK ) ) ) ) );
14411          break;
14412       }
14413       case 0x340: // xvcpsgnsp
14414       {
14415          UChar XA = ifieldRegXA( theInstr );
14416          IRTemp a3_I64, a2_I64, a1_I64, a0_I64;
14417          IRTemp b3_I64, b2_I64, b1_I64, b0_I64;
14418          IRTemp resHi = newTemp(Ity_I64);
14419          IRTemp resLo = newTemp(Ity_I64);
14420 
14421          a3_I64 = a2_I64 = a1_I64 = a0_I64 = IRTemp_INVALID;
14422          b3_I64 = b2_I64 = b1_I64 = b0_I64 = IRTemp_INVALID;
14423          DIP("xvcpsgnsp v%d,v%d v%d\n",XT, XA, XB);
14424          breakV128to4x64U( getVSReg( XA ), &a3_I64, &a2_I64, &a1_I64, &a0_I64 );
14425          breakV128to4x64U( getVSReg( XB ), &b3_I64, &b2_I64, &b1_I64, &b0_I64 );
14426 
14427          assign( resHi,
14428                  binop( Iop_32HLto64,
14429                         binop( Iop_Or32,
14430                                binop( Iop_And32,
14431                                       unop(Iop_64to32, mkexpr( a3_I64 ) ),
14432                                       mkU32( SIGN_BIT32 ) ),
14433                                binop( Iop_And32,
14434                                       unop(Iop_64to32, mkexpr( b3_I64 ) ),
14435                                       mkU32( SIGN_MASK32) ) ),
14436 
14437                         binop( Iop_Or32,
14438                                binop( Iop_And32,
14439                                       unop(Iop_64to32, mkexpr( a2_I64 ) ),
14440                                       mkU32( SIGN_BIT32 ) ),
14441                                binop( Iop_And32,
14442                                       unop(Iop_64to32, mkexpr( b2_I64 ) ),
14443                                       mkU32( SIGN_MASK32 ) ) ) ) );
14444          assign( resLo,
14445                  binop( Iop_32HLto64,
14446                         binop( Iop_Or32,
14447                                binop( Iop_And32,
14448                                       unop(Iop_64to32, mkexpr( a1_I64 ) ),
14449                                       mkU32( SIGN_BIT32 ) ),
14450                                binop( Iop_And32,
14451                                       unop(Iop_64to32, mkexpr( b1_I64 ) ),
14452                                       mkU32( SIGN_MASK32 ) ) ),
14453 
14454                         binop( Iop_Or32,
14455                                binop( Iop_And32,
14456                                       unop(Iop_64to32, mkexpr( a0_I64 ) ),
14457                                       mkU32( SIGN_BIT32 ) ),
14458                                binop( Iop_And32,
14459                                       unop(Iop_64to32, mkexpr( b0_I64 ) ),
14460                                       mkU32( SIGN_MASK32 ) ) ) ) );
14461          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( resHi ), mkexpr( resLo ) ) );
14462          break;
14463       }
14464       case 0x3B2: // xvabsdp (VSX Vector Absolute Value Double-Precision)
14465       case 0x3D2: // xvnabsdp VSX Vector Negative Absolute Value Double-Precision)
14466       {
14467          IRTemp frB = newTemp(Ity_F64);
14468          IRTemp frB2 = newTemp(Ity_F64);
14469          IRTemp abs_resultHi = newTemp(Ity_F64);
14470          IRTemp abs_resultLo = newTemp(Ity_F64);
14471          Bool make_negative = (opc2 == 0x3D2) ? True : False;
14472          assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
14473          assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
14474 
14475          DIP("xv%sabsdp v%d,v%d\n", make_negative ? "n" : "", XT, XB);
14476          if (make_negative) {
14477             assign(abs_resultHi, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB ) ) ) );
14478             assign(abs_resultLo, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB2 ) ) ) );
14479 
14480          } else {
14481             assign(abs_resultHi, unop( Iop_AbsF64, mkexpr( frB ) ) );
14482             assign(abs_resultLo, unop( Iop_AbsF64, mkexpr( frB2 ) ) );
14483          }
14484          putVSReg( XT, binop( Iop_64HLtoV128,
14485                               unop( Iop_ReinterpF64asI64, mkexpr( abs_resultHi ) ),
14486                               unop( Iop_ReinterpF64asI64, mkexpr( abs_resultLo ) ) ) );
14487          break;
14488       }
14489       case 0x332: // xvabssp (VSX Vector Absolute Value Single-Precision)
14490       case 0x352: // xvnabssp (VSX Vector Negative Absolute Value Single-Precision)
14491       {
14492          /*
14493           * The Iop_AbsF32 IRop is not implemented for ppc64 since, up until introduction
14494           * of xvabssp, there has not been an abs(sp) type of instruction.  But since emulation
14495           * of this function is so easy using shifts, I choose to emulate this instruction that
14496           * way versus a native instruction method of implementation.
14497           */
14498          Bool make_negative = (opc2 == 0x352) ? True : False;
14499          IRTemp shiftVector = newTemp(Ity_V128);
14500          IRTemp absVal_vector = newTemp(Ity_V128);
14501          assign( shiftVector,
14502                  binop( Iop_64HLtoV128,
14503                         binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ),
14504                         binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ) ) );
14505          assign( absVal_vector,
14506                    binop( Iop_Shr32x4,
14507                           binop( Iop_Shl32x4,
14508                                  getVSReg( XB ),
14509                                  mkexpr( shiftVector ) ),
14510                           mkexpr( shiftVector ) ) );
14511          if (make_negative) {
14512             IRTemp signBit_vector = newTemp(Ity_V128);
14513             assign( signBit_vector,
14514                     binop( Iop_64HLtoV128,
14515                            binop( Iop_32HLto64,
14516                                   mkU32( 0x80000000 ),
14517                                   mkU32( 0x80000000 ) ),
14518                            binop( Iop_32HLto64,
14519                                   mkU32( 0x80000000 ),
14520                                   mkU32( 0x80000000 ) ) ) );
14521             putVSReg( XT,
14522                       binop( Iop_OrV128,
14523                              mkexpr( absVal_vector ),
14524                              mkexpr( signBit_vector ) ) );
14525          } else {
14526             putVSReg( XT, mkexpr( absVal_vector ) );
14527          }
14528          break;
14529       }
14530       case 0x3F2: // xvnegdp (VSX Vector Negate Double-Precision)
14531       {
14532          IRTemp frB = newTemp(Ity_F64);
14533          IRTemp frB2 = newTemp(Ity_F64);
14534          assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
14535          assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
14536          DIP("xvnegdp v%d,v%d\n",  XT, XB);
14537          putVSReg( XT,
14538                    binop( Iop_64HLtoV128,
14539                           unop( Iop_ReinterpF64asI64,
14540                                 unop( Iop_NegF64, mkexpr( frB ) ) ),
14541                           unop( Iop_ReinterpF64asI64,
14542                                 unop( Iop_NegF64, mkexpr( frB2 ) ) ) ) );
14543          break;
14544       }
14545       case 0x192: // xvrdpi  (VSX Vector Round to Double-Precision Integer using round toward Nearest Away)
14546       case 0x1D6: // xvrdpic (VSX Vector Round to Double-Precision Integer using Current rounding mode)
14547       case 0x1F2: // xvrdpim (VSX Vector Round to Double-Precision Integer using round toward -Infinity)
14548       case 0x1D2: // xvrdpip (VSX Vector Round to Double-Precision Integer using round toward +Infinity)
14549       case 0x1B2: // xvrdpiz (VSX Vector Round to Double-Precision Integer using round toward Zero)
14550       {
14551          IRTemp frBHi_I64 = newTemp(Ity_I64);
14552          IRTemp frBLo_I64 = newTemp(Ity_I64);
14553          IRExpr * frD_fp_roundHi = NULL;
14554          IRExpr * frD_fp_roundLo = NULL;
14555 
14556          assign( frBHi_I64, unop( Iop_V128HIto64, getVSReg( XB ) ) );
14557          frD_fp_roundHi = _do_vsx_fp_roundToInt(frBHi_I64, opc2);
14558          assign( frBLo_I64, unop( Iop_V128to64, getVSReg( XB ) ) );
14559          frD_fp_roundLo = _do_vsx_fp_roundToInt(frBLo_I64, opc2);
14560 
14561          DIP("xvrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), XT, XB);
14562          putVSReg( XT,
14563                    binop( Iop_64HLtoV128,
14564                           unop( Iop_ReinterpF64asI64, frD_fp_roundHi ),
14565                           unop( Iop_ReinterpF64asI64, frD_fp_roundLo ) ) );
14566          break;
14567       }
14568       case 0x112: // xvrspi  (VSX Vector Round to Single-Precision Integer using round toward Nearest Away)
14569       case 0x156: // xvrspic (VSX Vector Round to SinglePrecision Integer using Current rounding mode)
14570       case 0x172: // xvrspim (VSX Vector Round to SinglePrecision Integer using round toward -Infinity)
14571       case 0x152: // xvrspip (VSX Vector Round to SinglePrecision Integer using round toward +Infinity)
14572       case 0x132: // xvrspiz (VSX Vector Round to SinglePrecision Integer using round toward Zero)
14573       {
14574          const HChar * insn_suffix = NULL;
14575          IROp op;
14576          if (opc2 != 0x156) {
14577             // Use pre-defined IRop's for vrfi{m|n|p|z}
14578             switch (opc2) {
14579                case 0x112:
14580                   insn_suffix = "";
14581                   op = Iop_RoundF32x4_RN;
14582                   break;
14583                case 0x172:
14584                   insn_suffix = "m";
14585                   op = Iop_RoundF32x4_RM;
14586                   break;
14587                case 0x152:
14588                   insn_suffix = "p";
14589                   op = Iop_RoundF32x4_RP;
14590                   break;
14591                case 0x132:
14592                   insn_suffix = "z";
14593                   op = Iop_RoundF32x4_RZ;
14594                   break;
14595 
14596                default:
14597                   vex_printf("Unrecognized opcode %x\n", opc2);
14598                   vpanic("dis_vxv_misc(ppc)(vrspi<x>)(opc2)\n");
14599             }
14600             DIP("xvrspi%s v%d,v%d\n", insn_suffix, XT, XB);
14601             putVSReg( XT, unop( op, getVSReg(XB) ) );
14602          } else {
14603             // Handle xvrspic.  Unfortunately there is no corresponding "vfric" instruction.
14604             IRExpr * frD_fp_roundb3, * frD_fp_roundb2, * frD_fp_roundb1, * frD_fp_roundb0;
14605             IRTemp b3_F64, b2_F64, b1_F64, b0_F64;
14606             IRTemp b3_I64 = newTemp(Ity_I64);
14607             IRTemp b2_I64 = newTemp(Ity_I64);
14608             IRTemp b1_I64 = newTemp(Ity_I64);
14609             IRTemp b0_I64 = newTemp(Ity_I64);
14610 
14611             b3_F64 = b2_F64 = b1_F64 = b0_F64 = IRTemp_INVALID;
14612             frD_fp_roundb3 = frD_fp_roundb2 = frD_fp_roundb1 = frD_fp_roundb0 = NULL;
14613             breakV128to4xF64( getVSReg(XB), &b3_F64, &b2_F64, &b1_F64, &b0_F64);
14614             assign(b3_I64, unop(Iop_ReinterpF64asI64, mkexpr(b3_F64)));
14615             assign(b2_I64, unop(Iop_ReinterpF64asI64, mkexpr(b2_F64)));
14616             assign(b1_I64, unop(Iop_ReinterpF64asI64, mkexpr(b1_F64)));
14617             assign(b0_I64, unop(Iop_ReinterpF64asI64, mkexpr(b0_F64)));
14618             frD_fp_roundb3 = unop(Iop_TruncF64asF32,
14619                                   _do_vsx_fp_roundToInt(b3_I64, opc2));
14620             frD_fp_roundb2 = unop(Iop_TruncF64asF32,
14621                                   _do_vsx_fp_roundToInt(b2_I64, opc2));
14622             frD_fp_roundb1 = unop(Iop_TruncF64asF32,
14623                                   _do_vsx_fp_roundToInt(b1_I64, opc2));
14624             frD_fp_roundb0 = unop(Iop_TruncF64asF32,
14625                                   _do_vsx_fp_roundToInt(b0_I64, opc2));
14626             DIP("xvrspic v%d,v%d\n", XT, XB);
14627             putVSReg( XT,
14628                       binop( Iop_64HLtoV128,
14629                              binop( Iop_32HLto64,
14630                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb3 ),
14631                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb2 ) ),
14632                              binop( Iop_32HLto64,
14633                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb1 ),
14634                                     unop( Iop_ReinterpF32asI32, frD_fp_roundb0 ) ) ) );
14635          }
14636          break;
14637       }
14638 
14639       default:
14640          vex_printf( "dis_vxv_misc(ppc)(opc2)\n" );
14641          return False;
14642    }
14643    return True;
14644 }
14645 
14646 
14647 /*
14648  * VSX Scalar Floating Point Arithmetic Instructions
14649  */
14650 static Bool
dis_vxs_arith(UInt theInstr,UInt opc2)14651 dis_vxs_arith ( UInt theInstr, UInt opc2 )
14652 {
14653    /* XX3-Form */
14654    UChar opc1 = ifieldOPC( theInstr );
14655    UChar XT = ifieldRegXT( theInstr );
14656    UChar XA = ifieldRegXA( theInstr );
14657    UChar XB = ifieldRegXB( theInstr );
14658    IRExpr* rm = get_IR_roundingmode();
14659    IRTemp frA = newTemp(Ity_F64);
14660    IRTemp frB = newTemp(Ity_F64);
14661 
14662    if (opc1 != 0x3C) {
14663       vex_printf( "dis_vxs_arith(ppc)(instr)\n" );
14664       return False;
14665    }
14666 
14667    assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
14668    assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
14669 
14670    /* For all the VSX sclar arithmetic instructions, the contents of doubleword element 1
14671     * of VSX[XT] are undefined after the operation; therefore, we can simply set
14672     * element to zero where it makes sense to do so.
14673     */
14674    switch (opc2) {
14675       case 0x000: // xsaddsp  (VSX Scalar Add Single-Precision)
14676          DIP("xsaddsp v%d,v%d,v%d\n", XT, XA, XB);
14677          putVSReg( XT, binop( Iop_64HLtoV128,
14678                               unop( Iop_ReinterpF64asI64,
14679                                     binop( Iop_RoundF64toF32, rm,
14680                                            triop( Iop_AddF64, rm,
14681                                                   mkexpr( frA ),
14682                                                   mkexpr( frB ) ) ) ),
14683                               mkU64( 0 ) ) );
14684          break;
14685       case 0x020: // xssubsp  (VSX Scalar Subtract Single-Precision)
14686          DIP("xssubsp v%d,v%d,v%d\n", XT, XA, XB);
14687          putVSReg( XT, binop( Iop_64HLtoV128,
14688                               unop( Iop_ReinterpF64asI64,
14689                                     binop( Iop_RoundF64toF32, rm,
14690                                            triop( Iop_SubF64, rm,
14691                                                   mkexpr( frA ),
14692                                                   mkexpr( frB ) ) ) ),
14693                               mkU64( 0 ) ) );
14694          break;
14695       case 0x080: // xsadddp (VSX scalar add double-precision)
14696          DIP("xsadddp v%d,v%d,v%d\n", XT, XA, XB);
14697          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
14698                                                     triop( Iop_AddF64, rm,
14699                                                            mkexpr( frA ),
14700                                                            mkexpr( frB ) ) ),
14701                               mkU64( 0 ) ) );
14702          break;
14703       case 0x060: // xsdivsp (VSX scalar divide single-precision)
14704          DIP("xsdivsp v%d,v%d,v%d\n", XT, XA, XB);
14705          putVSReg( XT, binop( Iop_64HLtoV128,
14706                               unop( Iop_ReinterpF64asI64,
14707                                     binop( Iop_RoundF64toF32, rm,
14708                                            triop( Iop_DivF64, rm,
14709                                                   mkexpr( frA ),
14710                                                   mkexpr( frB ) ) ) ),
14711                                mkU64( 0 ) ) );
14712          break;
14713       case 0x0E0: // xsdivdp (VSX scalar divide double-precision)
14714          DIP("xsdivdp v%d,v%d,v%d\n", XT, XA, XB);
14715          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
14716                                                     triop( Iop_DivF64, rm,
14717                                                            mkexpr( frA ),
14718                                                            mkexpr( frB ) ) ),
14719                               mkU64( 0 ) ) );
14720          break;
14721       case 0x004: case 0x024: /* xsmaddasp, xsmaddmsp (VSX scalar multiply-add
14722                                * single-precision)
14723                                */
14724       {
14725          IRTemp frT = newTemp(Ity_F64);
14726          Bool mdp = opc2 == 0x024;
14727          DIP("xsmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
14728          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14729                                                         getVSReg( XT ) ) ) );
14730          putVSReg( XT,
14731                    binop( Iop_64HLtoV128,
14732                           unop( Iop_ReinterpF64asI64,
14733                                 binop( Iop_RoundF64toF32, rm,
14734                                        qop( Iop_MAddF64, rm,
14735                                             mkexpr( frA ),
14736                                             mkexpr( mdp ? frT : frB ),
14737                                             mkexpr( mdp ? frB : frT ) ) ) ),
14738                           mkU64( 0 ) ) );
14739          break;
14740       }
14741       case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp (VSX scalar multiply-add double-precision)
14742       {
14743          IRTemp frT = newTemp(Ity_F64);
14744          Bool mdp = opc2 == 0x0A4;
14745          DIP("xsmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
14746          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14747                                                         getVSReg( XT ) ) ) );
14748          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
14749                                                     qop( Iop_MAddF64, rm,
14750                                                          mkexpr( frA ),
14751                                                          mkexpr( mdp ? frT : frB ),
14752                                                          mkexpr( mdp ? frB : frT ) ) ),
14753                               mkU64( 0 ) ) );
14754          break;
14755       }
14756       case 0x044: case 0x064: /* xsmsubasp, xsmsubmsp (VSX scalar
14757                                * multiply-subtract single-precision)
14758 			       */
14759       {
14760          IRTemp frT = newTemp(Ity_F64);
14761          Bool mdp = opc2 == 0x064;
14762          DIP("xsmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
14763          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14764                                                         getVSReg( XT ) ) ) );
14765          putVSReg( XT,
14766                    binop( Iop_64HLtoV128,
14767                           unop( Iop_ReinterpF64asI64,
14768                                 binop( Iop_RoundF64toF32, rm,
14769                                        qop( Iop_MSubF64, rm,
14770                                             mkexpr( frA ),
14771                                             mkexpr( mdp ? frT : frB ),
14772                                             mkexpr( mdp ? frB : frT ) ) ) ),
14773                           mkU64( 0 ) ) );
14774          break;
14775       }
14776       case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp (VSX scalar multiply-subtract double-precision)
14777       {
14778          IRTemp frT = newTemp(Ity_F64);
14779          Bool mdp = opc2 == 0x0E4;
14780          DIP("xsmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
14781          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14782                                                         getVSReg( XT ) ) ) );
14783          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
14784                                                     qop( Iop_MSubF64, rm,
14785                                                          mkexpr( frA ),
14786                                                          mkexpr( mdp ? frT : frB ),
14787                                                          mkexpr( mdp ? frB : frT ) ) ),
14788                               mkU64( 0 ) ) );
14789          break;
14790       }
14791       case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp (VSX scalar multiply-add double-precision)
14792       {
14793          /* TODO: mpj -- Naturally, I expected to be able to leverage the implementation
14794           * of fnmadd and use pretty much the same code. However, that code has a bug in the
14795           * way it blindly negates the signbit, even if the floating point result is a NaN.
14796           * So, the TODO is to fix fnmadd (which I'll do in a different patch).
14797           * FIXED 7/1/2012: carll fnmadd and fnmsubs fixed to not negate sign
14798           * bit for NaN result.
14799           */
14800          Bool mdp = opc2 == 0x2A4;
14801          IRTemp frT = newTemp(Ity_F64);
14802          IRTemp maddResult = newTemp(Ity_I64);
14803 
14804          DIP("xsnmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
14805          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14806                                                         getVSReg( XT ) ) ) );
14807          assign( maddResult, unop( Iop_ReinterpF64asI64, qop( Iop_MAddF64, rm,
14808                                                               mkexpr( frA ),
14809                                                               mkexpr( mdp ? frT : frB ),
14810                                                               mkexpr( mdp ? frB : frT ) ) ) );
14811 
14812          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(maddResult) ),
14813                               mkU64( 0 ) ) );
14814          break;
14815       }
14816       case 0x204: case 0x224: /* xsnmaddasp, xsnmaddmsp (VSX scalar
14817                                * multiply-add single-precision)
14818                                */
14819       {
14820          Bool mdp = opc2 == 0x224;
14821          IRTemp frT = newTemp(Ity_F64);
14822          IRTemp maddResult = newTemp(Ity_I64);
14823 
14824          DIP("xsnmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
14825          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14826                                                         getVSReg( XT ) ) ) );
14827          assign( maddResult,
14828                  unop( Iop_ReinterpF64asI64,
14829                        binop( Iop_RoundF64toF32, rm,
14830                               qop( Iop_MAddF64, rm,
14831                                    mkexpr( frA ),
14832                                    mkexpr( mdp ? frT : frB ),
14833                                    mkexpr( mdp ? frB : frT ) ) ) ) );
14834 
14835          putVSReg( XT, binop( Iop_64HLtoV128,
14836                               mkexpr( getNegatedResult(maddResult) ),
14837                               mkU64( 0 ) ) );
14838          break;
14839       }
14840       case 0x244: case 0x264: /* xsnmsubasp, xsnmsubmsp (VSX Scalar Negative
14841                                * Multiply-Subtract Single-Precision)
14842                                */
14843       {
14844          IRTemp frT = newTemp(Ity_F64);
14845          Bool mdp = opc2 == 0x264;
14846          IRTemp msubResult = newTemp(Ity_I64);
14847 
14848          DIP("xsnmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
14849          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14850                                                         getVSReg( XT ) ) ) );
14851          assign( msubResult,
14852                  unop( Iop_ReinterpF64asI64,
14853                        binop( Iop_RoundF64toF32, rm,
14854                               qop( Iop_MSubF64, rm,
14855                                    mkexpr( frA ),
14856                                    mkexpr( mdp ? frT : frB ),
14857                                    mkexpr( mdp ? frB : frT ) ) ) ) );
14858 
14859          putVSReg( XT, binop( Iop_64HLtoV128,
14860                               mkexpr( getNegatedResult(msubResult) ),
14861                               mkU64( 0 ) ) );
14862 
14863          break;
14864       }
14865 
14866       case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp (VSX Scalar Negative Multiply-Subtract Double-Precision)
14867       {
14868          IRTemp frT = newTemp(Ity_F64);
14869          Bool mdp = opc2 == 0x2E4;
14870          IRTemp msubResult = newTemp(Ity_I64);
14871 
14872          DIP("xsnmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
14873          assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
14874                                                         getVSReg( XT ) ) ) );
14875          assign(msubResult, unop( Iop_ReinterpF64asI64,
14876                                       qop( Iop_MSubF64,
14877                                            rm,
14878                                            mkexpr( frA ),
14879                                            mkexpr( mdp ? frT : frB ),
14880                                            mkexpr( mdp ? frB : frT ) ) ));
14881 
14882          putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(msubResult) ), mkU64( 0 ) ) );
14883 
14884          break;
14885       }
14886 
14887       case 0x040: // xsmulsp (VSX Scalar Multiply Single-Precision)
14888          DIP("xsmulsp v%d,v%d,v%d\n", XT, XA, XB);
14889          putVSReg( XT, binop( Iop_64HLtoV128,
14890                               unop( Iop_ReinterpF64asI64,
14891                                     binop( Iop_RoundF64toF32, rm,
14892                                            triop( Iop_MulF64, rm,
14893                                                    mkexpr( frA ),
14894                                                    mkexpr( frB ) ) ) ),
14895                               mkU64( 0 ) ) );
14896          break;
14897 
14898       case 0x0C0: // xsmuldp (VSX Scalar Multiply Double-Precision)
14899          DIP("xsmuldp v%d,v%d,v%d\n", XT, XA, XB);
14900          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
14901                                                     triop( Iop_MulF64, rm,
14902                                                            mkexpr( frA ),
14903                                                            mkexpr( frB ) ) ),
14904                               mkU64( 0 ) ) );
14905          break;
14906       case 0x0A0: // xssubdp (VSX Scalar Subtract Double-Precision)
14907          DIP("xssubdp v%d,v%d,v%d\n", XT, XA, XB);
14908          putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
14909                                                     triop( Iop_SubF64, rm,
14910                                                            mkexpr( frA ),
14911                                                            mkexpr( frB ) ) ),
14912                               mkU64( 0 ) ) );
14913          break;
14914 
14915       case 0x016: // xssqrtsp (VSX Scalar Square Root Single-Precision)
14916          DIP("xssqrtsp v%d,v%d\n", XT, XB);
14917          putVSReg( XT,
14918                    binop( Iop_64HLtoV128,
14919                           unop( Iop_ReinterpF64asI64,
14920                                 binop( Iop_RoundF64toF32, rm,
14921                                        binop( Iop_SqrtF64, rm,
14922                                               mkexpr( frB ) ) ) ),
14923                           mkU64( 0 ) ) );
14924          break;
14925 
14926       case 0x096: // xssqrtdp (VSX Scalar Square Root Double-Precision)
14927          DIP("xssqrtdp v%d,v%d\n", XT, XB);
14928          putVSReg( XT,  binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
14929                                                      binop( Iop_SqrtF64, rm,
14930                                                             mkexpr( frB ) ) ),
14931                                mkU64( 0 ) ) );
14932          break;
14933 
14934       case 0x0F4: // xstdivdp (VSX Scalar Test for software Divide Double-Precision)
14935       {
14936          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
14937          IRTemp frA_I64 = newTemp(Ity_I64);
14938          IRTemp frB_I64 = newTemp(Ity_I64);
14939          DIP("xstdivdp crf%d,v%d,v%d\n", crfD, XA, XB);
14940          assign( frA_I64, unop( Iop_ReinterpF64asI64, mkexpr( frA ) ) );
14941          assign( frB_I64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
14942          putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
14943          break;
14944       }
14945       case 0x0D4: // xstsqrtdp (VSX Vector Test for software Square Root Double-Precision)
14946       {
14947          IRTemp frB_I64 = newTemp(Ity_I64);
14948          UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
14949          IRTemp flags = newTemp(Ity_I32);
14950          IRTemp  fe_flag, fg_flag;
14951          fe_flag = fg_flag = IRTemp_INVALID;
14952          DIP("xstsqrtdp v%d,v%d\n", XT, XB);
14953          assign( frB_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
14954          do_fp_tsqrt(frB_I64, False /*not single precision*/, &fe_flag, &fg_flag);
14955          /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
14956           * where fl_flag == 1 on ppc64.
14957           */
14958          assign( flags,
14959                  binop( Iop_Or32,
14960                         binop( Iop_Or32, mkU32( 8 ), // fl_flag
14961                                binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
14962                         binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
14963          putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
14964          break;
14965       }
14966 
14967       default:
14968          vex_printf( "dis_vxs_arith(ppc)(opc2)\n" );
14969          return False;
14970    }
14971 
14972    return True;
14973 }
14974 
14975 
14976 /*
14977  * VSX Floating Point Compare Instructions
14978  */
14979 static Bool
dis_vx_cmp(UInt theInstr,UInt opc2)14980 dis_vx_cmp( UInt theInstr, UInt opc2 )
14981 {
14982    /* XX3-Form and XX2-Form */
14983    UChar opc1 = ifieldOPC( theInstr );
14984    UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
14985    IRTemp ccPPC32;
14986    UChar XA       = ifieldRegXA ( theInstr );
14987    UChar XB       = ifieldRegXB ( theInstr );
14988    IRTemp frA     = newTemp(Ity_F64);
14989    IRTemp frB     = newTemp(Ity_F64);
14990 
14991    if (opc1 != 0x3C) {
14992       vex_printf( "dis_vx_cmp(ppc)(instr)\n" );
14993       return False;
14994    }
14995 
14996    assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
14997    assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
14998    switch (opc2) {
14999       case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
15000          /* Note: Differences between xscmpudp and xscmpodp are only in
15001           * exception flag settings, which aren't supported anyway. */
15002          DIP("xscmp%sdp crf%d,fr%u,fr%u\n", opc2 == 0x08c ? "u" : "o",
15003                                            crfD, XA, XB);
15004          ccPPC32 = get_fp_cmp_CR_val( binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)));
15005          putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
15006          break;
15007 
15008       default:
15009          vex_printf( "dis_vx_cmp(ppc)(opc2)\n" );
15010          return False;
15011    }
15012    return True;
15013 }
15014 
15015 static void
do_vvec_fp_cmp(IRTemp vA,IRTemp vB,UChar XT,UChar flag_rC,ppc_cmp_t cmp_type)15016 do_vvec_fp_cmp ( IRTemp vA, IRTemp vB, UChar XT, UChar flag_rC,
15017                  ppc_cmp_t cmp_type )
15018 {
15019    IRTemp frA_hi     = newTemp(Ity_F64);
15020    IRTemp frB_hi     = newTemp(Ity_F64);
15021    IRTemp frA_lo     = newTemp(Ity_F64);
15022    IRTemp frB_lo     = newTemp(Ity_F64);
15023    IRTemp ccPPC32    = newTemp(Ity_I32);
15024    IRTemp ccIR_hi;
15025    IRTemp ccIR_lo;
15026 
15027    IRTemp hiResult = newTemp(Ity_I64);
15028    IRTemp loResult = newTemp(Ity_I64);
15029    IRTemp hiEQlo = newTemp(Ity_I1);
15030    IRTemp all_elem_true = newTemp(Ity_I32);
15031    IRTemp all_elem_false = newTemp(Ity_I32);
15032 
15033    assign(frA_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vA ))));
15034    assign(frB_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vB ))));
15035    assign(frA_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vA ))));
15036    assign(frB_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vB ))));
15037 
15038    ccIR_hi = get_fp_cmp_CR_val( binop( Iop_CmpF64,
15039                                        mkexpr( frA_hi ),
15040                                        mkexpr( frB_hi ) ) );
15041    ccIR_lo = get_fp_cmp_CR_val( binop( Iop_CmpF64,
15042                                        mkexpr( frA_lo ),
15043                                        mkexpr( frB_lo ) ) );
15044 
15045    if (cmp_type != PPC_CMP_GE) {
15046       assign( hiResult,
15047               unop( Iop_1Sto64,
15048                     binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( cmp_type ) ) ) );
15049       assign( loResult,
15050               unop( Iop_1Sto64,
15051                     binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( cmp_type ) ) ) );
15052    } else {
15053       // For PPC_CMP_GE, one element compare may return "4" (for "greater than") and
15054       // the other element compare may return "2" (for "equal to").
15055       IRTemp lo_GE = newTemp(Ity_I1);
15056       IRTemp hi_GE = newTemp(Ity_I1);
15057 
15058       assign(hi_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 2 ) ),
15059                            binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 4 ) ) ) );
15060       assign( hiResult,unop( Iop_1Sto64, mkexpr( hi_GE ) ) );
15061 
15062       assign(lo_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 2 ) ),
15063                            binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 4 ) ) ) );
15064       assign( loResult, unop( Iop_1Sto64, mkexpr( lo_GE ) ) );
15065    }
15066 
15067    // The [hi/lo]Result will be all 1's or all 0's.  We just look at the lower word.
15068    assign( hiEQlo,
15069            binop( Iop_CmpEQ32,
15070                   unop( Iop_64to32, mkexpr( hiResult ) ),
15071                   unop( Iop_64to32, mkexpr( loResult ) ) ) );
15072    putVSReg( XT,
15073              binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
15074 
15075    assign( all_elem_true,
15076            unop( Iop_1Uto32,
15077                  mkAND1( mkexpr( hiEQlo ),
15078                          binop( Iop_CmpEQ32,
15079                                 mkU32( 0xffffffff ),
15080                                 unop( Iop_64to32,
15081                                 mkexpr( hiResult ) ) ) ) ) );
15082 
15083    assign( all_elem_false,
15084            unop( Iop_1Uto32,
15085                  mkAND1( mkexpr( hiEQlo ),
15086                          binop( Iop_CmpEQ32,
15087                                 mkU32( 0 ),
15088                                 unop( Iop_64to32,
15089                                 mkexpr( hiResult ) ) ) ) ) );
15090    assign( ccPPC32,
15091            binop( Iop_Or32,
15092                   binop( Iop_Shl32, mkexpr( all_elem_false ), mkU8( 1 ) ),
15093                   binop( Iop_Shl32, mkexpr( all_elem_true ), mkU8( 3 ) ) ) );
15094 
15095    if (flag_rC) {
15096       putGST_field( PPC_GST_CR, mkexpr(ccPPC32), 6 );
15097    }
15098 }
15099 
15100 /*
15101  * VSX Vector Compare Instructions
15102  */
15103 static Bool
dis_vvec_cmp(UInt theInstr,UInt opc2)15104 dis_vvec_cmp( UInt theInstr, UInt opc2 )
15105 {
15106    /* XX3-Form */
15107    UChar opc1 = ifieldOPC( theInstr );
15108    UChar XT = ifieldRegXT ( theInstr );
15109    UChar XA = ifieldRegXA ( theInstr );
15110    UChar XB = ifieldRegXB ( theInstr );
15111    UChar flag_rC  = ifieldBIT10(theInstr);
15112    IRTemp vA = newTemp( Ity_V128 );
15113    IRTemp vB = newTemp( Ity_V128 );
15114 
15115    if (opc1 != 0x3C) {
15116       vex_printf( "dis_vvec_cmp(ppc)(instr)\n" );
15117       return False;
15118    }
15119 
15120    assign( vA, getVSReg( XA ) );
15121    assign( vB, getVSReg( XB ) );
15122 
15123    switch (opc2) {
15124       case 0x18C: case 0x38C:  // xvcmpeqdp[.] (VSX Vector Compare Equal To Double-Precision [ & Record ])
15125       {
15126          DIP("xvcmpeqdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
15127              XT, XA, XB);
15128          do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_EQ);
15129          break;
15130       }
15131 
15132       case 0x1CC: case 0x3CC: // xvcmpgedp[.] (VSX Vector Compare Greater Than or Equal To Double-Precision [ & Record ])
15133       {
15134          DIP("xvcmpgedp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
15135              XT, XA, XB);
15136          do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GE);
15137          break;
15138       }
15139 
15140       case 0x1AC: case 0x3AC: // xvcmpgtdp[.] (VSX Vector Compare Greater Than Double-Precision [ & Record ])
15141       {
15142          DIP("xvcmpgtdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
15143              XT, XA, XB);
15144          do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GT);
15145          break;
15146       }
15147 
15148       case 0x10C: case 0x30C: // xvcmpeqsp[.] (VSX Vector Compare Equal To Single-Precision [ & Record ])
15149       {
15150          IRTemp vD = newTemp(Ity_V128);
15151 
15152          DIP("xvcmpeqsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
15153              XT, XA, XB);
15154          assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
15155          putVSReg( XT, mkexpr(vD) );
15156          if (flag_rC) {
15157             set_AV_CR6( mkexpr(vD), True );
15158          }
15159          break;
15160       }
15161 
15162       case 0x14C: case 0x34C: // xvcmpgesp[.] (VSX Vector Compare Greater Than or Equal To Single-Precision [ & Record ])
15163       {
15164          IRTemp vD = newTemp(Ity_V128);
15165 
15166          DIP("xvcmpgesp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
15167              XT, XA, XB);
15168          assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
15169          putVSReg( XT, mkexpr(vD) );
15170          if (flag_rC) {
15171             set_AV_CR6( mkexpr(vD), True );
15172          }
15173          break;
15174       }
15175 
15176       case 0x12C: case 0x32C: //xvcmpgtsp[.] (VSX Vector Compare Greater Than Single-Precision [ & Record ])
15177       {
15178          IRTemp vD = newTemp(Ity_V128);
15179 
15180          DIP("xvcmpgtsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
15181              XT, XA, XB);
15182          assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
15183          putVSReg( XT, mkexpr(vD) );
15184          if (flag_rC) {
15185             set_AV_CR6( mkexpr(vD), True );
15186          }
15187          break;
15188       }
15189 
15190       default:
15191          vex_printf( "dis_vvec_cmp(ppc)(opc2)\n" );
15192          return False;
15193    }
15194    return True;
15195 }
15196 /*
15197  * Miscellaneous VSX Scalar Instructions
15198  */
15199 static Bool
dis_vxs_misc(UInt theInstr,UInt opc2)15200 dis_vxs_misc( UInt theInstr, UInt opc2 )
15201 {
15202 #define VG_PPC_SIGN_MASK 0x7fffffffffffffffULL
15203    /* XX3-Form and XX2-Form */
15204    UChar opc1 = ifieldOPC( theInstr );
15205    UChar XT = ifieldRegXT ( theInstr );
15206    UChar XA = ifieldRegXA ( theInstr );
15207    UChar XB = ifieldRegXB ( theInstr );
15208    IRTemp vA = newTemp( Ity_V128 );
15209    IRTemp vB = newTemp( Ity_V128 );
15210 
15211    if (opc1 != 0x3C) {
15212       vex_printf( "dis_vxs_misc(ppc)(instr)\n" );
15213       return False;
15214    }
15215 
15216    assign( vA, getVSReg( XA ) );
15217    assign( vB, getVSReg( XB ) );
15218 
15219    /* For all the VSX move instructions, the contents of doubleword element 1
15220     * of VSX[XT] are undefined after the operation; therefore, we can simply
15221     * move the entire array element where it makes sense to do so.
15222     */
15223 
15224    switch (opc2) {
15225       case 0x2B2: // xsabsdp (VSX scalar absolute value double-precision
15226       {
15227          /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */
15228          IRTemp absVal = newTemp(Ity_V128);
15229          if (host_endness == VexEndnessLE) {
15230             IRTemp hi64 = newTemp(Ity_I64);
15231             IRTemp lo64 = newTemp(Ity_I64);
15232             assign( hi64, unop( Iop_V128HIto64, mkexpr(vB) ) );
15233             assign( lo64, unop( Iop_V128to64, mkexpr(vB) ) );
15234             assign( absVal, binop( Iop_64HLtoV128,
15235                                    binop( Iop_And64, mkexpr(hi64),
15236                                           mkU64(VG_PPC_SIGN_MASK) ),
15237                                    mkexpr(lo64) ) );
15238          } else {
15239             assign(absVal, binop(Iop_ShrV128,
15240                                  binop(Iop_ShlV128, mkexpr(vB),
15241                                        mkU8(1)), mkU8(1)));
15242          }
15243          DIP("xsabsdp v%d,v%d\n", XT, XB);
15244          putVSReg(XT, mkexpr(absVal));
15245          break;
15246       }
15247       case 0x2C0: // xscpsgndp
15248       {
15249          /* Scalar copy sign double-precision */
15250          IRTemp vecA_signed = newTemp(Ity_I64);
15251          IRTemp vecB_unsigned = newTemp(Ity_I64);
15252          IRTemp vec_result = newTemp(Ity_V128);
15253          DIP("xscpsgndp v%d,v%d v%d\n", XT, XA, XB);
15254          assign( vecA_signed, binop( Iop_And64,
15255                                      unop( Iop_V128HIto64,
15256                                            mkexpr(vA)),
15257                                            mkU64(~VG_PPC_SIGN_MASK) ) );
15258          assign( vecB_unsigned, binop( Iop_And64,
15259                                        unop( Iop_V128HIto64,
15260                                              mkexpr(vB) ),
15261                                              mkU64(VG_PPC_SIGN_MASK) ) );
15262          assign( vec_result, binop( Iop_64HLtoV128,
15263                                     binop( Iop_Or64,
15264                                            mkexpr(vecA_signed),
15265                                            mkexpr(vecB_unsigned) ),
15266                                     mkU64(0x0ULL)));
15267          putVSReg(XT, mkexpr(vec_result));
15268          break;
15269       }
15270       case 0x2D2: // xsnabsdp
15271       {
15272          /* Scalar negative absolute value double-precision */
15273          IRTemp BHi_signed = newTemp(Ity_I64);
15274          DIP("xsnabsdp v%d,v%d\n", XT, XB);
15275          assign( BHi_signed, binop( Iop_Or64,
15276                                     unop( Iop_V128HIto64,
15277                                           mkexpr(vB) ),
15278                                           mkU64(~VG_PPC_SIGN_MASK) ) );
15279          putVSReg(XT, binop( Iop_64HLtoV128,
15280                              mkexpr(BHi_signed), mkU64(0x0ULL) ) );
15281          break;
15282       }
15283       case 0x2F2: // xsnegdp
15284       {
15285          /* Scalar negate double-precision */
15286          IRTemp BHi_signed = newTemp(Ity_I64);
15287          IRTemp BHi_unsigned = newTemp(Ity_I64);
15288          IRTemp BHi_negated = newTemp(Ity_I64);
15289          IRTemp BHi_negated_signbit = newTemp(Ity_I1);
15290          IRTemp vec_result = newTemp(Ity_V128);
15291          DIP("xsnabsdp v%d,v%d\n", XT, XB);
15292          assign( BHi_signed, unop( Iop_V128HIto64, mkexpr(vB) ) );
15293          assign( BHi_unsigned, binop( Iop_And64, mkexpr(BHi_signed),
15294                                       mkU64(VG_PPC_SIGN_MASK) ) );
15295          assign( BHi_negated_signbit,
15296                  unop( Iop_Not1,
15297                        unop( Iop_32to1,
15298                              binop( Iop_Shr32,
15299                                     unop( Iop_64HIto32,
15300                                           binop( Iop_And64,
15301                                                  mkexpr(BHi_signed),
15302                                                  mkU64(~VG_PPC_SIGN_MASK) )
15303                                           ),
15304                                     mkU8(31) ) ) ) );
15305          assign( BHi_negated,
15306                  binop( Iop_Or64,
15307                         binop( Iop_32HLto64,
15308                                binop( Iop_Shl32,
15309                                       unop( Iop_1Uto32,
15310                                             mkexpr(BHi_negated_signbit) ),
15311                                       mkU8(31) ),
15312                                mkU32(0) ),
15313                         mkexpr(BHi_unsigned) ) );
15314          assign( vec_result, binop( Iop_64HLtoV128, mkexpr(BHi_negated),
15315                                     mkU64(0x0ULL)));
15316          putVSReg( XT, mkexpr(vec_result));
15317          break;
15318       }
15319       case 0x280: // xsmaxdp (VSX Scalar Maximum Double-Precision)
15320       case 0x2A0: // xsmindp (VSX Scalar Minimum Double-Precision)
15321       {
15322          IRTemp frA     = newTemp(Ity_I64);
15323          IRTemp frB     = newTemp(Ity_I64);
15324          Bool isMin = opc2 == 0x2A0 ? True : False;
15325          DIP("%s v%d,v%d v%d\n", isMin ? "xsmaxdp" : "xsmindp", XT, XA, XB);
15326 
15327          assign(frA, unop(Iop_V128HIto64, mkexpr( vA )));
15328          assign(frB, unop(Iop_V128HIto64, mkexpr( vB )));
15329          putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), mkU64( 0 ) ) );
15330 
15331          break;
15332       }
15333       case 0x0F2: // xsrdpim (VSX Scalar Round to Double-Precision Integer using round toward -Infinity)
15334       case 0x0D2: // xsrdpip (VSX Scalar Round to Double-Precision Integer using round toward +Infinity)
15335       case 0x0D6: // xsrdpic (VSX Scalar Round to Double-Precision Integer using Current rounding mode)
15336       case 0x0B2: // xsrdpiz (VSX Scalar Round to Double-Precision Integer using round toward Zero)
15337       case 0x092: // xsrdpi  (VSX Scalar Round to Double-Precision Integer using round toward Nearest Away)
15338       {
15339          IRTemp frB_I64 = newTemp(Ity_I64);
15340          IRExpr * frD_fp_round = NULL;
15341 
15342          assign(frB_I64, unop(Iop_V128HIto64, mkexpr( vB )));
15343          frD_fp_round = _do_vsx_fp_roundToInt(frB_I64, opc2);
15344 
15345          DIP("xsrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), XT, XB);
15346          putVSReg( XT,
15347                    binop( Iop_64HLtoV128,
15348                           unop( Iop_ReinterpF64asI64, frD_fp_round),
15349                           mkU64( 0 ) ) );
15350          break;
15351       }
15352       case 0x034: // xsresp (VSX Scalar Reciprocal Estimate single-Precision)
15353       case 0x014: /* xsrsqrtesp (VSX Scalar Reciprocal Square Root Estimate
15354                    * single-Precision)
15355                    */
15356       {
15357          IRTemp frB = newTemp(Ity_F64);
15358          IRTemp sqrt = newTemp(Ity_F64);
15359          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
15360          IRExpr* rm  = get_IR_roundingmode();
15361          Bool redp = opc2 == 0x034;
15362          DIP("%s v%d,v%d\n", redp ? "xsresp" : "xsrsqrtesp", XT,
15363              XB);
15364 
15365          assign( frB,
15366                  unop( Iop_ReinterpI64asF64,
15367                        unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
15368 
15369          if (!redp)
15370             assign( sqrt,
15371                     binop( Iop_SqrtF64,
15372                            rm,
15373                            mkexpr(frB) ) );
15374          putVSReg( XT,
15375                       binop( Iop_64HLtoV128,
15376                              unop( Iop_ReinterpF64asI64,
15377                                    binop( Iop_RoundF64toF32, rm,
15378                                           triop( Iop_DivF64,
15379                                                  rm,
15380                                                  ieee_one,
15381                                                  redp ? mkexpr( frB ) :
15382                                                         mkexpr( sqrt ) ) ) ),
15383                              mkU64( 0 ) ) );
15384          break;
15385       }
15386 
15387       case 0x0B4: // xsredp (VSX Scalar Reciprocal Estimate Double-Precision)
15388       case 0x094: // xsrsqrtedp (VSX Scalar Reciprocal Square Root Estimate Double-Precision)
15389 
15390       {
15391          IRTemp frB = newTemp(Ity_F64);
15392          IRTemp sqrt = newTemp(Ity_F64);
15393          IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
15394          IRExpr* rm  = get_IR_roundingmode();
15395          Bool redp = opc2 == 0x0B4;
15396          DIP("%s v%d,v%d\n", redp ? "xsredp" : "xsrsqrtedp", XT, XB);
15397          assign( frB,
15398                  unop( Iop_ReinterpI64asF64,
15399                        unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
15400 
15401          if (!redp)
15402             assign( sqrt,
15403                     binop( Iop_SqrtF64,
15404                            rm,
15405                            mkexpr(frB) ) );
15406          putVSReg( XT,
15407                       binop( Iop_64HLtoV128,
15408                              unop( Iop_ReinterpF64asI64,
15409                                    triop( Iop_DivF64,
15410                                           rm,
15411                                           ieee_one,
15412                                           redp ? mkexpr( frB ) : mkexpr( sqrt ) ) ),
15413                              mkU64( 0 ) ) );
15414          break;
15415       }
15416 
15417       case 0x232: // xsrsp (VSX Scalar Round to Single-Precision)
15418       {
15419          IRTemp frB = newTemp(Ity_F64);
15420          IRExpr* rm  = get_IR_roundingmode();
15421          DIP("xsrsp v%d, v%d\n", XT, XB);
15422          assign( frB,
15423                  unop( Iop_ReinterpI64asF64,
15424                        unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
15425 
15426          putVSReg( XT, binop( Iop_64HLtoV128,
15427                               unop( Iop_ReinterpF64asI64,
15428                                     binop( Iop_RoundF64toF32,
15429                                            rm,
15430                                            mkexpr( frB ) ) ),
15431                               mkU64( 0 ) ) );
15432          break;
15433       }
15434 
15435       default:
15436          vex_printf( "dis_vxs_misc(ppc)(opc2)\n" );
15437          return False;
15438    }
15439    return True;
15440 }
15441 
15442 /*
15443  * VSX Logical Instructions
15444  */
15445 static Bool
dis_vx_logic(UInt theInstr,UInt opc2)15446 dis_vx_logic ( UInt theInstr, UInt opc2 )
15447 {
15448    /* XX3-Form */
15449    UChar opc1 = ifieldOPC( theInstr );
15450    UChar XT = ifieldRegXT ( theInstr );
15451    UChar XA = ifieldRegXA ( theInstr );
15452    UChar XB = ifieldRegXB ( theInstr );
15453    IRTemp vA = newTemp( Ity_V128 );
15454    IRTemp vB = newTemp( Ity_V128 );
15455 
15456    if (opc1 != 0x3C) {
15457       vex_printf( "dis_vx_logic(ppc)(instr)\n" );
15458       return False;
15459    }
15460 
15461    assign( vA, getVSReg( XA ) );
15462    assign( vB, getVSReg( XB ) );
15463 
15464    switch (opc2) {
15465       case 0x268: // xxlxor
15466          DIP("xxlxor v%d,v%d,v%d\n", XT, XA, XB);
15467          putVSReg( XT, binop( Iop_XorV128, mkexpr( vA ), mkexpr( vB ) ) );
15468          break;
15469       case 0x248: // xxlor
15470          DIP("xxlor v%d,v%d,v%d\n", XT, XA, XB);
15471          putVSReg( XT, binop( Iop_OrV128, mkexpr( vA ), mkexpr( vB ) ) );
15472          break;
15473       case 0x288: // xxlnor
15474          DIP("xxlnor v%d,v%d,v%d\n", XT, XA, XB);
15475          putVSReg( XT, unop( Iop_NotV128, binop( Iop_OrV128, mkexpr( vA ),
15476                                                  mkexpr( vB ) ) ) );
15477          break;
15478       case 0x208: // xxland
15479          DIP("xxland v%d,v%d,v%d\n", XT, XA, XB);
15480          putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), mkexpr( vB ) ) );
15481          break;
15482       case 0x228: //xxlandc
15483          DIP("xxlandc v%d,v%d,v%d\n", XT, XA, XB);
15484          putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), unop( Iop_NotV128,
15485                                                                mkexpr( vB ) ) ) );
15486          break;
15487       case 0x2A8: // xxlorc (VSX Logical OR with complement)
15488          DIP("xxlorc v%d,v%d,v%d\n", XT, XA, XB);
15489          putVSReg( XT, binop( Iop_OrV128,
15490                               mkexpr( vA ),
15491                               unop( Iop_NotV128, mkexpr( vB ) ) ) );
15492          break;
15493       case 0x2C8: // xxlnand (VSX Logical NAND)
15494          DIP("xxlnand v%d,v%d,v%d\n", XT, XA, XB);
15495          putVSReg( XT, unop( Iop_NotV128,
15496                              binop( Iop_AndV128, mkexpr( vA ),
15497                                     mkexpr( vB ) ) ) );
15498          break;
15499       case 0x2E8: // xxleqv (VSX Logical Equivalence)
15500          DIP("xxleqv v%d,v%d,v%d\n", XT, XA, XB);
15501          putVSReg( XT, unop( Iop_NotV128,
15502                              binop( Iop_XorV128,
15503                              mkexpr( vA ), mkexpr( vB ) ) ) );
15504          break;
15505       default:
15506          vex_printf( "dis_vx_logic(ppc)(opc2)\n" );
15507          return False;
15508    }
15509    return True;
15510 }
15511 
15512 /*
15513  * VSX Load Instructions
15514  * NOTE: VSX supports word-aligned storage access.
15515  */
15516 static Bool
dis_vx_load(UInt theInstr)15517 dis_vx_load ( UInt theInstr )
15518 {
15519    /* XX1-Form */
15520    UChar opc1 = ifieldOPC( theInstr );
15521    UChar XT = ifieldRegXT ( theInstr );
15522    UChar rA_addr = ifieldRegA( theInstr );
15523    UChar rB_addr = ifieldRegB( theInstr );
15524    UInt opc2 = ifieldOPClo10( theInstr );
15525 
15526    IRType ty = mode64 ? Ity_I64 : Ity_I32;
15527    IRTemp EA = newTemp( ty );
15528 
15529    if (opc1 != 0x1F) {
15530       vex_printf( "dis_vx_load(ppc)(instr)\n" );
15531       return False;
15532    }
15533 
15534    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
15535 
15536    switch (opc2) {
15537    case 0x00C: // lxsiwzx (Load VSX Scalar as Integer Word and Zero Indexed)
15538    {
15539       IRExpr * exp;
15540       DIP("lxsiwzx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
15541 
15542       if (host_endness == VexEndnessLE)
15543          exp = unop( Iop_64to32, load( Ity_I64, mkexpr( EA ) ) );
15544       else
15545          exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) );
15546 
15547       putVSReg( XT, binop( Iop_64HLtoV128,
15548                            unop( Iop_32Uto64, exp),
15549                            mkU64(0) ) );
15550       break;
15551    }
15552    case 0x04C: // lxsiwax (Load VSX Scalar as Integer Word Algebraic Indexed)
15553    {
15554       IRExpr * exp;
15555       DIP("lxsiwax %d,r%u,r%u\n", XT, rA_addr, rB_addr);
15556 
15557       if (host_endness == VexEndnessLE)
15558          exp = unop( Iop_64to32, load( Ity_I64, mkexpr( EA ) ) );
15559       else
15560          exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) );
15561 
15562       putVSReg( XT, binop( Iop_64HLtoV128,
15563                            unop( Iop_32Sto64, exp),
15564                            mkU64(0) ) );
15565       break;
15566    }
15567    case 0x20C: // lxsspx (Load VSX Scalar Single-Precision Indexed)
15568    {
15569       IRExpr * exp;
15570       DIP("lxsspx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
15571       /* Take 32-bit floating point value in the upper half of the fetched
15572        * 64-bit value, convert to 64-bit floating point value and load into
15573        * top word of V128.
15574        */
15575       exp = unop( Iop_ReinterpF64asI64,
15576                   unop( Iop_F32toF64,
15577                         unop( Iop_ReinterpI32asF32,
15578                               load( Ity_I32, mkexpr( EA ) ) ) ) );
15579 
15580       putVSReg( XT, binop( Iop_64HLtoV128, exp, mkU64( 0 ) ) );
15581       break;
15582    }
15583    case 0x24C: // lxsdx
15584    {
15585       IRExpr * exp;
15586       DIP("lxsdx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
15587       exp = load( Ity_I64, mkexpr( EA ) );
15588       // We need to pass an expression of type Ity_V128 with putVSReg, but the load
15589       // we just performed is only a DW.  But since the contents of VSR[XT] element 1
15590       // are undefined after this operation, we can just do a splat op.
15591       putVSReg( XT, binop( Iop_64HLtoV128, exp, exp ) );
15592       break;
15593    }
15594    case 0x34C: // lxvd2x
15595    {
15596       IROp addOp = ty == Ity_I64 ? Iop_Add64 : Iop_Add32;
15597       IRExpr * high, *low;
15598       ULong ea_off = 8;
15599       IRExpr* high_addr;
15600       DIP("lxvd2x %d,r%u,r%u\n", XT, rA_addr, rB_addr);
15601       high = load( Ity_I64, mkexpr( EA ) );
15602       high_addr = binop( addOp, mkexpr( EA ), ty == Ity_I64 ? mkU64( ea_off )
15603             : mkU32( ea_off ) );
15604       low = load( Ity_I64, high_addr );
15605       putVSReg( XT, binop( Iop_64HLtoV128, high, low ) );
15606       break;
15607    }
15608    case 0x14C: // lxvdsx
15609    {
15610       IRTemp data = newTemp(Ity_I64);
15611       DIP("lxvdsx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
15612       assign( data, load( Ity_I64, mkexpr( EA ) ) );
15613       putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( data ), mkexpr( data ) ) );
15614       break;
15615    }
15616    case 0x30C:
15617    {
15618       IRExpr *t0;
15619 
15620       DIP("lxvw4x %d,r%u,r%u\n", XT, rA_addr, rB_addr);
15621 
15622       /* The load will result in the data being in BE order. */
15623       if (host_endness == VexEndnessLE) {
15624          IRExpr *t0_BE;
15625          IRTemp perm_LE = newTemp(Ity_V128);
15626 
15627          t0_BE = load( Ity_V128, mkexpr( EA ) );
15628 
15629          /*  Permute the data to LE format */
15630          assign( perm_LE, binop( Iop_64HLtoV128, mkU64(0x0c0d0e0f08090a0bULL),
15631                                  mkU64(0x0405060700010203ULL)));
15632 
15633          t0 = binop( Iop_Perm8x16, t0_BE, mkexpr(perm_LE) );
15634       } else {
15635          t0 = load( Ity_V128, mkexpr( EA ) );
15636       }
15637 
15638       putVSReg( XT, t0 );
15639       break;
15640    }
15641    default:
15642       vex_printf( "dis_vx_load(ppc)(opc2)\n" );
15643       return False;
15644    }
15645    return True;
15646 }
15647 
15648 /*
15649  * VSX Store Instructions
15650  * NOTE: VSX supports word-aligned storage access.
15651  */
15652 static Bool
dis_vx_store(UInt theInstr)15653 dis_vx_store ( UInt theInstr )
15654 {
15655    /* XX1-Form */
15656    UChar opc1 = ifieldOPC( theInstr );
15657    UChar XS = ifieldRegXS( theInstr );
15658    UChar rA_addr = ifieldRegA( theInstr );
15659    UChar rB_addr = ifieldRegB( theInstr );
15660    IRTemp vS = newTemp( Ity_V128 );
15661    UInt opc2 = ifieldOPClo10( theInstr );
15662 
15663    IRType ty = mode64 ? Ity_I64 : Ity_I32;
15664    IRTemp EA = newTemp( ty );
15665 
15666    if (opc1 != 0x1F) {
15667       vex_printf( "dis_vx_store(ppc)(instr)\n" );
15668       return False;
15669    }
15670 
15671    assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
15672    assign( vS, getVSReg( XS ) );
15673 
15674    switch (opc2) {
15675    case 0x08C:
15676    {
15677      /* Need the next to the most significant 32-bit word from
15678       * the 128-bit vector.
15679       */
15680       IRExpr * high64, * low32;
15681       DIP("stxsiwx %d,r%u,r%u\n", XS, rA_addr, rB_addr);
15682       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
15683       low32  = unop( Iop_64to32, high64 );
15684       store( mkexpr( EA ), low32 );
15685       break;
15686    }
15687    case 0x28C:
15688    {
15689       IRTemp high64 = newTemp(Ity_F64);
15690       IRTemp val32  = newTemp(Ity_I32);
15691       DIP("stxsspx %d,r%u,r%u\n", XS, rA_addr, rB_addr);
15692       assign(high64, unop( Iop_ReinterpI64asF64,
15693                            unop( Iop_V128HIto64, mkexpr( vS ) ) ) );
15694       assign(val32, unop( Iop_ReinterpF32asI32,
15695                           unop( Iop_TruncF64asF32,
15696                                 mkexpr(high64) ) ) );
15697       store( mkexpr( EA ), mkexpr( val32 ) );
15698       break;
15699    }
15700    case 0x2CC:
15701    {
15702       IRExpr * high64;
15703       DIP("stxsdx %d,r%u,r%u\n", XS, rA_addr, rB_addr);
15704       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
15705       store( mkexpr( EA ), high64 );
15706       break;
15707    }
15708    case 0x3CC:
15709    {
15710       IRExpr * high64, *low64;
15711       DIP("stxvd2x %d,r%u,r%u\n", XS, rA_addr, rB_addr);
15712       high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
15713       low64 = unop( Iop_V128to64, mkexpr( vS ) );
15714       store( mkexpr( EA ), high64 );
15715       store( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
15716                     ty == Ity_I64 ? mkU64( 8 ) : mkU32( 8 ) ), low64 );
15717       break;
15718    }
15719    case 0x38C:
15720    {
15721       UInt ea_off = 0;
15722       IRExpr* irx_addr;
15723       IRTemp hi64 = newTemp( Ity_I64 );
15724       IRTemp lo64 = newTemp( Ity_I64 );
15725 
15726       DIP("stxvw4x %d,r%u,r%u\n", XS, rA_addr, rB_addr);
15727 
15728       // This instruction supports word-aligned stores, so EA may not be
15729       // quad-word aligned.  Therefore, do 4 individual word-size stores.
15730       assign( hi64, unop( Iop_V128HIto64, mkexpr( vS ) ) );
15731       assign( lo64, unop( Iop_V128to64, mkexpr( vS ) ) );
15732       store( mkexpr( EA ), unop( Iop_64HIto32, mkexpr( hi64 ) ) );
15733       ea_off += 4;
15734       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
15735                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
15736       store( irx_addr, unop( Iop_64to32, mkexpr( hi64 ) ) );
15737       ea_off += 4;
15738       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
15739                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
15740       store( irx_addr, unop( Iop_64HIto32, mkexpr( lo64 ) ) );
15741       ea_off += 4;
15742       irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
15743                         ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
15744       store( irx_addr, unop( Iop_64to32, mkexpr( lo64 ) ) );
15745 
15746       break;
15747    }
15748    default:
15749       vex_printf( "dis_vx_store(ppc)(opc2)\n" );
15750       return False;
15751    }
15752    return True;
15753 }
15754 
15755 /*
15756  * VSX permute and other miscealleous instructions
15757  */
15758 static Bool
dis_vx_permute_misc(UInt theInstr,UInt opc2)15759 dis_vx_permute_misc( UInt theInstr, UInt opc2 )
15760 {
15761    /* XX3-Form */
15762    UChar opc1 = ifieldOPC( theInstr );
15763    UChar XT = ifieldRegXT ( theInstr );
15764    UChar XA = ifieldRegXA ( theInstr );
15765    UChar XB = ifieldRegXB ( theInstr );
15766    IRTemp vT = newTemp( Ity_V128 );
15767    IRTemp vA = newTemp( Ity_V128 );
15768    IRTemp vB = newTemp( Ity_V128 );
15769 
15770    if (opc1 != 0x3C) {
15771       vex_printf( "dis_vx_permute_misc(ppc)(instr)\n" );
15772       return False;
15773    }
15774 
15775    assign( vA, getVSReg( XA ) );
15776    assign( vB, getVSReg( XB ) );
15777 
15778    switch (opc2) {
15779       case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate)
15780       {
15781          UChar SHW = ifieldSHW ( theInstr );
15782          IRTemp result = newTemp(Ity_V128);
15783          if ( SHW != 0 ) {
15784              IRTemp hi = newTemp(Ity_V128);
15785              IRTemp lo = newTemp(Ity_V128);
15786              assign( hi, binop(Iop_ShlV128, mkexpr(vA), mkU8(SHW*32)) );
15787              assign( lo, binop(Iop_ShrV128, mkexpr(vB), mkU8(128-SHW*32)) );
15788              assign ( result, binop(Iop_OrV128, mkexpr(hi), mkexpr(lo)) );
15789          } else
15790              assign ( result, mkexpr(vA) );
15791          DIP("xxsldwi v%d,v%d,v%d,%d\n", XT, XA, XB, SHW);
15792          putVSReg( XT, mkexpr(result) );
15793          break;
15794       }
15795       case 0x28: // xpermdi (VSX Permute Doubleword Immediate)
15796       {
15797          UChar DM = ifieldDM ( theInstr );
15798          IRTemp hi = newTemp(Ity_I64);
15799          IRTemp lo = newTemp(Ity_I64);
15800 
15801          if (DM & 0x2)
15802            assign( hi, unop(Iop_V128to64, mkexpr(vA)) );
15803          else
15804            assign( hi, unop(Iop_V128HIto64, mkexpr(vA)) );
15805 
15806          if (DM & 0x1)
15807            assign( lo, unop(Iop_V128to64, mkexpr(vB)) );
15808          else
15809            assign( lo, unop(Iop_V128HIto64, mkexpr(vB)) );
15810 
15811          assign( vT, binop(Iop_64HLtoV128, mkexpr(hi), mkexpr(lo)) );
15812 
15813          DIP("xxpermdi v%d,v%d,v%d,0x%x\n", XT, XA, XB, DM);
15814          putVSReg( XT, mkexpr( vT ) );
15815          break;
15816       }
15817       case 0x48: // xxmrghw (VSX Merge High Word)
15818       case 0xc8: // xxmrglw (VSX Merge Low Word)
15819       {
15820          const HChar type = (opc2 == 0x48) ? 'h' : 'l';
15821          IROp word_op = (opc2 == 0x48) ? Iop_V128HIto64 : Iop_V128to64;
15822          IRTemp a64 = newTemp(Ity_I64);
15823          IRTemp ahi32 = newTemp(Ity_I32);
15824          IRTemp alo32 = newTemp(Ity_I32);
15825          IRTemp b64 = newTemp(Ity_I64);
15826          IRTemp bhi32 = newTemp(Ity_I32);
15827          IRTemp blo32 = newTemp(Ity_I32);
15828 
15829          assign( a64, unop(word_op, mkexpr(vA)) );
15830          assign( ahi32, unop(Iop_64HIto32, mkexpr(a64)) );
15831          assign( alo32, unop(Iop_64to32, mkexpr(a64)) );
15832 
15833          assign( b64, unop(word_op, mkexpr(vB)) );
15834          assign( bhi32, unop(Iop_64HIto32, mkexpr(b64)) );
15835          assign( blo32, unop(Iop_64to32, mkexpr(b64)) );
15836 
15837          assign( vT, binop(Iop_64HLtoV128,
15838                            binop(Iop_32HLto64, mkexpr(ahi32), mkexpr(bhi32)),
15839                            binop(Iop_32HLto64, mkexpr(alo32), mkexpr(blo32))) );
15840 
15841          DIP("xxmrg%cw v%d,v%d,v%d\n", type, XT, XA, XB);
15842          putVSReg( XT, mkexpr( vT ) );
15843          break;
15844       }
15845       case 0x018: // xxsel (VSX Select)
15846       {
15847          UChar XC = ifieldRegXC(theInstr);
15848          IRTemp vC = newTemp( Ity_V128 );
15849          assign( vC, getVSReg( XC ) );
15850          DIP("xxsel v%d,v%d,v%d,v%d\n", XT, XA, XB, XC);
15851          /* vD = (vA & ~vC) | (vB & vC) */
15852          putVSReg( XT, binop(Iop_OrV128,
15853             binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
15854             binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
15855          break;
15856       }
15857       case 0x148: // xxspltw (VSX Splat Word)
15858       {
15859          UChar UIM   = ifieldRegA(theInstr) & 3;
15860          UChar sh_uim = (3 - (UIM)) * 32;
15861          DIP("xxspltw v%d,v%d,%d\n", XT, XB, UIM);
15862          putVSReg( XT,
15863                    unop( Iop_Dup32x4,
15864                          unop( Iop_V128to32,
15865                                binop( Iop_ShrV128, mkexpr( vB ), mkU8( sh_uim ) ) ) ) );
15866          break;
15867       }
15868 
15869       default:
15870          vex_printf( "dis_vx_permute_misc(ppc)(opc2)\n" );
15871          return False;
15872    }
15873    return True;
15874 }
15875 
15876 /*
15877   AltiVec Load Instructions
15878 */
dis_av_load(const VexAbiInfo * vbi,UInt theInstr)15879 static Bool dis_av_load ( const VexAbiInfo* vbi, UInt theInstr )
15880 {
15881    /* X-Form */
15882    UChar opc1     = ifieldOPC(theInstr);
15883    UChar vD_addr  = ifieldRegDS(theInstr);
15884    UChar rA_addr  = ifieldRegA(theInstr);
15885    UChar rB_addr  = ifieldRegB(theInstr);
15886    UInt  opc2     = ifieldOPClo10(theInstr);
15887    UChar b0       = ifieldBIT0(theInstr);
15888 
15889    IRType ty         = mode64 ? Ity_I64 : Ity_I32;
15890    IRTemp EA         = newTemp(ty);
15891    IRTemp EA_align16 = newTemp(ty);
15892 
15893    if (opc1 != 0x1F || b0 != 0) {
15894       vex_printf("dis_av_load(ppc)(instr)\n");
15895       return False;
15896    }
15897 
15898    assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
15899    assign( EA_align16, addr_align( mkexpr(EA), 16 ) );
15900 
15901    switch (opc2) {
15902 
15903    case 0x006: { // lvsl (Load Vector for Shift Left, AV p123)
15904       IRDirty* d;
15905       UInt vD_off = vectorGuestRegOffset(vD_addr);
15906       IRExpr** args_be = mkIRExprVec_5(
15907                          IRExpr_BBPTR(),
15908                          mkU32(vD_off),
15909                          binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
15910                                           mkU32(0xF)),
15911                          mkU32(0)/*left*/,
15912                          mkU32(1)/*Big Endian*/);
15913       IRExpr** args_le = mkIRExprVec_5(
15914                          IRExpr_BBPTR(),
15915                          mkU32(vD_off),
15916                          binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
15917                                           mkU32(0xF)),
15918                          mkU32(0)/*left*/,
15919                          mkU32(0)/*Little Endian*/);
15920       if (!mode64) {
15921          d = unsafeIRDirty_0_N (
15922                         0/*regparms*/,
15923                         "ppc32g_dirtyhelper_LVS",
15924                         fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
15925                         args_be );
15926       } else {
15927          if (host_endness == VexEndnessBE)
15928             d = unsafeIRDirty_0_N (
15929                            0/*regparms*/,
15930                            "ppc64g_dirtyhelper_LVS",
15931                            fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
15932                            args_be );
15933          else
15934             d = unsafeIRDirty_0_N (
15935                            0/*regparms*/,
15936                            "ppc64g_dirtyhelper_LVS",
15937                            &ppc64g_dirtyhelper_LVS,
15938                            args_le );
15939       }
15940       DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
15941       /* declare guest state effects */
15942       d->nFxState = 1;
15943       vex_bzero(&d->fxState, sizeof(d->fxState));
15944       d->fxState[0].fx     = Ifx_Write;
15945       d->fxState[0].offset = vD_off;
15946       d->fxState[0].size   = sizeof(U128);
15947 
15948       /* execute the dirty call, side-effecting guest state */
15949       stmt( IRStmt_Dirty(d) );
15950       break;
15951    }
15952    case 0x026: { // lvsr (Load Vector for Shift Right, AV p125)
15953       IRDirty* d;
15954       UInt vD_off = vectorGuestRegOffset(vD_addr);
15955       IRExpr** args_be = mkIRExprVec_5(
15956                              IRExpr_BBPTR(),
15957                              mkU32(vD_off),
15958                              binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
15959                                               mkU32(0xF)),
15960                              mkU32(1)/*right*/,
15961                              mkU32(1)/*Big Endian*/);
15962       IRExpr** args_le = mkIRExprVec_5(
15963                              IRExpr_BBPTR(),
15964                              mkU32(vD_off),
15965                              binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
15966                                               mkU32(0xF)),
15967                              mkU32(1)/*right*/,
15968                              mkU32(0)/*Little Endian*/);
15969 
15970       if (!mode64) {
15971          d = unsafeIRDirty_0_N (
15972                         0/*regparms*/,
15973                         "ppc32g_dirtyhelper_LVS",
15974                         fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
15975                         args_be );
15976       } else {
15977          if (host_endness == VexEndnessBE)
15978             d = unsafeIRDirty_0_N (
15979                            0/*regparms*/,
15980                            "ppc64g_dirtyhelper_LVS",
15981                            fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
15982                            args_be );
15983          else
15984             d = unsafeIRDirty_0_N (
15985                            0/*regparms*/,
15986                            "ppc64g_dirtyhelper_LVS",
15987                            &ppc64g_dirtyhelper_LVS,
15988                            args_le );
15989       }
15990       DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
15991       /* declare guest state effects */
15992       d->nFxState = 1;
15993       vex_bzero(&d->fxState, sizeof(d->fxState));
15994       d->fxState[0].fx     = Ifx_Write;
15995       d->fxState[0].offset = vD_off;
15996       d->fxState[0].size   = sizeof(U128);
15997 
15998       /* execute the dirty call, side-effecting guest state */
15999       stmt( IRStmt_Dirty(d) );
16000       break;
16001    }
16002    case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119)
16003       DIP("lvebx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
16004       /* loads addressed byte into vector[EA[0:3]
16005          since all other destination bytes are undefined,
16006          can simply load entire vector from 16-aligned EA */
16007       putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
16008       break;
16009 
16010    case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121)
16011       DIP("lvehx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
16012       /* see note for lvebx */
16013       putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
16014       break;
16015 
16016    case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122)
16017       DIP("lvewx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
16018       /* see note for lvebx */
16019       putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
16020       break;
16021 
16022    case 0x067: // lvx (Load Vector Indexed, AV p127)
16023       DIP("lvx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
16024       putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
16025       break;
16026 
16027    case 0x167: // lvxl (Load Vector Indexed LRU, AV p128)
16028       DIP("lvxl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
16029       putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
16030       break;
16031 
16032    default:
16033       vex_printf("dis_av_load(ppc)(opc2)\n");
16034       return False;
16035    }
16036    return True;
16037 }
16038 
16039 /*
16040   AltiVec Store Instructions
16041 */
dis_av_store(UInt theInstr)16042 static Bool dis_av_store ( UInt theInstr )
16043 {
16044    /* X-Form */
16045    UChar opc1     = ifieldOPC(theInstr);
16046    UChar vS_addr  = ifieldRegDS(theInstr);
16047    UChar rA_addr  = ifieldRegA(theInstr);
16048    UChar rB_addr  = ifieldRegB(theInstr);
16049    UInt  opc2     = ifieldOPClo10(theInstr);
16050    UChar b0       = ifieldBIT0(theInstr);
16051 
16052    IRType ty           = mode64 ? Ity_I64 : Ity_I32;
16053    IRTemp EA           = newTemp(ty);
16054    IRTemp addr_aligned = newTemp(ty);
16055    IRTemp vS           = newTemp(Ity_V128);
16056    IRTemp eb           = newTemp(Ity_I8);
16057    IRTemp idx          = newTemp(Ity_I8);
16058 
16059    if (opc1 != 0x1F || b0 != 0) {
16060       vex_printf("dis_av_store(ppc)(instr)\n");
16061       return False;
16062    }
16063 
16064    assign( vS, getVReg(vS_addr));
16065    assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
16066 
16067    switch (opc2) {
16068    case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131)
16069       DIP("stvebx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
16070       assign( eb, binop(Iop_And8, mkU8(0xF),
16071                         unop(Iop_32to8,
16072                              mkNarrowTo32(ty, mkexpr(EA)) )) );
16073      if (host_endness == VexEndnessLE) {
16074          assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
16075       } else {
16076          assign( idx, binop(Iop_Shl8,
16077                             binop(Iop_Sub8, mkU8(15), mkexpr(eb)),
16078                             mkU8(3)) );
16079       }
16080       store( mkexpr(EA),
16081              unop( Iop_32to8, unop(Iop_V128to32,
16082                    binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
16083       break;
16084    }
16085    case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132)
16086       DIP("stvehx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
16087       assign( addr_aligned, addr_align(mkexpr(EA), 2) );
16088       assign( eb, binop(Iop_And8, mkU8(0xF),
16089                         mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
16090       if (host_endness == VexEndnessLE) {
16091           assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
16092       } else {
16093          assign( idx, binop(Iop_Shl8,
16094                             binop(Iop_Sub8, mkU8(14), mkexpr(eb)),
16095                             mkU8(3)) );
16096       }
16097       store( mkexpr(addr_aligned),
16098              unop( Iop_32to16, unop(Iop_V128to32,
16099                    binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
16100       break;
16101    }
16102    case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133)
16103       DIP("stvewx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
16104       assign( addr_aligned, addr_align(mkexpr(EA), 4) );
16105       assign( eb, binop(Iop_And8, mkU8(0xF),
16106                         mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
16107       if (host_endness == VexEndnessLE) {
16108          assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
16109       } else {
16110          assign( idx, binop(Iop_Shl8,
16111                             binop(Iop_Sub8, mkU8(12), mkexpr(eb)),
16112                             mkU8(3)) );
16113       }
16114       store( mkexpr( addr_aligned),
16115              unop( Iop_V128to32,
16116                    binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) );
16117       break;
16118    }
16119 
16120    case 0x0E7: // stvx (Store Vector Indexed, AV p134)
16121       DIP("stvx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
16122       store( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
16123       break;
16124 
16125    case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135)
16126       DIP("stvxl v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
16127       store( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
16128       break;
16129 
16130    default:
16131       vex_printf("dis_av_store(ppc)(opc2)\n");
16132       return False;
16133    }
16134    return True;
16135 }
16136 
16137 /*
16138   AltiVec Arithmetic Instructions
16139 */
dis_av_arith(UInt theInstr)16140 static Bool dis_av_arith ( UInt theInstr )
16141 {
16142    /* VX-Form */
16143    UChar opc1     = ifieldOPC(theInstr);
16144    UChar vD_addr  = ifieldRegDS(theInstr);
16145    UChar vA_addr  = ifieldRegA(theInstr);
16146    UChar vB_addr  = ifieldRegB(theInstr);
16147    UInt  opc2     = IFIELD( theInstr, 0, 11 );
16148 
16149    IRTemp vA = newTemp(Ity_V128);
16150    IRTemp vB = newTemp(Ity_V128);
16151    IRTemp z3 = newTemp(Ity_I64);
16152    IRTemp z2 = newTemp(Ity_I64);
16153    IRTemp z1 = newTemp(Ity_I64);
16154    IRTemp z0 = newTemp(Ity_I64);
16155    IRTemp aEvn, aOdd;
16156    IRTemp a15, a14, a13, a12, a11, a10, a9, a8;
16157    IRTemp a7, a6, a5, a4, a3, a2, a1, a0;
16158    IRTemp b3, b2, b1, b0;
16159 
16160    aEvn = aOdd = IRTemp_INVALID;
16161    a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID;
16162    a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID;
16163    b3 = b2 = b1 = b0 = IRTemp_INVALID;
16164 
16165    assign( vA, getVReg(vA_addr));
16166    assign( vB, getVReg(vB_addr));
16167 
16168    if (opc1 != 0x4) {
16169       vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n");
16170       return False;
16171    }
16172 
16173    switch (opc2) {
16174    /* Add */
16175    case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136)
16176       DIP("vaddcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16177       /* unsigned_ov(x+y) = (y >u not(x)) */
16178       putVReg( vD_addr, binop(Iop_ShrN32x4,
16179                               binop(Iop_CmpGT32Ux4, mkexpr(vB),
16180                                     unop(Iop_NotV128, mkexpr(vA))),
16181                               mkU8(31)) );
16182       break;
16183    }
16184    case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141)
16185       DIP("vaddubm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16186       putVReg( vD_addr, binop(Iop_Add8x16, mkexpr(vA), mkexpr(vB)) );
16187       break;
16188 
16189    case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143)
16190       DIP("vadduhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16191       putVReg( vD_addr, binop(Iop_Add16x8, mkexpr(vA), mkexpr(vB)) );
16192       break;
16193 
16194    case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145)
16195       DIP("vadduwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16196       putVReg( vD_addr, binop(Iop_Add32x4, mkexpr(vA), mkexpr(vB)) );
16197       break;
16198 
16199    case 0x0C0: // vaddudm (Add Unsigned Double Word Modulo)
16200       DIP("vaddudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16201       putVReg( vD_addr, binop(Iop_Add64x2, mkexpr(vA), mkexpr(vB)) );
16202       break;
16203 
16204    case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142)
16205       DIP("vaddubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16206       putVReg( vD_addr, binop(Iop_QAdd8Ux16, mkexpr(vA), mkexpr(vB)) );
16207       // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16
16208       break;
16209 
16210    case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144)
16211       DIP("vadduhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16212       putVReg( vD_addr, binop(Iop_QAdd16Ux8, mkexpr(vA), mkexpr(vB)) );
16213       // TODO: set VSCR[SAT]
16214       break;
16215 
16216    case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146)
16217       DIP("vadduws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16218       putVReg( vD_addr, binop(Iop_QAdd32Ux4, mkexpr(vA), mkexpr(vB)) );
16219       // TODO: set VSCR[SAT]
16220       break;
16221 
16222    case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138)
16223       DIP("vaddsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16224       putVReg( vD_addr, binop(Iop_QAdd8Sx16, mkexpr(vA), mkexpr(vB)) );
16225       // TODO: set VSCR[SAT]
16226       break;
16227 
16228    case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139)
16229       DIP("vaddshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16230       putVReg( vD_addr, binop(Iop_QAdd16Sx8, mkexpr(vA), mkexpr(vB)) );
16231       // TODO: set VSCR[SAT]
16232       break;
16233 
16234    case 0x380: // vaddsws (Add Signed Word Saturate, AV p140)
16235       DIP("vaddsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16236       putVReg( vD_addr, binop(Iop_QAdd32Sx4, mkexpr(vA), mkexpr(vB)) );
16237       // TODO: set VSCR[SAT]
16238       break;
16239 
16240 
16241    /* Subtract */
16242    case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260)
16243       DIP("vsubcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16244       /* unsigned_ov(x-y) = (y >u x) */
16245       putVReg( vD_addr, binop(Iop_ShrN32x4,
16246                               unop(Iop_NotV128,
16247                                    binop(Iop_CmpGT32Ux4, mkexpr(vB),
16248                                          mkexpr(vA))),
16249                               mkU8(31)) );
16250       break;
16251    }
16252    case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265)
16253       DIP("vsububm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16254       putVReg( vD_addr, binop(Iop_Sub8x16, mkexpr(vA), mkexpr(vB)) );
16255       break;
16256 
16257    case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267)
16258       DIP("vsubuhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16259       putVReg( vD_addr, binop(Iop_Sub16x8, mkexpr(vA), mkexpr(vB)) );
16260       break;
16261 
16262    case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269)
16263       DIP("vsubuwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16264       putVReg( vD_addr, binop(Iop_Sub32x4, mkexpr(vA), mkexpr(vB)) );
16265       break;
16266 
16267    case 0x4C0: // vsubudm (Subtract Unsigned Double Word Modulo)
16268       DIP("vsubudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16269       putVReg( vD_addr, binop(Iop_Sub64x2, mkexpr(vA), mkexpr(vB)) );
16270       break;
16271 
16272    case 0x600: // vsububs (Subtract Unsigned Byte Saturate, AV p266)
16273       DIP("vsububs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16274       putVReg( vD_addr, binop(Iop_QSub8Ux16, mkexpr(vA), mkexpr(vB)) );
16275       // TODO: set VSCR[SAT]
16276       break;
16277 
16278    case 0x640: // vsubuhs (Subtract Unsigned HWord Saturate, AV p268)
16279       DIP("vsubuhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16280       putVReg( vD_addr, binop(Iop_QSub16Ux8, mkexpr(vA), mkexpr(vB)) );
16281       // TODO: set VSCR[SAT]
16282       break;
16283 
16284    case 0x680: // vsubuws (Subtract Unsigned Word Saturate, AV p270)
16285       DIP("vsubuws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16286       putVReg( vD_addr, binop(Iop_QSub32Ux4, mkexpr(vA), mkexpr(vB)) );
16287       // TODO: set VSCR[SAT]
16288       break;
16289 
16290    case 0x700: // vsubsbs (Subtract Signed Byte Saturate, AV p262)
16291       DIP("vsubsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16292       putVReg( vD_addr, binop(Iop_QSub8Sx16, mkexpr(vA), mkexpr(vB)) );
16293       // TODO: set VSCR[SAT]
16294       break;
16295 
16296    case 0x740: // vsubshs (Subtract Signed Half Word Saturate, AV p263)
16297       DIP("vsubshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16298       putVReg( vD_addr, binop(Iop_QSub16Sx8, mkexpr(vA), mkexpr(vB)) );
16299       // TODO: set VSCR[SAT]
16300       break;
16301 
16302    case 0x780: // vsubsws (Subtract Signed Word Saturate, AV p264)
16303       DIP("vsubsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16304       putVReg( vD_addr, binop(Iop_QSub32Sx4, mkexpr(vA), mkexpr(vB)) );
16305       // TODO: set VSCR[SAT]
16306       break;
16307 
16308 
16309    /* Maximum */
16310    case 0x002: // vmaxub (Maximum Unsigned Byte, AV p182)
16311       DIP("vmaxub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16312       putVReg( vD_addr, binop(Iop_Max8Ux16, mkexpr(vA), mkexpr(vB)) );
16313       break;
16314 
16315    case 0x042: // vmaxuh (Maximum Unsigned Half Word, AV p183)
16316       DIP("vmaxuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16317       putVReg( vD_addr, binop(Iop_Max16Ux8, mkexpr(vA), mkexpr(vB)) );
16318       break;
16319 
16320    case 0x082: // vmaxuw (Maximum Unsigned Word, AV p184)
16321       DIP("vmaxuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16322       putVReg( vD_addr, binop(Iop_Max32Ux4, mkexpr(vA), mkexpr(vB)) );
16323       break;
16324 
16325    case 0x0C2: // vmaxud (Maximum Unsigned Double word)
16326       DIP("vmaxud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16327       putVReg( vD_addr, binop(Iop_Max64Ux2, mkexpr(vA), mkexpr(vB)) );
16328       break;
16329 
16330    case 0x102: // vmaxsb (Maximum Signed Byte, AV p179)
16331       DIP("vmaxsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16332       putVReg( vD_addr, binop(Iop_Max8Sx16, mkexpr(vA), mkexpr(vB)) );
16333       break;
16334 
16335    case 0x142: // vmaxsh (Maximum Signed Half Word, AV p180)
16336       DIP("vmaxsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16337       putVReg( vD_addr, binop(Iop_Max16Sx8, mkexpr(vA), mkexpr(vB)) );
16338       break;
16339 
16340    case 0x182: // vmaxsw (Maximum Signed Word, AV p181)
16341       DIP("vmaxsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16342       putVReg( vD_addr, binop(Iop_Max32Sx4, mkexpr(vA), mkexpr(vB)) );
16343       break;
16344 
16345    case 0x1C2: // vmaxsd (Maximum Signed Double word)
16346       DIP("vmaxsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16347       putVReg( vD_addr, binop(Iop_Max64Sx2, mkexpr(vA), mkexpr(vB)) );
16348       break;
16349 
16350    /* Minimum */
16351    case 0x202: // vminub (Minimum Unsigned Byte, AV p191)
16352       DIP("vminub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16353       putVReg( vD_addr, binop(Iop_Min8Ux16, mkexpr(vA), mkexpr(vB)) );
16354       break;
16355 
16356    case 0x242: // vminuh (Minimum Unsigned Half Word, AV p192)
16357       DIP("vminuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16358       putVReg( vD_addr, binop(Iop_Min16Ux8, mkexpr(vA), mkexpr(vB)) );
16359       break;
16360 
16361    case 0x282: // vminuw (Minimum Unsigned Word, AV p193)
16362       DIP("vminuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16363       putVReg( vD_addr, binop(Iop_Min32Ux4, mkexpr(vA), mkexpr(vB)) );
16364       break;
16365 
16366    case 0x2C2: // vminud (Minimum Unsigned Double Word)
16367       DIP("vminud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16368       putVReg( vD_addr, binop(Iop_Min64Ux2, mkexpr(vA), mkexpr(vB)) );
16369       break;
16370 
16371    case 0x302: // vminsb (Minimum Signed Byte, AV p188)
16372       DIP("vminsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16373       putVReg( vD_addr, binop(Iop_Min8Sx16, mkexpr(vA), mkexpr(vB)) );
16374       break;
16375 
16376    case 0x342: // vminsh (Minimum Signed Half Word, AV p189)
16377       DIP("vminsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16378       putVReg( vD_addr, binop(Iop_Min16Sx8, mkexpr(vA), mkexpr(vB)) );
16379       break;
16380 
16381    case 0x382: // vminsw (Minimum Signed Word, AV p190)
16382       DIP("vminsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16383       putVReg( vD_addr, binop(Iop_Min32Sx4, mkexpr(vA), mkexpr(vB)) );
16384       break;
16385 
16386    case 0x3C2: // vminsd (Minimum Signed Double Word)
16387       DIP("vminsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16388       putVReg( vD_addr, binop(Iop_Min64Sx2, mkexpr(vA), mkexpr(vB)) );
16389       break;
16390 
16391 
16392    /* Average */
16393    case 0x402: // vavgub (Average Unsigned Byte, AV p152)
16394       DIP("vavgub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16395       putVReg( vD_addr, binop(Iop_Avg8Ux16, mkexpr(vA), mkexpr(vB)) );
16396       break;
16397 
16398    case 0x442: // vavguh (Average Unsigned Half Word, AV p153)
16399       DIP("vavguh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16400       putVReg( vD_addr, binop(Iop_Avg16Ux8, mkexpr(vA), mkexpr(vB)) );
16401       break;
16402 
16403    case 0x482: // vavguw (Average Unsigned Word, AV p154)
16404       DIP("vavguw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16405       putVReg( vD_addr, binop(Iop_Avg32Ux4, mkexpr(vA), mkexpr(vB)) );
16406       break;
16407 
16408    case 0x502: // vavgsb (Average Signed Byte, AV p149)
16409       DIP("vavgsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16410       putVReg( vD_addr, binop(Iop_Avg8Sx16, mkexpr(vA), mkexpr(vB)) );
16411       break;
16412 
16413    case 0x542: // vavgsh (Average Signed Half Word, AV p150)
16414       DIP("vavgsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16415       putVReg( vD_addr, binop(Iop_Avg16Sx8, mkexpr(vA), mkexpr(vB)) );
16416       break;
16417 
16418    case 0x582: // vavgsw (Average Signed Word, AV p151)
16419       DIP("vavgsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16420       putVReg( vD_addr, binop(Iop_Avg32Sx4, mkexpr(vA), mkexpr(vB)) );
16421       break;
16422 
16423 
16424    /* Multiply */
16425    case 0x008: // vmuloub (Multiply Odd Unsigned Byte, AV p213)
16426       DIP("vmuloub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16427       putVReg( vD_addr,
16428                binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)));
16429       break;
16430 
16431    case 0x048: // vmulouh (Multiply Odd Unsigned Half Word, AV p214)
16432       DIP("vmulouh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16433       putVReg( vD_addr,
16434                binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)));
16435       break;
16436 
16437    case 0x088: // vmulouw (Multiply Odd Unsigned Word)
16438       DIP("vmulouw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16439       putVReg( vD_addr, binop( Iop_MullEven32Ux4, mkexpr(vA), mkexpr(vB) ) );
16440       break;
16441 
16442    case 0x089: // vmuluwm (Multiply Unsigned Word Modulo)
16443       DIP("vmuluwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16444       putVReg( vD_addr, binop( Iop_Mul32x4, mkexpr(vA), mkexpr(vB) ) );
16445       break;
16446 
16447    case 0x108: // vmulosb (Multiply Odd Signed Byte, AV p211)
16448       DIP("vmulosb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16449       putVReg( vD_addr,
16450                binop(Iop_MullEven8Sx16, mkexpr(vA), mkexpr(vB)));
16451       break;
16452 
16453    case 0x148: // vmulosh (Multiply Odd Signed Half Word, AV p212)
16454       DIP("vmulosh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16455       putVReg( vD_addr,
16456                binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)));
16457       break;
16458 
16459    case 0x188: // vmulosw (Multiply Odd Signed Word)
16460       DIP("vmulosw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16461       putVReg( vD_addr, binop( Iop_MullEven32Sx4, mkexpr(vA), mkexpr(vB) ) );
16462       break;
16463 
16464    case 0x208: // vmuleub (Multiply Even Unsigned Byte, AV p209)
16465       DIP("vmuleub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16466       putVReg( vD_addr, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
16467       break;
16468 
16469    case 0x248: // vmuleuh (Multiply Even Unsigned Half Word, AV p210)
16470       DIP("vmuleuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16471       putVReg( vD_addr, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
16472       break;
16473 
16474    case 0x288: // vmuleuw (Multiply Even Unsigned Word)
16475       DIP("vmuleuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16476       putVReg( vD_addr, MK_Iop_MullOdd32Ux4( mkexpr(vA), mkexpr(vB) ) );
16477       break;
16478 
16479    case 0x308: // vmulesb (Multiply Even Signed Byte, AV p207)
16480       DIP("vmulesb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16481       putVReg( vD_addr, MK_Iop_MullOdd8Sx16( mkexpr(vA), mkexpr(vB) ));
16482       break;
16483 
16484    case 0x348: // vmulesh (Multiply Even Signed Half Word, AV p208)
16485       DIP("vmulesh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16486       putVReg( vD_addr, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
16487       break;
16488 
16489    case 0x388: // vmulesw (Multiply Even Signed Word)
16490       DIP("vmulesw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16491       putVReg( vD_addr, MK_Iop_MullOdd32Sx4( mkexpr(vA), mkexpr(vB) ) );
16492       break;
16493 
16494    /* Sum Across Partial */
16495    case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275)
16496       IRTemp aEE, aEO, aOE, aOO;
16497       aEE = aEO = aOE = aOO = IRTemp_INVALID;
16498       DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16499 
16500       /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */
16501       expand8Ux16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
16502       expand16Ux8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
16503       expand16Ux8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
16504 
16505       /* break V128 to 4xI32's, zero-extending to I64's */
16506       breakV128to4x64U( mkexpr(aEE), &a15, &a11, &a7, &a3 );
16507       breakV128to4x64U( mkexpr(aOE), &a14, &a10, &a6, &a2 );
16508       breakV128to4x64U( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
16509       breakV128to4x64U( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
16510       breakV128to4x64U( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
16511 
16512       /* add lanes */
16513       assign( z3, binop(Iop_Add64, mkexpr(b3),
16514                      binop(Iop_Add64,
16515                         binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
16516                         binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
16517       assign( z2, binop(Iop_Add64, mkexpr(b2),
16518                      binop(Iop_Add64,
16519                          binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
16520                          binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
16521       assign( z1, binop(Iop_Add64, mkexpr(b1),
16522                      binop(Iop_Add64,
16523                          binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
16524                          binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
16525       assign( z0, binop(Iop_Add64, mkexpr(b0),
16526                      binop(Iop_Add64,
16527                          binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
16528                          binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
16529 
16530       /* saturate-narrow to 32bit, and combine to V128 */
16531       putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
16532                                          mkexpr(z1), mkexpr(z0)) );
16533       break;
16534    }
16535    case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273)
16536       IRTemp aEE, aEO, aOE, aOO;
16537       aEE = aEO = aOE = aOO = IRTemp_INVALID;
16538       DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16539 
16540       /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */
16541       expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
16542       expand16Sx8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
16543       expand16Sx8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
16544 
16545       /* break V128 to 4xI32's, sign-extending to I64's */
16546       breakV128to4x64S( mkexpr(aEE), &a15, &a11, &a7, &a3 );
16547       breakV128to4x64S( mkexpr(aOE), &a14, &a10, &a6, &a2 );
16548       breakV128to4x64S( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
16549       breakV128to4x64S( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
16550       breakV128to4x64S( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
16551 
16552       /* add lanes */
16553       assign( z3, binop(Iop_Add64, mkexpr(b3),
16554                      binop(Iop_Add64,
16555                         binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
16556                         binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
16557       assign( z2, binop(Iop_Add64, mkexpr(b2),
16558                      binop(Iop_Add64,
16559                         binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
16560                         binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
16561       assign( z1, binop(Iop_Add64, mkexpr(b1),
16562                      binop(Iop_Add64,
16563                         binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
16564                         binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
16565       assign( z0, binop(Iop_Add64, mkexpr(b0),
16566                      binop(Iop_Add64,
16567                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
16568                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
16569 
16570       /* saturate-narrow to 32bit, and combine to V128 */
16571       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
16572                                          mkexpr(z1), mkexpr(z0)) );
16573       break;
16574    }
16575    case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274)
16576       DIP("vsum4shs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16577 
16578       /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */
16579       expand16Sx8( mkexpr(vA), &aEvn, &aOdd ); // (7,5...),(6,4...)
16580 
16581       /* break V128 to 4xI32's, sign-extending to I64's */
16582       breakV128to4x64S( mkexpr(aEvn), &a7, &a5, &a3, &a1 );
16583       breakV128to4x64S( mkexpr(aOdd), &a6, &a4, &a2, &a0 );
16584       breakV128to4x64S( mkexpr(vB),   &b3, &b2, &b1, &b0 );
16585 
16586       /* add lanes */
16587       assign( z3, binop(Iop_Add64, mkexpr(b3),
16588                         binop(Iop_Add64, mkexpr(a7), mkexpr(a6))));
16589       assign( z2, binop(Iop_Add64, mkexpr(b2),
16590                         binop(Iop_Add64, mkexpr(a5), mkexpr(a4))));
16591       assign( z1, binop(Iop_Add64, mkexpr(b1),
16592                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2))));
16593       assign( z0, binop(Iop_Add64, mkexpr(b0),
16594                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0))));
16595 
16596       /* saturate-narrow to 32bit, and combine to V128 */
16597       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
16598                                          mkexpr(z1), mkexpr(z0)) );
16599       break;
16600    }
16601    case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272)
16602       DIP("vsum2sws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16603 
16604       /* break V128 to 4xI32's, sign-extending to I64's */
16605       breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
16606       breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
16607 
16608       /* add lanes */
16609       assign( z2, binop(Iop_Add64, mkexpr(b2),
16610                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2))) );
16611       assign( z0, binop(Iop_Add64, mkexpr(b0),
16612                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0))) );
16613 
16614       /* saturate-narrow to 32bit, and combine to V128 */
16615       putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkexpr(z2),
16616                                          mkU64(0), mkexpr(z0)) );
16617       break;
16618    }
16619    case 0x788: { // vsumsws  (Sum SW Saturate, AV p271)
16620       DIP("vsumsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16621 
16622       /* break V128 to 4xI32's, sign-extending to I64's */
16623       breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
16624       breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
16625 
16626       /* add lanes */
16627       assign( z0, binop(Iop_Add64, mkexpr(b0),
16628                      binop(Iop_Add64,
16629                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
16630                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
16631 
16632       /* saturate-narrow to 32bit, and combine to V128 */
16633       putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkU64(0),
16634                                          mkU64(0), mkexpr(z0)) );
16635       break;
16636    }
16637    default:
16638       vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2);
16639       return False;
16640    }
16641    return True;
16642 }
16643 
16644 /*
16645   AltiVec Logic Instructions
16646 */
dis_av_logic(UInt theInstr)16647 static Bool dis_av_logic ( UInt theInstr )
16648 {
16649    /* VX-Form */
16650    UChar opc1    = ifieldOPC(theInstr);
16651    UChar vD_addr = ifieldRegDS(theInstr);
16652    UChar vA_addr = ifieldRegA(theInstr);
16653    UChar vB_addr = ifieldRegB(theInstr);
16654    UInt  opc2    = IFIELD( theInstr, 0, 11 );
16655 
16656    IRTemp vA = newTemp(Ity_V128);
16657    IRTemp vB = newTemp(Ity_V128);
16658    assign( vA, getVReg(vA_addr));
16659    assign( vB, getVReg(vB_addr));
16660 
16661    if (opc1 != 0x4) {
16662       vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n");
16663       return False;
16664    }
16665 
16666    switch (opc2) {
16667    case 0x404: // vand (And, AV p147)
16668       DIP("vand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16669       putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), mkexpr(vB)) );
16670       break;
16671 
16672    case 0x444: // vandc (And, AV p148)
16673       DIP("vandc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16674       putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA),
16675                               unop(Iop_NotV128, mkexpr(vB))) );
16676       break;
16677 
16678    case 0x484: // vor (Or, AV p217)
16679       DIP("vor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16680       putVReg( vD_addr, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB)) );
16681       break;
16682 
16683    case 0x4C4: // vxor (Xor, AV p282)
16684       DIP("vxor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16685       putVReg( vD_addr, binop(Iop_XorV128, mkexpr(vA), mkexpr(vB)) );
16686       break;
16687 
16688    case 0x504: // vnor (Nor, AV p216)
16689       DIP("vnor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16690       putVReg( vD_addr,
16691          unop(Iop_NotV128, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB))) );
16692       break;
16693 
16694    case 0x544: // vorc (vA Or'd with complement of vb)
16695       DIP("vorc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16696       putVReg( vD_addr, binop( Iop_OrV128,
16697                                mkexpr( vA ),
16698                                unop( Iop_NotV128, mkexpr( vB ) ) ) );
16699       break;
16700 
16701    case 0x584: // vnand (Nand)
16702       DIP("vnand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16703       putVReg( vD_addr, unop( Iop_NotV128,
16704                               binop(Iop_AndV128, mkexpr( vA ),
16705                               mkexpr( vB ) ) ) );
16706       break;
16707 
16708    case 0x684: // veqv (complemented XOr)
16709       DIP("veqv v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16710       putVReg( vD_addr, unop( Iop_NotV128,
16711                               binop( Iop_XorV128, mkexpr( vA ),
16712                               mkexpr( vB ) ) ) );
16713       break;
16714 
16715    default:
16716       vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2);
16717       return False;
16718    }
16719    return True;
16720 }
16721 
16722 /*
16723   AltiVec Compare Instructions
16724 */
dis_av_cmp(UInt theInstr)16725 static Bool dis_av_cmp ( UInt theInstr )
16726 {
16727    /* VXR-Form */
16728    UChar opc1     = ifieldOPC(theInstr);
16729    UChar vD_addr  = ifieldRegDS(theInstr);
16730    UChar vA_addr  = ifieldRegA(theInstr);
16731    UChar vB_addr  = ifieldRegB(theInstr);
16732    UChar flag_rC  = ifieldBIT10(theInstr);
16733    UInt  opc2     = IFIELD( theInstr, 0, 10 );
16734 
16735    IRTemp vA = newTemp(Ity_V128);
16736    IRTemp vB = newTemp(Ity_V128);
16737    IRTemp vD = newTemp(Ity_V128);
16738    assign( vA, getVReg(vA_addr));
16739    assign( vB, getVReg(vB_addr));
16740 
16741    if (opc1 != 0x4) {
16742       vex_printf("dis_av_cmp(ppc)(instr)\n");
16743       return False;
16744    }
16745 
16746    switch (opc2) {
16747    case 0x006: // vcmpequb (Compare Equal-to Unsigned B, AV p160)
16748       DIP("vcmpequb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16749                                       vD_addr, vA_addr, vB_addr);
16750       assign( vD, binop(Iop_CmpEQ8x16, mkexpr(vA), mkexpr(vB)) );
16751       break;
16752 
16753    case 0x046: // vcmpequh (Compare Equal-to Unsigned HW, AV p161)
16754       DIP("vcmpequh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16755                                       vD_addr, vA_addr, vB_addr);
16756       assign( vD, binop(Iop_CmpEQ16x8, mkexpr(vA), mkexpr(vB)) );
16757       break;
16758 
16759    case 0x086: // vcmpequw (Compare Equal-to Unsigned W, AV p162)
16760       DIP("vcmpequw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16761                                       vD_addr, vA_addr, vB_addr);
16762       assign( vD, binop(Iop_CmpEQ32x4, mkexpr(vA), mkexpr(vB)) );
16763       break;
16764 
16765    case 0x0C7: // vcmpequd (Compare Equal-to Unsigned Doubleword)
16766       DIP("vcmpequd%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16767                                       vD_addr, vA_addr, vB_addr);
16768       assign( vD, binop(Iop_CmpEQ64x2, mkexpr(vA), mkexpr(vB)) );
16769       break;
16770 
16771    case 0x206: // vcmpgtub (Compare Greater-than Unsigned B, AV p168)
16772       DIP("vcmpgtub%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16773                                       vD_addr, vA_addr, vB_addr);
16774       assign( vD, binop(Iop_CmpGT8Ux16, mkexpr(vA), mkexpr(vB)) );
16775       break;
16776 
16777    case 0x246: // vcmpgtuh (Compare Greater-than Unsigned HW, AV p169)
16778       DIP("vcmpgtuh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16779                                       vD_addr, vA_addr, vB_addr);
16780       assign( vD, binop(Iop_CmpGT16Ux8, mkexpr(vA), mkexpr(vB)) );
16781       break;
16782 
16783    case 0x286: // vcmpgtuw (Compare Greater-than Unsigned W, AV p170)
16784       DIP("vcmpgtuw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16785                                        vD_addr, vA_addr, vB_addr);
16786       assign( vD, binop(Iop_CmpGT32Ux4, mkexpr(vA), mkexpr(vB)) );
16787       break;
16788 
16789    case 0x2C7: // vcmpgtud (Compare Greater-than Unsigned double)
16790       DIP("vcmpgtud%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16791                                       vD_addr, vA_addr, vB_addr);
16792       assign( vD, binop(Iop_CmpGT64Ux2, mkexpr(vA), mkexpr(vB)) );
16793       break;
16794 
16795    case 0x306: // vcmpgtsb (Compare Greater-than Signed B, AV p165)
16796       DIP("vcmpgtsb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16797                                        vD_addr, vA_addr, vB_addr);
16798       assign( vD, binop(Iop_CmpGT8Sx16, mkexpr(vA), mkexpr(vB)) );
16799       break;
16800 
16801    case 0x346: // vcmpgtsh (Compare Greater-than Signed HW, AV p166)
16802       DIP("vcmpgtsh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16803                                       vD_addr, vA_addr, vB_addr);
16804       assign( vD, binop(Iop_CmpGT16Sx8, mkexpr(vA), mkexpr(vB)) );
16805       break;
16806 
16807    case 0x386: // vcmpgtsw (Compare Greater-than Signed W, AV p167)
16808       DIP("vcmpgtsw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16809                                       vD_addr, vA_addr, vB_addr);
16810       assign( vD, binop(Iop_CmpGT32Sx4, mkexpr(vA), mkexpr(vB)) );
16811       break;
16812 
16813    case 0x3C7: // vcmpgtsd (Compare Greater-than Signed double)
16814       DIP("vcmpgtsd%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
16815                                       vD_addr, vA_addr, vB_addr);
16816       assign( vD, binop(Iop_CmpGT64Sx2, mkexpr(vA), mkexpr(vB)) );
16817       break;
16818 
16819    default:
16820       vex_printf("dis_av_cmp(ppc)(opc2)\n");
16821       return False;
16822    }
16823 
16824    putVReg( vD_addr, mkexpr(vD) );
16825 
16826    if (flag_rC) {
16827       set_AV_CR6( mkexpr(vD), True );
16828    }
16829    return True;
16830 }
16831 
16832 /*
16833   AltiVec Multiply-Sum Instructions
16834 */
dis_av_multarith(UInt theInstr)16835 static Bool dis_av_multarith ( UInt theInstr )
16836 {
16837    /* VA-Form */
16838    UChar opc1     = ifieldOPC(theInstr);
16839    UChar vD_addr  = ifieldRegDS(theInstr);
16840    UChar vA_addr  = ifieldRegA(theInstr);
16841    UChar vB_addr  = ifieldRegB(theInstr);
16842    UChar vC_addr  = ifieldRegC(theInstr);
16843    UChar opc2     = toUChar( IFIELD( theInstr, 0, 6 ) );
16844 
16845    IRTemp vA    = newTemp(Ity_V128);
16846    IRTemp vB    = newTemp(Ity_V128);
16847    IRTemp vC    = newTemp(Ity_V128);
16848    IRTemp zeros = newTemp(Ity_V128);
16849    IRTemp aLo   = newTemp(Ity_V128);
16850    IRTemp bLo   = newTemp(Ity_V128);
16851    IRTemp cLo   = newTemp(Ity_V128);
16852    IRTemp zLo   = newTemp(Ity_V128);
16853    IRTemp aHi   = newTemp(Ity_V128);
16854    IRTemp bHi   = newTemp(Ity_V128);
16855    IRTemp cHi   = newTemp(Ity_V128);
16856    IRTemp zHi   = newTemp(Ity_V128);
16857    IRTemp abEvn = newTemp(Ity_V128);
16858    IRTemp abOdd = newTemp(Ity_V128);
16859    IRTemp z3    = newTemp(Ity_I64);
16860    IRTemp z2    = newTemp(Ity_I64);
16861    IRTemp z1    = newTemp(Ity_I64);
16862    IRTemp z0    = newTemp(Ity_I64);
16863    IRTemp ab7, ab6, ab5, ab4, ab3, ab2, ab1, ab0;
16864    IRTemp c3, c2, c1, c0;
16865 
16866    ab7 = ab6 = ab5 = ab4 = ab3 = ab2 = ab1 = ab0 = IRTemp_INVALID;
16867    c3 = c2 = c1 = c0 = IRTemp_INVALID;
16868 
16869    assign( vA, getVReg(vA_addr));
16870    assign( vB, getVReg(vB_addr));
16871    assign( vC, getVReg(vC_addr));
16872    assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
16873 
16874    if (opc1 != 0x4) {
16875       vex_printf("dis_av_multarith(ppc)(instr)\n");
16876       return False;
16877    }
16878 
16879    switch (opc2) {
16880    /* Multiply-Add */
16881    case 0x20: { // vmhaddshs (Mult Hi, Add Signed HW Saturate, AV p185)
16882       IRTemp cSigns = newTemp(Ity_V128);
16883       DIP("vmhaddshs v%d,v%d,v%d,v%d\n",
16884           vD_addr, vA_addr, vB_addr, vC_addr);
16885       assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)));
16886       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
16887       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
16888       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
16889       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
16890       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
16891       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
16892 
16893       assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
16894                          binop(Iop_SarN32x4,
16895                                binop(Iop_MullEven16Sx8,
16896                                      mkexpr(aLo), mkexpr(bLo)),
16897                                mkU8(15))) );
16898 
16899       assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
16900                          binop(Iop_SarN32x4,
16901                                binop(Iop_MullEven16Sx8,
16902                                      mkexpr(aHi), mkexpr(bHi)),
16903                                mkU8(15))) );
16904 
16905       putVReg( vD_addr,
16906                binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
16907       break;
16908    }
16909    case 0x21: { // vmhraddshs (Mult High Round, Add Signed HW Saturate, AV p186)
16910       IRTemp zKonst = newTemp(Ity_V128);
16911       IRTemp cSigns = newTemp(Ity_V128);
16912       DIP("vmhraddshs v%d,v%d,v%d,v%d\n",
16913           vD_addr, vA_addr, vB_addr, vC_addr);
16914       assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)) );
16915       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
16916       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
16917       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
16918       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
16919       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
16920       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
16921 
16922       /* shifting our const avoids store/load version of Dup */
16923       assign( zKonst, binop(Iop_ShlN32x4, unop(Iop_Dup32x4, mkU32(0x1)),
16924                             mkU8(14)) );
16925 
16926       assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
16927                          binop(Iop_SarN32x4,
16928                                binop(Iop_Add32x4, mkexpr(zKonst),
16929                                      binop(Iop_MullEven16Sx8,
16930                                            mkexpr(aLo), mkexpr(bLo))),
16931                                mkU8(15))) );
16932 
16933       assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
16934                          binop(Iop_SarN32x4,
16935                                binop(Iop_Add32x4, mkexpr(zKonst),
16936                                      binop(Iop_MullEven16Sx8,
16937                                            mkexpr(aHi), mkexpr(bHi))),
16938                                mkU8(15))) );
16939 
16940       putVReg( vD_addr,
16941                binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
16942       break;
16943    }
16944    case 0x22: { // vmladduhm (Mult Low, Add Unsigned HW Modulo, AV p194)
16945       DIP("vmladduhm v%d,v%d,v%d,v%d\n",
16946           vD_addr, vA_addr, vB_addr, vC_addr);
16947       assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
16948       assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
16949       assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vC)));
16950       assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
16951       assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
16952       assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vC)));
16953       assign(zLo, binop(Iop_Add32x4,
16954                      binop(Iop_MullEven16Ux8, mkexpr(aLo), mkexpr(bLo)),
16955                      mkexpr(cLo)) );
16956       assign(zHi, binop(Iop_Add32x4,
16957                      binop(Iop_MullEven16Ux8, mkexpr(aHi), mkexpr(bHi)),
16958                      mkexpr(cHi)));
16959       putVReg( vD_addr,
16960                binop(Iop_NarrowBin32to16x8, mkexpr(zHi), mkexpr(zLo)) );
16961       break;
16962    }
16963 
16964 
16965    /* Multiply-Sum */
16966    case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204)
16967       IRTemp abEE, abEO, abOE, abOO;
16968       abEE = abEO = abOE = abOO = IRTemp_INVALID;
16969       DIP("vmsumubm v%d,v%d,v%d,v%d\n",
16970           vD_addr, vA_addr, vB_addr, vC_addr);
16971 
16972       /* multiply vA,vB (unsigned, widening) */
16973       assign( abEvn, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
16974       assign( abOdd, binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)) );
16975 
16976       /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */
16977       expand16Ux8( mkexpr(abEvn), &abEE, &abEO );
16978       expand16Ux8( mkexpr(abOdd), &abOE, &abOO );
16979 
16980       putVReg( vD_addr,
16981          binop(Iop_Add32x4, mkexpr(vC),
16982                binop(Iop_Add32x4,
16983                      binop(Iop_Add32x4, mkexpr(abEE), mkexpr(abEO)),
16984                      binop(Iop_Add32x4, mkexpr(abOE), mkexpr(abOO)))) );
16985       break;
16986    }
16987    case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201)
16988       IRTemp aEvn, aOdd, bEvn, bOdd;
16989       IRTemp abEE = newTemp(Ity_V128);
16990       IRTemp abEO = newTemp(Ity_V128);
16991       IRTemp abOE = newTemp(Ity_V128);
16992       IRTemp abOO = newTemp(Ity_V128);
16993       aEvn = aOdd = bEvn = bOdd = IRTemp_INVALID;
16994       DIP("vmsummbm v%d,v%d,v%d,v%d\n",
16995           vD_addr, vA_addr, vB_addr, vC_addr);
16996 
16997       /* sign-extend vA, zero-extend vB, for mixed-sign multiply
16998          (separating out adjacent lanes to different vectors) */
16999       expand8Sx16( mkexpr(vA), &aEvn, &aOdd );
17000       expand8Ux16( mkexpr(vB), &bEvn, &bOdd );
17001 
17002       /* multiply vA, vB, again separating adjacent lanes */
17003       assign( abEE, MK_Iop_MullOdd16Sx8( mkexpr(aEvn), mkexpr(bEvn) ));
17004       assign( abEO, binop(Iop_MullEven16Sx8, mkexpr(aEvn), mkexpr(bEvn)) );
17005       assign( abOE, MK_Iop_MullOdd16Sx8( mkexpr(aOdd), mkexpr(bOdd) ));
17006       assign( abOO, binop(Iop_MullEven16Sx8, mkexpr(aOdd), mkexpr(bOdd)) );
17007 
17008       /* add results together, + vC */
17009       putVReg( vD_addr,
17010          binop(Iop_QAdd32Sx4, mkexpr(vC),
17011                binop(Iop_QAdd32Sx4,
17012                      binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)),
17013                      binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)))) );
17014       break;
17015    }
17016    case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205)
17017       DIP("vmsumuhm v%d,v%d,v%d,v%d\n",
17018           vD_addr, vA_addr, vB_addr, vC_addr);
17019       assign( abEvn, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
17020       assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
17021       putVReg( vD_addr,
17022          binop(Iop_Add32x4, mkexpr(vC),
17023                binop(Iop_Add32x4, mkexpr(abEvn), mkexpr(abOdd))) );
17024       break;
17025    }
17026    case 0x27: { // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206)
17027       DIP("vmsumuhs v%d,v%d,v%d,v%d\n",
17028           vD_addr, vA_addr, vB_addr, vC_addr);
17029       /* widening multiply, separating lanes */
17030       assign( abEvn, MK_Iop_MullOdd16Ux8(mkexpr(vA), mkexpr(vB) ));
17031       assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
17032 
17033       /* break V128 to 4xI32's, zero-extending to I64's */
17034       breakV128to4x64U( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
17035       breakV128to4x64U( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
17036       breakV128to4x64U( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
17037 
17038       /* add lanes */
17039       assign( z3, binop(Iop_Add64, mkexpr(c3),
17040                         binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
17041       assign( z2, binop(Iop_Add64, mkexpr(c2),
17042                         binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
17043       assign( z1, binop(Iop_Add64, mkexpr(c1),
17044                         binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
17045       assign( z0, binop(Iop_Add64, mkexpr(c0),
17046                         binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
17047 
17048       /* saturate-narrow to 32bit, and combine to V128 */
17049       putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
17050                                          mkexpr(z1), mkexpr(z0)) );
17051 
17052       break;
17053    }
17054    case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202)
17055       DIP("vmsumshm v%d,v%d,v%d,v%d\n",
17056           vD_addr, vA_addr, vB_addr, vC_addr);
17057       assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
17058       assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
17059       putVReg( vD_addr,
17060          binop(Iop_Add32x4, mkexpr(vC),
17061                binop(Iop_Add32x4, mkexpr(abOdd), mkexpr(abEvn))) );
17062       break;
17063    }
17064    case 0x29: { // vmsumshs (Multiply Sum Signed HW Saturate, AV p203)
17065       DIP("vmsumshs v%d,v%d,v%d,v%d\n",
17066           vD_addr, vA_addr, vB_addr, vC_addr);
17067       /* widening multiply, separating lanes */
17068       assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
17069       assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
17070 
17071       /* break V128 to 4xI32's, sign-extending to I64's */
17072       breakV128to4x64S( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
17073       breakV128to4x64S( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
17074       breakV128to4x64S( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
17075 
17076       /* add lanes */
17077       assign( z3, binop(Iop_Add64, mkexpr(c3),
17078                         binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
17079       assign( z2, binop(Iop_Add64, mkexpr(c2),
17080                         binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
17081       assign( z1, binop(Iop_Add64, mkexpr(c1),
17082                         binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
17083       assign( z0, binop(Iop_Add64, mkexpr(c0),
17084                         binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
17085 
17086       /* saturate-narrow to 32bit, and combine to V128 */
17087       putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
17088                                          mkexpr(z1), mkexpr(z0)) );
17089       break;
17090    }
17091    default:
17092       vex_printf("dis_av_multarith(ppc)(opc2)\n");
17093       return False;
17094    }
17095    return True;
17096 }
17097 
17098 /*
17099   AltiVec Polynomial Multiply-Sum Instructions
17100 */
dis_av_polymultarith(UInt theInstr)17101 static Bool dis_av_polymultarith ( UInt theInstr )
17102 {
17103    /* VA-Form */
17104    UChar opc1     = ifieldOPC(theInstr);
17105    UChar vD_addr  = ifieldRegDS(theInstr);
17106    UChar vA_addr  = ifieldRegA(theInstr);
17107    UChar vB_addr  = ifieldRegB(theInstr);
17108    UChar vC_addr  = ifieldRegC(theInstr);
17109    UInt  opc2     = IFIELD(theInstr, 0, 11);
17110    IRTemp vA    = newTemp(Ity_V128);
17111    IRTemp vB    = newTemp(Ity_V128);
17112    IRTemp vC    = newTemp(Ity_V128);
17113 
17114    assign( vA, getVReg(vA_addr));
17115    assign( vB, getVReg(vB_addr));
17116    assign( vC, getVReg(vC_addr));
17117 
17118    if (opc1 != 0x4) {
17119       vex_printf("dis_av_polymultarith(ppc)(instr)\n");
17120       return False;
17121    }
17122 
17123    switch (opc2) {
17124       /* Polynomial Multiply-Add */
17125       case 0x408:  // vpmsumb   Vector Polynomial Multipy-sum Byte
17126          DIP("vpmsumb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17127          putVReg( vD_addr, binop(Iop_PolynomialMulAdd8x16,
17128                                  mkexpr(vA), mkexpr(vB)) );
17129          break;
17130       case 0x448:  // vpmsumd   Vector Polynomial Multipy-sum Double Word
17131          DIP("vpmsumd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17132          putVReg( vD_addr, binop(Iop_PolynomialMulAdd64x2,
17133                                  mkexpr(vA), mkexpr(vB)) );
17134          break;
17135       case 0x488:  // vpmsumw   Vector Polynomial Multipy-sum Word
17136          DIP("vpmsumw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17137          putVReg( vD_addr, binop(Iop_PolynomialMulAdd32x4,
17138                                  mkexpr(vA), mkexpr(vB)) );
17139          break;
17140       case 0x4C8:  // vpmsumh   Vector Polynomial Multipy-sum Half Word
17141          DIP("vpmsumh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17142          putVReg( vD_addr, binop(Iop_PolynomialMulAdd16x8,
17143                                  mkexpr(vA), mkexpr(vB)) );
17144          break;
17145       default:
17146          vex_printf("dis_av_polymultarith(ppc)(opc2=0x%x)\n", opc2);
17147          return False;
17148    }
17149    return True;
17150 }
17151 
17152 /*
17153   AltiVec Shift/Rotate Instructions
17154 */
dis_av_shift(UInt theInstr)17155 static Bool dis_av_shift ( UInt theInstr )
17156 {
17157    /* VX-Form */
17158    UChar opc1    = ifieldOPC(theInstr);
17159    UChar vD_addr = ifieldRegDS(theInstr);
17160    UChar vA_addr = ifieldRegA(theInstr);
17161    UChar vB_addr = ifieldRegB(theInstr);
17162    UInt  opc2    = IFIELD( theInstr, 0, 11 );
17163 
17164    IRTemp vA = newTemp(Ity_V128);
17165    IRTemp vB = newTemp(Ity_V128);
17166    assign( vA, getVReg(vA_addr));
17167    assign( vB, getVReg(vB_addr));
17168 
17169    if (opc1 != 0x4){
17170       vex_printf("dis_av_shift(ppc)(instr)\n");
17171       return False;
17172    }
17173 
17174    switch (opc2) {
17175    /* Rotate */
17176    case 0x004: // vrlb (Rotate Left Integer B, AV p234)
17177       DIP("vrlb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17178       putVReg( vD_addr, binop(Iop_Rol8x16, mkexpr(vA), mkexpr(vB)) );
17179       break;
17180 
17181    case 0x044: // vrlh (Rotate Left Integer HW, AV p235)
17182       DIP("vrlh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17183       putVReg( vD_addr, binop(Iop_Rol16x8, mkexpr(vA), mkexpr(vB)) );
17184       break;
17185 
17186    case 0x084: // vrlw (Rotate Left Integer W, AV p236)
17187       DIP("vrlw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17188       putVReg( vD_addr, binop(Iop_Rol32x4, mkexpr(vA), mkexpr(vB)) );
17189       break;
17190 
17191    case 0x0C4: // vrld (Rotate Left Integer Double Word)
17192       DIP("vrld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17193       putVReg( vD_addr, binop(Iop_Rol64x2, mkexpr(vA), mkexpr(vB)) );
17194       break;
17195 
17196 
17197    /* Shift Left */
17198    case 0x104: // vslb (Shift Left Integer B, AV p240)
17199       DIP("vslb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17200       putVReg( vD_addr, binop(Iop_Shl8x16, mkexpr(vA), mkexpr(vB)) );
17201       break;
17202 
17203    case 0x144: // vslh (Shift Left Integer HW, AV p242)
17204       DIP("vslh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17205       putVReg( vD_addr, binop(Iop_Shl16x8, mkexpr(vA), mkexpr(vB)) );
17206       break;
17207 
17208    case 0x184: // vslw (Shift Left Integer W, AV p244)
17209       DIP("vslw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17210       putVReg( vD_addr, binop(Iop_Shl32x4, mkexpr(vA), mkexpr(vB)) );
17211       break;
17212 
17213    case 0x5C4: // vsld (Shift Left Integer Double Word)
17214       DIP("vsld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17215       putVReg( vD_addr, binop(Iop_Shl64x2, mkexpr(vA), mkexpr(vB)) );
17216       break;
17217 
17218    case 0x1C4: { // vsl (Shift Left, AV p239)
17219       IRTemp sh = newTemp(Ity_I8);
17220       DIP("vsl v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17221       assign( sh, binop(Iop_And8, mkU8(0x7),
17222                         unop(Iop_32to8,
17223                              unop(Iop_V128to32, mkexpr(vB)))) );
17224       putVReg( vD_addr,
17225                binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
17226       break;
17227    }
17228    case 0x40C: { // vslo (Shift Left by Octet, AV p243)
17229       IRTemp sh = newTemp(Ity_I8);
17230       DIP("vslo v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17231       assign( sh, binop(Iop_And8, mkU8(0x78),
17232                         unop(Iop_32to8,
17233                              unop(Iop_V128to32, mkexpr(vB)))) );
17234       putVReg( vD_addr,
17235                binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
17236       break;
17237    }
17238 
17239 
17240    /* Shift Right */
17241    case 0x204: // vsrb (Shift Right B, AV p256)
17242       DIP("vsrb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17243       putVReg( vD_addr, binop(Iop_Shr8x16, mkexpr(vA), mkexpr(vB)) );
17244       break;
17245 
17246    case 0x244: // vsrh (Shift Right HW, AV p257)
17247       DIP("vsrh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17248       putVReg( vD_addr, binop(Iop_Shr16x8, mkexpr(vA), mkexpr(vB)) );
17249       break;
17250 
17251    case 0x284: // vsrw (Shift Right W, AV p259)
17252       DIP("vsrw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17253       putVReg( vD_addr, binop(Iop_Shr32x4, mkexpr(vA), mkexpr(vB)) );
17254       break;
17255 
17256    case 0x2C4: { // vsr (Shift Right, AV p251)
17257       IRTemp sh = newTemp(Ity_I8);
17258       DIP("vsr v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17259       assign( sh, binop(Iop_And8, mkU8(0x7),
17260                         unop(Iop_32to8,
17261                              unop(Iop_V128to32, mkexpr(vB)))) );
17262       putVReg( vD_addr,
17263                binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
17264       break;
17265    }
17266    case 0x304: // vsrab (Shift Right Alg B, AV p253)
17267       DIP("vsrab v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17268       putVReg( vD_addr, binop(Iop_Sar8x16, mkexpr(vA), mkexpr(vB)) );
17269       break;
17270 
17271    case 0x344: // vsrah (Shift Right Alg HW, AV p254)
17272       DIP("vsrah v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17273       putVReg( vD_addr, binop(Iop_Sar16x8, mkexpr(vA), mkexpr(vB)) );
17274       break;
17275 
17276    case 0x384: // vsraw (Shift Right Alg W, AV p255)
17277       DIP("vsraw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17278       putVReg( vD_addr, binop(Iop_Sar32x4, mkexpr(vA), mkexpr(vB)) );
17279       break;
17280 
17281    case 0x3C4: // vsrad (Shift Right Alg Double Word)
17282       DIP("vsrad v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17283       putVReg( vD_addr, binop(Iop_Sar64x2, mkexpr(vA), mkexpr(vB)) );
17284       break;
17285 
17286    case 0x44C: { // vsro (Shift Right by Octet, AV p258)
17287       IRTemp sh = newTemp(Ity_I8);
17288       DIP("vsro v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17289       assign( sh, binop(Iop_And8, mkU8(0x78),
17290                         unop(Iop_32to8,
17291                              unop(Iop_V128to32, mkexpr(vB)))) );
17292       putVReg( vD_addr,
17293                binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
17294       break;
17295    }
17296 
17297    case 0x6C4: // vsrd (Shift Right Double Word)
17298       DIP("vsrd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17299       putVReg( vD_addr, binop(Iop_Shr64x2, mkexpr(vA), mkexpr(vB)) );
17300       break;
17301 
17302 
17303    default:
17304       vex_printf("dis_av_shift(ppc)(opc2)\n");
17305       return False;
17306    }
17307    return True;
17308 }
17309 
17310 /*
17311   AltiVec Permute Instructions
17312 */
dis_av_permute(UInt theInstr)17313 static Bool dis_av_permute ( UInt theInstr )
17314 {
17315    /* VA-Form, VX-Form */
17316    UChar opc1      = ifieldOPC(theInstr);
17317    UChar vD_addr   = ifieldRegDS(theInstr);
17318    UChar vA_addr   = ifieldRegA(theInstr);
17319    UChar UIMM_5    = vA_addr;
17320    UChar vB_addr   = ifieldRegB(theInstr);
17321    UChar vC_addr   = ifieldRegC(theInstr);
17322    UChar b10       = ifieldBIT10(theInstr);
17323    UChar SHB_uimm4 = toUChar( IFIELD( theInstr, 6, 4 ) );
17324    UInt  opc2      = toUChar( IFIELD( theInstr, 0, 6 ) );
17325 
17326    UChar SIMM_8 = extend_s_5to8(UIMM_5);
17327 
17328    IRTemp vA = newTemp(Ity_V128);
17329    IRTemp vB = newTemp(Ity_V128);
17330    IRTemp vC = newTemp(Ity_V128);
17331    assign( vA, getVReg(vA_addr));
17332    assign( vB, getVReg(vB_addr));
17333    assign( vC, getVReg(vC_addr));
17334 
17335    if (opc1 != 0x4) {
17336       vex_printf("dis_av_permute(ppc)(instr)\n");
17337       return False;
17338    }
17339 
17340    switch (opc2) {
17341    case 0x2A: // vsel (Conditional Select, AV p238)
17342       DIP("vsel v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
17343       /* vD = (vA & ~vC) | (vB & vC) */
17344       putVReg( vD_addr, binop(Iop_OrV128,
17345          binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
17346          binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
17347       return True;
17348 
17349    case 0x2B: { // vperm (Permute, AV p218)
17350       /* limited to two args for IR, so have to play games... */
17351       IRTemp a_perm  = newTemp(Ity_V128);
17352       IRTemp b_perm  = newTemp(Ity_V128);
17353       IRTemp mask    = newTemp(Ity_V128);
17354       IRTemp vC_andF = newTemp(Ity_V128);
17355       DIP("vperm v%d,v%d,v%d,v%d\n",
17356           vD_addr, vA_addr, vB_addr, vC_addr);
17357       /* Limit the Perm8x16 steering values to 0 .. 15 as that is what
17358          IR specifies, and also to hide irrelevant bits from
17359          memcheck */
17360       assign( vC_andF,
17361               binop(Iop_AndV128, mkexpr(vC),
17362                                  unop(Iop_Dup8x16, mkU8(0xF))) );
17363       assign( a_perm,
17364               binop(Iop_Perm8x16, mkexpr(vA), mkexpr(vC_andF)) );
17365       assign( b_perm,
17366               binop(Iop_Perm8x16, mkexpr(vB), mkexpr(vC_andF)) );
17367       // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0
17368       assign( mask, binop(Iop_SarN8x16,
17369                           binop(Iop_ShlN8x16, mkexpr(vC), mkU8(3)),
17370                           mkU8(7)) );
17371       // dst = (a & ~mask) | (b & mask)
17372       putVReg( vD_addr, binop(Iop_OrV128,
17373                               binop(Iop_AndV128, mkexpr(a_perm),
17374                                     unop(Iop_NotV128, mkexpr(mask))),
17375                               binop(Iop_AndV128, mkexpr(b_perm),
17376                                     mkexpr(mask))) );
17377       return True;
17378    }
17379    case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241)
17380       if (b10 != 0) {
17381          vex_printf("dis_av_permute(ppc)(vsldoi)\n");
17382          return False;
17383       }
17384       DIP("vsldoi v%d,v%d,v%d,%d\n",
17385           vD_addr, vA_addr, vB_addr, SHB_uimm4);
17386       if (SHB_uimm4 == 0)
17387          putVReg( vD_addr, mkexpr(vA) );
17388       else
17389          putVReg( vD_addr,
17390             binop(Iop_OrV128,
17391                   binop(Iop_ShlV128, mkexpr(vA), mkU8(SHB_uimm4*8)),
17392                   binop(Iop_ShrV128, mkexpr(vB), mkU8((16-SHB_uimm4)*8))) );
17393       return True;
17394    case 0x2D: {  // vpermxor (Vector Permute and Exclusive-OR)
17395       IRTemp a_perm  = newTemp(Ity_V128);
17396       IRTemp b_perm  = newTemp(Ity_V128);
17397       IRTemp vrc_a   = newTemp(Ity_V128);
17398       IRTemp vrc_b   = newTemp(Ity_V128);
17399 
17400       /* IBM index  is 0:7, Change index value to index 7:0 */
17401       assign( vrc_b, binop( Iop_AndV128, mkexpr( vC ),
17402                             unop( Iop_Dup8x16, mkU8( 0xF ) ) ) );
17403       assign( vrc_a, binop( Iop_ShrV128,
17404                             binop( Iop_AndV128, mkexpr( vC ),
17405                                    unop( Iop_Dup8x16, mkU8( 0xF0 ) ) ),
17406                             mkU8 ( 4 ) ) );
17407       assign( a_perm, binop( Iop_Perm8x16, mkexpr( vA ), mkexpr( vrc_a ) ) );
17408       assign( b_perm, binop( Iop_Perm8x16, mkexpr( vB ), mkexpr( vrc_b ) ) );
17409       putVReg( vD_addr, binop( Iop_XorV128,
17410                                mkexpr( a_perm ), mkexpr( b_perm) ) );
17411       return True;
17412    }
17413    default:
17414      break; // Fall through...
17415    }
17416 
17417    opc2 = IFIELD( theInstr, 0, 11 );
17418    switch (opc2) {
17419 
17420    /* Merge */
17421    case 0x00C: // vmrghb (Merge High B, AV p195)
17422       DIP("vmrghb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17423       putVReg( vD_addr,
17424                binop(Iop_InterleaveHI8x16, mkexpr(vA), mkexpr(vB)) );
17425       break;
17426 
17427    case 0x04C: // vmrghh (Merge High HW, AV p196)
17428       DIP("vmrghh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17429       putVReg( vD_addr,
17430                binop(Iop_InterleaveHI16x8, mkexpr(vA), mkexpr(vB)) );
17431       break;
17432 
17433    case 0x08C: // vmrghw (Merge High W, AV p197)
17434       DIP("vmrghw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17435       putVReg( vD_addr,
17436                binop(Iop_InterleaveHI32x4, mkexpr(vA), mkexpr(vB)) );
17437       break;
17438 
17439    case 0x10C: // vmrglb (Merge Low B, AV p198)
17440       DIP("vmrglb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17441       putVReg( vD_addr,
17442                binop(Iop_InterleaveLO8x16, mkexpr(vA), mkexpr(vB)) );
17443       break;
17444 
17445    case 0x14C: // vmrglh (Merge Low HW, AV p199)
17446       DIP("vmrglh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17447       putVReg( vD_addr,
17448                binop(Iop_InterleaveLO16x8, mkexpr(vA), mkexpr(vB)) );
17449       break;
17450 
17451    case 0x18C: // vmrglw (Merge Low W, AV p200)
17452       DIP("vmrglw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17453       putVReg( vD_addr,
17454                binop(Iop_InterleaveLO32x4, mkexpr(vA), mkexpr(vB)) );
17455       break;
17456 
17457 
17458    /* Splat */
17459    case 0x20C: { // vspltb (Splat Byte, AV p245)
17460       /* vD = Dup8x16( vB[UIMM_5] ) */
17461       UChar sh_uimm = (15 - (UIMM_5 & 15)) * 8;
17462       DIP("vspltb v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
17463       putVReg( vD_addr, unop(Iop_Dup8x16,
17464            unop(Iop_32to8, unop(Iop_V128to32,
17465                 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
17466       break;
17467    }
17468    case 0x24C: { // vsplth (Splat Half Word, AV p246)
17469       UChar sh_uimm = (7 - (UIMM_5 & 7)) * 16;
17470       DIP("vsplth v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
17471       putVReg( vD_addr, unop(Iop_Dup16x8,
17472            unop(Iop_32to16, unop(Iop_V128to32,
17473                 binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
17474       break;
17475    }
17476    case 0x28C: { // vspltw (Splat Word, AV p250)
17477       /* vD = Dup32x4( vB[UIMM_5] ) */
17478       UChar sh_uimm = (3 - (UIMM_5 & 3)) * 32;
17479       DIP("vspltw v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
17480       putVReg( vD_addr, unop(Iop_Dup32x4,
17481          unop(Iop_V128to32,
17482               binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm)))) );
17483       break;
17484    }
17485    case 0x30C: // vspltisb (Splat Immediate Signed B, AV p247)
17486       DIP("vspltisb v%d,%d\n", vD_addr, (Char)SIMM_8);
17487       putVReg( vD_addr, unop(Iop_Dup8x16, mkU8(SIMM_8)) );
17488       break;
17489 
17490    case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248)
17491       DIP("vspltish v%d,%d\n", vD_addr, (Char)SIMM_8);
17492       putVReg( vD_addr,
17493                unop(Iop_Dup16x8, mkU16(extend_s_8to32(SIMM_8))) );
17494       break;
17495 
17496    case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249)
17497       DIP("vspltisw v%d,%d\n", vD_addr, (Char)SIMM_8);
17498       putVReg( vD_addr,
17499                unop(Iop_Dup32x4, mkU32(extend_s_8to32(SIMM_8))) );
17500       break;
17501 
17502    case 0x68C: // vmrgow (Merge Odd Word)
17503      DIP("vmrgow v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17504       /*   VD[0] <- VA[1]
17505            VD[1] <- VB[1]
17506            VD[2] <- VA[3]
17507            VD[3] <- VB[3]
17508       */
17509       putVReg( vD_addr,
17510                binop(Iop_CatOddLanes32x4, mkexpr(vA), mkexpr(vB) ) );
17511       break;
17512 
17513    case 0x78C: // vmrgew (Merge Even Word)
17514       DIP("vmrgew v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17515       /*   VD[0] <- VA[0]
17516            VD[1] <- VB[0]
17517            VD[2] <- VA[2]
17518            VD[3] <- VB[2]
17519       */
17520       putVReg( vD_addr,
17521                binop(Iop_CatEvenLanes32x4, mkexpr(vA), mkexpr(vB) ) );
17522       break;
17523 
17524    default:
17525       vex_printf("dis_av_permute(ppc)(opc2)\n");
17526       return False;
17527    }
17528    return True;
17529 }
17530 
17531 /*
17532   AltiVec Pack/Unpack Instructions
17533 */
dis_av_pack(UInt theInstr)17534 static Bool dis_av_pack ( UInt theInstr )
17535 {
17536    /* VX-Form */
17537    UChar opc1     = ifieldOPC(theInstr);
17538    UChar vD_addr  = ifieldRegDS(theInstr);
17539    UChar vA_addr  = ifieldRegA(theInstr);
17540    UChar vB_addr  = ifieldRegB(theInstr);
17541    UInt  opc2     = IFIELD( theInstr, 0, 11 );
17542 
17543    IRTemp signs = IRTemp_INVALID;
17544    IRTemp zeros = IRTemp_INVALID;
17545    IRTemp vA    = newTemp(Ity_V128);
17546    IRTemp vB    = newTemp(Ity_V128);
17547    assign( vA, getVReg(vA_addr));
17548    assign( vB, getVReg(vB_addr));
17549 
17550    if (opc1 != 0x4) {
17551       vex_printf("dis_av_pack(ppc)(instr)\n");
17552       return False;
17553    }
17554    switch (opc2) {
17555    /* Packing */
17556    case 0x00E: // vpkuhum (Pack Unsigned HW Unsigned Modulo, AV p224)
17557       DIP("vpkuhum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17558       putVReg( vD_addr,
17559                binop(Iop_NarrowBin16to8x16, mkexpr(vA), mkexpr(vB)) );
17560       return True;
17561 
17562    case 0x04E: // vpkuwum (Pack Unsigned W Unsigned Modulo, AV p226)
17563       DIP("vpkuwum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17564       putVReg( vD_addr,
17565                binop(Iop_NarrowBin32to16x8, mkexpr(vA), mkexpr(vB)) );
17566       return True;
17567 
17568    case 0x08E: // vpkuhus (Pack Unsigned HW Unsigned Saturate, AV p225)
17569       DIP("vpkuhus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17570       putVReg( vD_addr,
17571                binop(Iop_QNarrowBin16Uto8Ux16, mkexpr(vA), mkexpr(vB)) );
17572       // TODO: set VSCR[SAT]
17573       return True;
17574 
17575    case 0x0CE: // vpkuwus (Pack Unsigned W Unsigned Saturate, AV p227)
17576       DIP("vpkuwus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17577       putVReg( vD_addr,
17578                binop(Iop_QNarrowBin32Uto16Ux8, mkexpr(vA), mkexpr(vB)) );
17579       // TODO: set VSCR[SAT]
17580       return True;
17581 
17582    case 0x10E: { // vpkshus (Pack Signed HW Unsigned Saturate, AV p221)
17583       // This insn does a signed->unsigned saturating conversion.
17584       // Conversion done here, then uses unsigned->unsigned vpk insn:
17585       //  => UnsignedSaturatingNarrow( x & ~ (x >>s 15) )
17586       IRTemp vA_tmp = newTemp(Ity_V128);
17587       IRTemp vB_tmp = newTemp(Ity_V128);
17588       DIP("vpkshus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17589       assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
17590                             unop(Iop_NotV128,
17591                                  binop(Iop_SarN16x8,
17592                                        mkexpr(vA), mkU8(15)))) );
17593       assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
17594                             unop(Iop_NotV128,
17595                                  binop(Iop_SarN16x8,
17596                                        mkexpr(vB), mkU8(15)))) );
17597       putVReg( vD_addr, binop(Iop_QNarrowBin16Uto8Ux16,
17598                               mkexpr(vA_tmp), mkexpr(vB_tmp)) );
17599       // TODO: set VSCR[SAT]
17600       return True;
17601    }
17602    case 0x14E: { // vpkswus (Pack Signed W Unsigned Saturate, AV p223)
17603       // This insn does a signed->unsigned saturating conversion.
17604       // Conversion done here, then uses unsigned->unsigned vpk insn:
17605       //  => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
17606       IRTemp vA_tmp = newTemp(Ity_V128);
17607       IRTemp vB_tmp = newTemp(Ity_V128);
17608       DIP("vpkswus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17609       assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
17610                             unop(Iop_NotV128,
17611                                  binop(Iop_SarN32x4,
17612                                        mkexpr(vA), mkU8(31)))) );
17613       assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
17614                             unop(Iop_NotV128,
17615                                  binop(Iop_SarN32x4,
17616                                        mkexpr(vB), mkU8(31)))) );
17617       putVReg( vD_addr, binop(Iop_QNarrowBin32Uto16Ux8,
17618                               mkexpr(vA_tmp), mkexpr(vB_tmp)) );
17619       // TODO: set VSCR[SAT]
17620       return True;
17621    }
17622    case 0x18E: // vpkshss (Pack Signed HW Signed Saturate, AV p220)
17623       DIP("vpkshss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17624       putVReg( vD_addr,
17625                binop(Iop_QNarrowBin16Sto8Sx16, mkexpr(vA), mkexpr(vB)) );
17626       // TODO: set VSCR[SAT]
17627       return True;
17628 
17629    case 0x1CE: // vpkswss (Pack Signed W Signed Saturate, AV p222)
17630       DIP("vpkswss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17631       putVReg( vD_addr,
17632                binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(vA), mkexpr(vB)) );
17633       // TODO: set VSCR[SAT]
17634       return True;
17635 
17636    case 0x30E: { // vpkpx (Pack Pixel, AV p219)
17637       /* CAB: Worth a new primop? */
17638       /* Using shifts to compact pixel elements, then packing them */
17639       IRTemp a1 = newTemp(Ity_V128);
17640       IRTemp a2 = newTemp(Ity_V128);
17641       IRTemp a3 = newTemp(Ity_V128);
17642       IRTemp a_tmp = newTemp(Ity_V128);
17643       IRTemp b1 = newTemp(Ity_V128);
17644       IRTemp b2 = newTemp(Ity_V128);
17645       IRTemp b3 = newTemp(Ity_V128);
17646       IRTemp b_tmp = newTemp(Ity_V128);
17647       DIP("vpkpx v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17648       assign( a1, binop(Iop_ShlN16x8,
17649                         binop(Iop_ShrN32x4, mkexpr(vA), mkU8(19)),
17650                         mkU8(10)) );
17651       assign( a2, binop(Iop_ShlN16x8,
17652                         binop(Iop_ShrN16x8, mkexpr(vA), mkU8(11)),
17653                         mkU8(5)) );
17654       assign( a3,  binop(Iop_ShrN16x8,
17655                          binop(Iop_ShlN16x8, mkexpr(vA), mkU8(8)),
17656                          mkU8(11)) );
17657       assign( a_tmp, binop(Iop_OrV128, mkexpr(a1),
17658                            binop(Iop_OrV128, mkexpr(a2), mkexpr(a3))) );
17659 
17660       assign( b1, binop(Iop_ShlN16x8,
17661                         binop(Iop_ShrN32x4, mkexpr(vB), mkU8(19)),
17662                         mkU8(10)) );
17663       assign( b2, binop(Iop_ShlN16x8,
17664                         binop(Iop_ShrN16x8, mkexpr(vB), mkU8(11)),
17665                         mkU8(5)) );
17666       assign( b3,  binop(Iop_ShrN16x8,
17667                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(8)),
17668                          mkU8(11)) );
17669       assign( b_tmp, binop(Iop_OrV128, mkexpr(b1),
17670                            binop(Iop_OrV128, mkexpr(b2), mkexpr(b3))) );
17671 
17672       putVReg( vD_addr, binop(Iop_NarrowBin32to16x8,
17673                               mkexpr(a_tmp), mkexpr(b_tmp)) );
17674       return True;
17675    }
17676 
17677    case 0x44E: // vpkudum (Pack Unsigned Double Word Unsigned Modulo)
17678       DIP("vpkudum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17679       putVReg( vD_addr,
17680                binop(Iop_NarrowBin64to32x4, mkexpr(vA), mkexpr(vB)) );
17681       return True;
17682 
17683    case 0x4CE: // vpkudus (Pack Unsigned Double Word Unsigned Saturate)
17684       DIP("vpkudus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17685       putVReg( vD_addr,
17686                binop(Iop_QNarrowBin64Uto32Ux4, mkexpr(vA), mkexpr(vB)) );
17687       // TODO: set VSCR[SAT]
17688       return True;
17689 
17690    case 0x54E: { // vpksdus (Pack Signed Double Word Unsigned Saturate)
17691       // This insn does a doubled signed->double unsigned saturating conversion
17692       // Conversion done here, then uses unsigned->unsigned vpk insn:
17693       //  => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
17694       // This is similar to the technique used for vpkswus, except done
17695       // with double word integers versus word integers.
17696       IRTemp vA_tmp = newTemp(Ity_V128);
17697       IRTemp vB_tmp = newTemp(Ity_V128);
17698       DIP("vpksdus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17699       assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
17700                             unop(Iop_NotV128,
17701                                  binop(Iop_SarN64x2,
17702                                        mkexpr(vA), mkU8(63)))) );
17703       assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
17704                             unop(Iop_NotV128,
17705                                  binop(Iop_SarN64x2,
17706                                        mkexpr(vB), mkU8(63)))) );
17707       putVReg( vD_addr, binop(Iop_QNarrowBin64Uto32Ux4,
17708                               mkexpr(vA_tmp), mkexpr(vB_tmp)) );
17709       // TODO: set VSCR[SAT]
17710       return True;
17711    }
17712 
17713    case 0x5CE: // vpksdss (Pack Signed double word Signed Saturate)
17714       DIP("vpksdss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17715       putVReg( vD_addr,
17716                binop(Iop_QNarrowBin64Sto32Sx4, mkexpr(vA), mkexpr(vB)) );
17717       // TODO: set VSCR[SAT]
17718       return True;
17719    default:
17720       break; // Fall through...
17721    }
17722 
17723 
17724    if (vA_addr != 0) {
17725       vex_printf("dis_av_pack(ppc)(vA_addr)\n");
17726       return False;
17727    }
17728 
17729    signs = newTemp(Ity_V128);
17730    zeros = newTemp(Ity_V128);
17731    assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
17732 
17733    switch (opc2) {
17734    /* Unpacking */
17735    case 0x20E: { // vupkhsb (Unpack High Signed B, AV p277)
17736       DIP("vupkhsb v%d,v%d\n", vD_addr, vB_addr);
17737       assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
17738       putVReg( vD_addr,
17739                binop(Iop_InterleaveHI8x16, mkexpr(signs), mkexpr(vB)) );
17740       break;
17741    }
17742    case 0x24E: { // vupkhsh (Unpack High Signed HW, AV p278)
17743       DIP("vupkhsh v%d,v%d\n", vD_addr, vB_addr);
17744       assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
17745       putVReg( vD_addr,
17746                binop(Iop_InterleaveHI16x8, mkexpr(signs), mkexpr(vB)) );
17747       break;
17748    }
17749    case 0x28E: { // vupklsb (Unpack Low Signed B, AV p280)
17750       DIP("vupklsb v%d,v%d\n", vD_addr, vB_addr);
17751       assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
17752       putVReg( vD_addr,
17753                binop(Iop_InterleaveLO8x16, mkexpr(signs), mkexpr(vB)) );
17754       break;
17755    }
17756    case 0x2CE: { // vupklsh (Unpack Low Signed HW, AV p281)
17757       DIP("vupklsh v%d,v%d\n", vD_addr, vB_addr);
17758       assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
17759       putVReg( vD_addr,
17760                binop(Iop_InterleaveLO16x8, mkexpr(signs), mkexpr(vB)) );
17761       break;
17762    }
17763    case 0x34E: { // vupkhpx (Unpack High Pixel16, AV p276)
17764       /* CAB: Worth a new primop? */
17765       /* Using shifts to isolate pixel elements, then expanding them */
17766       IRTemp z0  = newTemp(Ity_V128);
17767       IRTemp z1  = newTemp(Ity_V128);
17768       IRTemp z01 = newTemp(Ity_V128);
17769       IRTemp z2  = newTemp(Ity_V128);
17770       IRTemp z3  = newTemp(Ity_V128);
17771       IRTemp z23 = newTemp(Ity_V128);
17772       DIP("vupkhpx v%d,v%d\n", vD_addr, vB_addr);
17773       assign( z0,  binop(Iop_ShlN16x8,
17774                          binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
17775                          mkU8(8)) );
17776       assign( z1,  binop(Iop_ShrN16x8,
17777                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
17778                          mkU8(11)) );
17779       assign( z01, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
17780                          binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
17781       assign( z2,  binop(Iop_ShrN16x8,
17782                          binop(Iop_ShlN16x8,
17783                                binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
17784                                mkU8(11)),
17785                          mkU8(3)) );
17786       assign( z3,  binop(Iop_ShrN16x8,
17787                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
17788                          mkU8(11)) );
17789       assign( z23, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
17790                          binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
17791       putVReg( vD_addr,
17792                binop(Iop_OrV128,
17793                      binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
17794                      mkexpr(z23)) );
17795       break;
17796    }
17797    case 0x3CE: { // vupklpx (Unpack Low Pixel16, AV p279)
17798       /* identical to vupkhpx, except interleaving LO */
17799       IRTemp z0  = newTemp(Ity_V128);
17800       IRTemp z1  = newTemp(Ity_V128);
17801       IRTemp z01 = newTemp(Ity_V128);
17802       IRTemp z2  = newTemp(Ity_V128);
17803       IRTemp z3  = newTemp(Ity_V128);
17804       IRTemp z23 = newTemp(Ity_V128);
17805       DIP("vupklpx v%d,v%d\n", vD_addr, vB_addr);
17806       assign( z0,  binop(Iop_ShlN16x8,
17807                          binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
17808                          mkU8(8)) );
17809       assign( z1,  binop(Iop_ShrN16x8,
17810                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
17811                          mkU8(11)) );
17812       assign( z01, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
17813                          binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
17814       assign( z2,  binop(Iop_ShrN16x8,
17815                          binop(Iop_ShlN16x8,
17816                                binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
17817                                mkU8(11)),
17818                          mkU8(3)) );
17819       assign( z3,  binop(Iop_ShrN16x8,
17820                          binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
17821                          mkU8(11)) );
17822       assign( z23, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
17823                          binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
17824       putVReg( vD_addr,
17825                binop(Iop_OrV128,
17826                      binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
17827                      mkexpr(z23)) );
17828       break;
17829    }
17830    case 0x64E: { // vupkhsw (Unpack High Signed Word)
17831       DIP("vupkhsw v%d,v%d\n", vD_addr, vB_addr);
17832       assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) );
17833       putVReg( vD_addr,
17834                binop(Iop_InterleaveHI32x4, mkexpr(signs), mkexpr(vB)) );
17835       break;
17836    }
17837    case 0x6CE: { // vupklsw (Unpack Low Signed Word)
17838       DIP("vupklsw v%d,v%d\n", vD_addr, vB_addr);
17839       assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) );
17840       putVReg( vD_addr,
17841                binop(Iop_InterleaveLO32x4, mkexpr(signs), mkexpr(vB)) );
17842       break;
17843    }
17844    default:
17845       vex_printf("dis_av_pack(ppc)(opc2)\n");
17846       return False;
17847    }
17848    return True;
17849 }
17850 
17851 /*
17852   AltiVec Cipher Instructions
17853 */
dis_av_cipher(UInt theInstr)17854 static Bool dis_av_cipher ( UInt theInstr )
17855 {
17856    /* VX-Form */
17857    UChar opc1     = ifieldOPC(theInstr);
17858    UChar vD_addr  = ifieldRegDS(theInstr);
17859    UChar vA_addr  = ifieldRegA(theInstr);
17860    UChar vB_addr  = ifieldRegB(theInstr);
17861    UInt  opc2     = IFIELD( theInstr, 0, 11 );
17862 
17863    IRTemp vA    = newTemp(Ity_V128);
17864    IRTemp vB    = newTemp(Ity_V128);
17865    assign( vA, getVReg(vA_addr));
17866    assign( vB, getVReg(vB_addr));
17867 
17868    if (opc1 != 0x4) {
17869       vex_printf("dis_av_cipher(ppc)(instr)\n");
17870       return False;
17871    }
17872    switch (opc2) {
17873       case 0x508: // vcipher (Vector Inverser Cipher)
17874          DIP("vcipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17875          putVReg( vD_addr,
17876                   binop(Iop_CipherV128, mkexpr(vA), mkexpr(vB)) );
17877          return True;
17878 
17879       case 0x509: // vcipherlast (Vector Inverser Cipher Last)
17880          DIP("vcipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17881          putVReg( vD_addr,
17882                   binop(Iop_CipherLV128, mkexpr(vA), mkexpr(vB)) );
17883          return True;
17884 
17885       case 0x548: // vncipher (Vector Inverser Cipher)
17886          DIP("vncipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17887          putVReg( vD_addr,
17888                   binop(Iop_NCipherV128, mkexpr(vA), mkexpr(vB)) );
17889          return True;
17890 
17891       case 0x549: // vncipherlast (Vector Inverser Cipher Last)
17892          DIP("vncipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
17893          putVReg( vD_addr,
17894                   binop(Iop_NCipherLV128, mkexpr(vA), mkexpr(vB)) );
17895          return True;
17896 
17897       case 0x5C8: /* vsbox (Vector SubBytes, this does the cipher
17898        * subBytes transform)
17899        */
17900          DIP("vsbox v%d,v%d\n", vD_addr, vA_addr);
17901          putVReg( vD_addr,
17902                   unop(Iop_CipherSV128, mkexpr(vA) ) );
17903          return True;
17904 
17905       default:
17906          vex_printf("dis_av_cipher(ppc)(opc2)\n");
17907          return False;
17908    }
17909    return True;
17910 }
17911 
17912 /*
17913   AltiVec Secure Hash Instructions
17914 */
dis_av_hash(UInt theInstr)17915 static Bool dis_av_hash ( UInt theInstr )
17916 {
17917    /* VX-Form */
17918    UChar opc1     = ifieldOPC(theInstr);
17919    UChar vRT_addr = ifieldRegDS(theInstr);
17920    UChar vRA_addr  = ifieldRegA(theInstr);
17921    UChar s_field  = IFIELD( theInstr, 11, 5 );  // st and six field
17922    UChar st       = IFIELD( theInstr, 15, 1 );  // st
17923    UChar six      = IFIELD( theInstr, 11, 4 );  // six field
17924    UInt  opc2     = IFIELD( theInstr, 0, 11 );
17925 
17926    IRTemp vA    = newTemp(Ity_V128);
17927    IRTemp dst    = newTemp(Ity_V128);
17928    assign( vA, getVReg(vRA_addr));
17929 
17930    if (opc1 != 0x4) {
17931       vex_printf("dis_av_hash(ppc)(instr)\n");
17932       return False;
17933    }
17934 
17935    switch (opc2) {
17936       case 0x682:  // vshasigmaw
17937          DIP("vshasigmaw v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six);
17938          assign( dst, binop( Iop_SHA256, mkexpr( vA ), mkU8( s_field) ) );
17939          putVReg( vRT_addr, mkexpr(dst));
17940          return True;
17941 
17942       case 0x6C2:  // vshasigmad,
17943          DIP("vshasigmad v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six);
17944          putVReg( vRT_addr, binop( Iop_SHA512, mkexpr( vA ), mkU8( s_field) ) );
17945          return True;
17946 
17947       default:
17948          vex_printf("dis_av_hash(ppc)(opc2)\n");
17949          return False;
17950    }
17951    return True;
17952 }
17953 
17954 /*
17955  * This function is used by the Vector add/subtract [extended] modulo/carry
17956  * instructions.
17957  *   - For the non-extended add instructions, the cin arg is set to zero.
17958  *   - For the extended add instructions, cin is the integer value of
17959  *     src3.bit[127].
17960  *   - For the non-extended subtract instructions, src1 is added to the one's
17961  *     complement of src2 + 1.  We re-use the cin argument to hold the '1'
17962  *     value for this operation.
17963  *   - For the extended subtract instructions, cin is the integer value of src3.bit[127].
17964  */
_get_quad_modulo_or_carry(IRExpr * vecA,IRExpr * vecB,IRExpr * cin,Bool modulo)17965 static IRTemp _get_quad_modulo_or_carry(IRExpr * vecA, IRExpr * vecB,
17966                                         IRExpr * cin, Bool modulo)
17967 {
17968    IRTemp _vecA_32   = IRTemp_INVALID;
17969    IRTemp _vecB_32   = IRTemp_INVALID;
17970    IRTemp res_32     = IRTemp_INVALID;
17971    IRTemp result     = IRTemp_INVALID;
17972    IRTemp tmp_result = IRTemp_INVALID;
17973    IRTemp carry      = IRTemp_INVALID;
17974    Int i;
17975    IRExpr * _vecA_low64 =  unop( Iop_V128to64, vecA );
17976    IRExpr * _vecB_low64 =  unop( Iop_V128to64, vecB );
17977    IRExpr * _vecA_high64 = unop( Iop_V128HIto64, vecA );
17978    IRExpr * _vecB_high64 = unop( Iop_V128HIto64, vecB );
17979 
17980    for (i = 0; i < 4; i++) {
17981       _vecA_32 = newTemp(Ity_I32);
17982       _vecB_32 = newTemp(Ity_I32);
17983       res_32   = newTemp(Ity_I32);
17984       switch (i) {
17985       case 0:
17986          assign(_vecA_32, unop( Iop_64to32, _vecA_low64 ) );
17987          assign(_vecB_32, unop( Iop_64to32, _vecB_low64 ) );
17988          break;
17989       case 1:
17990          assign(_vecA_32, unop( Iop_64HIto32, _vecA_low64 ) );
17991          assign(_vecB_32, unop( Iop_64HIto32, _vecB_low64 ) );
17992          break;
17993       case 2:
17994          assign(_vecA_32, unop( Iop_64to32, _vecA_high64 ) );
17995          assign(_vecB_32, unop( Iop_64to32, _vecB_high64 ) );
17996          break;
17997       case 3:
17998          assign(_vecA_32, unop( Iop_64HIto32, _vecA_high64 ) );
17999          assign(_vecB_32, unop( Iop_64HIto32, _vecB_high64 ) );
18000          break;
18001       }
18002 
18003       assign(res_32, binop( Iop_Add32,
18004                             binop( Iop_Add32,
18005                                    binop ( Iop_Add32,
18006                                            mkexpr(_vecA_32),
18007                                            mkexpr(_vecB_32) ),
18008                                    (i == 0) ? mkU32(0) : mkexpr(carry) ),
18009                             (i == 0) ? cin : mkU32(0) ) );
18010       if (modulo) {
18011          result = newTemp(Ity_V128);
18012          assign(result, binop( Iop_OrV128,
18013                               (i == 0) ? binop( Iop_64HLtoV128,
18014                                                 mkU64(0),
18015                                                 mkU64(0) ) : mkexpr(tmp_result),
18016                               binop( Iop_ShlV128,
18017                                      binop( Iop_64HLtoV128,
18018                                             mkU64(0),
18019                                             binop( Iop_32HLto64,
18020                                                    mkU32(0),
18021                                                    mkexpr(res_32) ) ),
18022                                      mkU8(i * 32) ) ) );
18023          tmp_result = newTemp(Ity_V128);
18024          assign(tmp_result, mkexpr(result));
18025       }
18026       carry = newTemp(Ity_I32);
18027       assign(carry, unop(Iop_1Uto32, binop( Iop_CmpLT32U,
18028                                             mkexpr(res_32),
18029                                             mkexpr(_vecA_32 ) ) ) );
18030    }
18031    if (modulo)
18032       return result;
18033    else
18034       return carry;
18035 }
18036 
18037 
dis_av_quad(UInt theInstr)18038 static Bool dis_av_quad ( UInt theInstr )
18039 {
18040    /* VX-Form */
18041    UChar opc1     = ifieldOPC(theInstr);
18042    UChar vRT_addr = ifieldRegDS(theInstr);
18043    UChar vRA_addr = ifieldRegA(theInstr);
18044    UChar vRB_addr = ifieldRegB(theInstr);
18045    UChar vRC_addr;
18046    UInt  opc2     = IFIELD( theInstr, 0, 11 );
18047 
18048    IRTemp vA    = newTemp(Ity_V128);
18049    IRTemp vB    = newTemp(Ity_V128);
18050    IRTemp vC    = IRTemp_INVALID;
18051    IRTemp cin    = IRTemp_INVALID;
18052    assign( vA, getVReg(vRA_addr));
18053    assign( vB, getVReg(vRB_addr));
18054 
18055    if (opc1 != 0x4) {
18056       vex_printf("dis_av_quad(ppc)(instr)\n");
18057       return False;
18058    }
18059 
18060    switch (opc2) {
18061    case 0x140:  // vaddcuq
18062      DIP("vaddcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
18063      putVReg( vRT_addr, unop( Iop_32UtoV128,
18064                               mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
18065                                                                mkexpr(vB),
18066                                                                mkU32(0), False) ) ) );
18067      return True;
18068    case 0x100: // vadduqm
18069       DIP("vadduqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
18070       putVReg( vRT_addr, mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
18071                                                           mkexpr(vB), mkU32(0), True) ) );
18072       return True;
18073    case 0x540: // vsubcuq
18074       DIP("vsubcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
18075       putVReg( vRT_addr,
18076                unop( Iop_32UtoV128,
18077                      mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
18078                                                       unop( Iop_NotV128,
18079                                                             mkexpr(vB) ),
18080                                                       mkU32(1), False) ) ) );
18081       return True;
18082    case 0x500: // vsubuqm
18083       DIP("vsubuqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
18084       putVReg( vRT_addr,
18085                mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
18086                                                 unop( Iop_NotV128, mkexpr(vB) ),
18087                                                 mkU32(1), True) ) );
18088       return True;
18089    case 0x054C: // vbpermq
18090    {
18091 #define BPERMD_IDX_MASK 0x00000000000000FFULL
18092 #define BPERMD_BIT_MASK 0x8000000000000000ULL
18093       int i;
18094       IRExpr * vB_expr = mkexpr(vB);
18095       IRExpr * res = binop(Iop_AndV128, mkV128(0), mkV128(0));
18096       DIP("vbpermq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
18097       for (i = 0; i < 16; i++) {
18098          IRTemp idx_tmp = newTemp( Ity_V128 );
18099          IRTemp perm_bit = newTemp( Ity_V128 );
18100          IRTemp idx = newTemp( Ity_I8 );
18101          IRTemp idx_LT127 = newTemp( Ity_I1 );
18102          IRTemp idx_LT127_ity128 = newTemp( Ity_V128 );
18103 
18104          assign( idx_tmp,
18105                  binop( Iop_AndV128,
18106                         binop( Iop_64HLtoV128,
18107                                mkU64(0),
18108                                mkU64(BPERMD_IDX_MASK) ),
18109                         vB_expr ) );
18110          assign( idx_LT127,
18111                  binop( Iop_CmpEQ32,
18112                         unop ( Iop_64to32,
18113                                unop( Iop_V128to64, binop( Iop_ShrV128,
18114                                                           mkexpr(idx_tmp),
18115                                                           mkU8(7) ) ) ),
18116                         mkU32(0) ) );
18117 
18118          /* Below, we set idx to determine which bit of vA to use for the
18119           * perm bit.  If idx_LT127 is 0, the perm bit is forced to '0'.
18120           */
18121          assign( idx,
18122                  binop( Iop_And8,
18123                         unop( Iop_1Sto8,
18124                               mkexpr(idx_LT127) ),
18125                         unop( Iop_32to8,
18126                               unop( Iop_V128to32, mkexpr( idx_tmp ) ) ) ) );
18127 
18128          assign( idx_LT127_ity128,
18129                  binop( Iop_64HLtoV128,
18130                         mkU64(0),
18131                         unop( Iop_32Uto64,
18132                               unop( Iop_1Uto32, mkexpr(idx_LT127 ) ) ) ) );
18133          assign( perm_bit,
18134                  binop( Iop_AndV128,
18135                         mkexpr( idx_LT127_ity128 ),
18136                         binop( Iop_ShrV128,
18137                                binop( Iop_AndV128,
18138                                       binop (Iop_64HLtoV128,
18139                                              mkU64( BPERMD_BIT_MASK ),
18140                                              mkU64(0)),
18141                                       binop( Iop_ShlV128,
18142                                              mkexpr( vA ),
18143                                              mkexpr( idx ) ) ),
18144                                mkU8( 127 ) ) ) );
18145          res = binop( Iop_OrV128,
18146                       res,
18147                       binop( Iop_ShlV128,
18148                              mkexpr( perm_bit ),
18149                              mkU8( i + 64 ) ) );
18150          vB_expr = binop( Iop_ShrV128, vB_expr, mkU8( 8 ) );
18151       }
18152       putVReg( vRT_addr, res);
18153       return True;
18154 #undef BPERMD_IDX_MASK
18155 #undef BPERMD_BIT_MASK
18156    }
18157 
18158    default:
18159       break;  // fall through
18160    }
18161 
18162    opc2     = IFIELD( theInstr, 0, 6 );
18163    vRC_addr = ifieldRegC(theInstr);
18164    vC = newTemp(Ity_V128);
18165    cin = newTemp(Ity_I32);
18166    switch (opc2) {
18167       case 0x3D: // vaddecuq
18168          assign( vC, getVReg(vRC_addr));
18169          DIP("vaddecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
18170              vRC_addr);
18171          assign(cin, binop( Iop_And32,
18172                             unop( Iop_64to32,
18173                                   unop( Iop_V128to64, mkexpr(vC) ) ),
18174                             mkU32(1) ) );
18175          putVReg( vRT_addr,
18176                   unop( Iop_32UtoV128,
18177                         mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB),
18178                                                          mkexpr(cin),
18179                                                          False) ) ) );
18180          return True;
18181       case 0x3C: // vaddeuqm
18182          assign( vC, getVReg(vRC_addr));
18183          DIP("vaddeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
18184              vRC_addr);
18185          assign(cin, binop( Iop_And32,
18186                             unop( Iop_64to32,
18187                                   unop( Iop_V128to64, mkexpr(vC) ) ),
18188                             mkU32(1) ) );
18189          putVReg( vRT_addr,
18190                   mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB),
18191                                                    mkexpr(cin),
18192                                                    True) ) );
18193          return True;
18194       case 0x3F: // vsubecuq
18195          assign( vC, getVReg(vRC_addr));
18196          DIP("vsubecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
18197              vRC_addr);
18198          assign(cin, binop( Iop_And32,
18199                             unop( Iop_64to32,
18200                                   unop( Iop_V128to64, mkexpr(vC) ) ),
18201                             mkU32(1) ) );
18202          putVReg( vRT_addr,
18203                   unop( Iop_32UtoV128,
18204                         mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
18205                                                          unop( Iop_NotV128,
18206                                                                mkexpr(vB) ),
18207                                                          mkexpr(cin),
18208                                                          False) ) ) );
18209          return True;
18210       case 0x3E: // vsubeuqm
18211          assign( vC, getVReg(vRC_addr));
18212          DIP("vsubeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
18213              vRC_addr);
18214          assign(cin, binop( Iop_And32,
18215                             unop( Iop_64to32,
18216                                   unop( Iop_V128to64, mkexpr(vC) ) ),
18217                             mkU32(1) ) );
18218          putVReg( vRT_addr,
18219                   mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
18220                                                    unop( Iop_NotV128, mkexpr(vB) ),
18221                                                    mkexpr(cin),
18222                                                    True) ) );
18223          return True;
18224       default:
18225          vex_printf("dis_av_quad(ppc)(opc2.2)\n");
18226          return False;
18227    }
18228 
18229    return True;
18230 }
18231 
18232 
18233 /*
18234   AltiVec BCD Arithmetic instructions.
18235   These instructions modify CR6 for various conditions in the result,
18236   including when an overflow occurs.  We could easily detect all conditions
18237   except when an overflow occurs.  But since we can't be 100% accurate
18238   in our emulation of CR6, it seems best to just not support it all.
18239 */
dis_av_bcd(UInt theInstr)18240 static Bool dis_av_bcd ( UInt theInstr )
18241 {
18242    /* VX-Form */
18243    UChar opc1     = ifieldOPC(theInstr);
18244    UChar vRT_addr = ifieldRegDS(theInstr);
18245    UChar vRA_addr = ifieldRegA(theInstr);
18246    UChar vRB_addr = ifieldRegB(theInstr);
18247    UChar ps       = IFIELD( theInstr, 9, 1 );
18248    UInt  opc2     = IFIELD( theInstr, 0, 9 );
18249 
18250    IRTemp vA    = newTemp(Ity_V128);
18251    IRTemp vB    = newTemp(Ity_V128);
18252    IRTemp dst    = newTemp(Ity_V128);
18253    assign( vA, getVReg(vRA_addr));
18254    assign( vB, getVReg(vRB_addr));
18255 
18256    if (opc1 != 0x4) {
18257       vex_printf("dis_av_bcd(ppc)(instr)\n");
18258       return False;
18259    }
18260 
18261    switch (opc2) {
18262    case 0x1:  // bcdadd
18263      DIP("bcdadd. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps);
18264      assign( dst, triop( Iop_BCDAdd, mkexpr( vA ),
18265                          mkexpr( vB ), mkU8( ps ) ) );
18266      putVReg( vRT_addr, mkexpr(dst));
18267      return True;
18268 
18269    case 0x41:  // bcdsub
18270      DIP("bcdsub. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps);
18271      assign( dst, triop( Iop_BCDSub, mkexpr( vA ),
18272                          mkexpr( vB ), mkU8( ps ) ) );
18273      putVReg( vRT_addr, mkexpr(dst));
18274      return True;
18275 
18276    default:
18277       vex_printf("dis_av_bcd(ppc)(opc2)\n");
18278       return False;
18279    }
18280    return True;
18281 }
18282 
18283 /*
18284   AltiVec Floating Point Arithmetic Instructions
18285 */
dis_av_fp_arith(UInt theInstr)18286 static Bool dis_av_fp_arith ( UInt theInstr )
18287 {
18288    /* VA-Form */
18289    UChar opc1     = ifieldOPC(theInstr);
18290    UChar vD_addr  = ifieldRegDS(theInstr);
18291    UChar vA_addr  = ifieldRegA(theInstr);
18292    UChar vB_addr  = ifieldRegB(theInstr);
18293    UChar vC_addr  = ifieldRegC(theInstr);
18294    UInt  opc2=0;
18295 
18296    IRTemp vA = newTemp(Ity_V128);
18297    IRTemp vB = newTemp(Ity_V128);
18298    IRTemp vC = newTemp(Ity_V128);
18299    assign( vA, getVReg(vA_addr));
18300    assign( vB, getVReg(vB_addr));
18301    assign( vC, getVReg(vC_addr));
18302 
18303    if (opc1 != 0x4) {
18304       vex_printf("dis_av_fp_arith(ppc)(instr)\n");
18305       return False;
18306    }
18307 
18308    IRTemp rm = newTemp(Ity_I32);
18309    assign(rm, get_IR_roundingmode());
18310 
18311    opc2 = IFIELD( theInstr, 0, 6 );
18312    switch (opc2) {
18313    case 0x2E: // vmaddfp (Multiply Add FP, AV p177)
18314       DIP("vmaddfp v%d,v%d,v%d,v%d\n",
18315           vD_addr, vA_addr, vC_addr, vB_addr);
18316       putVReg( vD_addr,
18317                triop(Iop_Add32Fx4, mkU32(Irrm_NEAREST),
18318                      mkexpr(vB),
18319                      triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
18320                            mkexpr(vA), mkexpr(vC))) );
18321       return True;
18322 
18323    case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215)
18324       DIP("vnmsubfp v%d,v%d,v%d,v%d\n",
18325           vD_addr, vA_addr, vC_addr, vB_addr);
18326       putVReg( vD_addr,
18327                triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST),
18328                      mkexpr(vB),
18329                      triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
18330                            mkexpr(vA), mkexpr(vC))) );
18331       return True;
18332    }
18333 
18334    default:
18335      break; // Fall through...
18336    }
18337 
18338    opc2 = IFIELD( theInstr, 0, 11 );
18339    switch (opc2) {
18340    case 0x00A: // vaddfp (Add FP, AV p137)
18341       DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
18342       putVReg( vD_addr, triop(Iop_Add32Fx4,
18343                               mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) );
18344       return True;
18345 
18346   case 0x04A: // vsubfp (Subtract FP, AV p261)
18347       DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
18348       putVReg( vD_addr, triop(Iop_Sub32Fx4,
18349                               mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) );
18350       return True;
18351 
18352    case 0x40A: // vmaxfp (Maximum FP, AV p178)
18353       DIP("vmaxfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
18354       putVReg( vD_addr, binop(Iop_Max32Fx4, mkexpr(vA), mkexpr(vB)) );
18355       return True;
18356 
18357    case 0x44A: // vminfp (Minimum FP, AV p187)
18358       DIP("vminfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
18359       putVReg( vD_addr, binop(Iop_Min32Fx4, mkexpr(vA), mkexpr(vB)) );
18360       return True;
18361 
18362    default:
18363       break; // Fall through...
18364    }
18365 
18366 
18367    if (vA_addr != 0) {
18368       vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n");
18369       return False;
18370    }
18371 
18372    switch (opc2) {
18373    case 0x10A: // vrefp (Reciprocal Esimate FP, AV p228)
18374       DIP("vrefp v%d,v%d\n", vD_addr, vB_addr);
18375       putVReg( vD_addr, unop(Iop_RecipEst32Fx4, mkexpr(vB)) );
18376       return True;
18377 
18378    case 0x14A: // vrsqrtefp (Reciprocal Sqrt Estimate FP, AV p237)
18379       DIP("vrsqrtefp v%d,v%d\n", vD_addr, vB_addr);
18380       putVReg( vD_addr, unop(Iop_RSqrtEst32Fx4, mkexpr(vB)) );
18381       return True;
18382 
18383    case 0x18A: // vexptefp (2 Raised to the Exp Est FP, AV p173)
18384       DIP("vexptefp v%d,v%d\n", vD_addr, vB_addr);
18385       DIP(" => not implemented\n");
18386       return False;
18387 
18388    case 0x1CA: // vlogefp (Log2 Estimate FP, AV p175)
18389       DIP("vlogefp v%d,v%d\n", vD_addr, vB_addr);
18390       DIP(" => not implemented\n");
18391       return False;
18392 
18393    default:
18394       vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2);
18395       return False;
18396    }
18397    return True;
18398 }
18399 
18400 /*
18401   AltiVec Floating Point Compare Instructions
18402 */
dis_av_fp_cmp(UInt theInstr)18403 static Bool dis_av_fp_cmp ( UInt theInstr )
18404 {
18405    /* VXR-Form */
18406    UChar opc1     = ifieldOPC(theInstr);
18407    UChar vD_addr  = ifieldRegDS(theInstr);
18408    UChar vA_addr  = ifieldRegA(theInstr);
18409    UChar vB_addr  = ifieldRegB(theInstr);
18410    UChar flag_rC  = ifieldBIT10(theInstr);
18411    UInt  opc2     = IFIELD( theInstr, 0, 10 );
18412 
18413    Bool cmp_bounds = False;
18414 
18415    IRTemp vA = newTemp(Ity_V128);
18416    IRTemp vB = newTemp(Ity_V128);
18417    IRTemp vD = newTemp(Ity_V128);
18418    assign( vA, getVReg(vA_addr));
18419    assign( vB, getVReg(vB_addr));
18420 
18421    if (opc1 != 0x4) {
18422       vex_printf("dis_av_fp_cmp(ppc)(instr)\n");
18423       return False;
18424    }
18425 
18426    switch (opc2) {
18427    case 0x0C6: // vcmpeqfp (Compare Equal-to FP, AV p159)
18428       DIP("vcmpeqfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
18429                                       vD_addr, vA_addr, vB_addr);
18430       assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
18431       break;
18432 
18433    case 0x1C6: // vcmpgefp (Compare Greater-than-or-Equal-to, AV p163)
18434       DIP("vcmpgefp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
18435                                       vD_addr, vA_addr, vB_addr);
18436       assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
18437       break;
18438 
18439    case 0x2C6: // vcmpgtfp (Compare Greater-than FP, AV p164)
18440       DIP("vcmpgtfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
18441                                       vD_addr, vA_addr, vB_addr);
18442       assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
18443       break;
18444 
18445    case 0x3C6: { // vcmpbfp (Compare Bounds FP, AV p157)
18446       IRTemp gt      = newTemp(Ity_V128);
18447       IRTemp lt      = newTemp(Ity_V128);
18448       IRTemp zeros   = newTemp(Ity_V128);
18449       DIP("vcmpbfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
18450                                      vD_addr, vA_addr, vB_addr);
18451       cmp_bounds = True;
18452       assign( zeros,   unop(Iop_Dup32x4, mkU32(0)) );
18453 
18454       /* Note: making use of fact that the ppc backend for compare insns
18455          return zero'd lanes if either of the corresponding arg lanes is
18456          a nan.
18457 
18458          Perhaps better to have an irop Iop_isNan32Fx4, but then we'd
18459          need this for the other compares too (vcmpeqfp etc)...
18460          Better still, tighten down the spec for compare irops.
18461        */
18462       assign( gt, unop(Iop_NotV128,
18463                        binop(Iop_CmpLE32Fx4, mkexpr(vA), mkexpr(vB))) );
18464       assign( lt, unop(Iop_NotV128,
18465                        binop(Iop_CmpGE32Fx4, mkexpr(vA),
18466                              triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST),
18467                                    mkexpr(zeros),
18468                                    mkexpr(vB)))) );
18469 
18470       // finally, just shift gt,lt to correct position
18471       assign( vD, binop(Iop_ShlN32x4,
18472                         binop(Iop_OrV128,
18473                               binop(Iop_AndV128, mkexpr(gt),
18474                                     unop(Iop_Dup32x4, mkU32(0x2))),
18475                               binop(Iop_AndV128, mkexpr(lt),
18476                                     unop(Iop_Dup32x4, mkU32(0x1)))),
18477                         mkU8(30)) );
18478       break;
18479    }
18480 
18481    default:
18482       vex_printf("dis_av_fp_cmp(ppc)(opc2)\n");
18483       return False;
18484    }
18485 
18486    putVReg( vD_addr, mkexpr(vD) );
18487 
18488    if (flag_rC) {
18489       set_AV_CR6( mkexpr(vD), !cmp_bounds );
18490    }
18491    return True;
18492 }
18493 
18494 /*
18495   AltiVec Floating Point Convert/Round Instructions
18496 */
dis_av_fp_convert(UInt theInstr)18497 static Bool dis_av_fp_convert ( UInt theInstr )
18498 {
18499    /* VX-Form */
18500    UChar opc1     = ifieldOPC(theInstr);
18501    UChar vD_addr  = ifieldRegDS(theInstr);
18502    UChar UIMM_5   = ifieldRegA(theInstr);
18503    UChar vB_addr  = ifieldRegB(theInstr);
18504    UInt  opc2     = IFIELD( theInstr, 0, 11 );
18505 
18506    IRTemp vB        = newTemp(Ity_V128);
18507    IRTemp vScale    = newTemp(Ity_V128);
18508    IRTemp vInvScale = newTemp(Ity_V128);
18509 
18510    float scale, inv_scale;
18511 
18512    assign( vB, getVReg(vB_addr));
18513 
18514    /* scale = 2^UIMM, cast to float, reinterpreted as uint */
18515    scale = (float)( (unsigned int) 1<<UIMM_5 );
18516    assign( vScale, unop(Iop_Dup32x4, mkU32( float_to_bits(scale) )) );
18517    inv_scale = 1/scale;
18518    assign( vInvScale,
18519            unop(Iop_Dup32x4, mkU32( float_to_bits(inv_scale) )) );
18520 
18521    if (opc1 != 0x4) {
18522       vex_printf("dis_av_fp_convert(ppc)(instr)\n");
18523       return False;
18524    }
18525 
18526    switch (opc2) {
18527    case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156)
18528       DIP("vcfux v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
18529       putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
18530                               unop(Iop_I32UtoFx4, mkexpr(vB)),
18531                               mkexpr(vInvScale)) );
18532       return True;
18533 
18534    case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155)
18535       DIP("vcfsx v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
18536 
18537       putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
18538                               unop(Iop_I32StoFx4, mkexpr(vB)),
18539                               mkexpr(vInvScale)) );
18540       return True;
18541 
18542    case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172)
18543       DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
18544       putVReg( vD_addr,
18545                unop(Iop_QFtoI32Ux4_RZ,
18546                     triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
18547                           mkexpr(vB), mkexpr(vScale))) );
18548       return True;
18549 
18550    case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171)
18551       DIP("vctsxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
18552       putVReg( vD_addr,
18553                unop(Iop_QFtoI32Sx4_RZ,
18554                      triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
18555                            mkexpr(vB), mkexpr(vScale))) );
18556       return True;
18557 
18558    default:
18559      break;    // Fall through...
18560    }
18561 
18562    if (UIMM_5 != 0) {
18563       vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n");
18564       return False;
18565    }
18566 
18567    switch (opc2) {
18568    case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231)
18569       DIP("vrfin v%d,v%d\n", vD_addr, vB_addr);
18570       putVReg( vD_addr, unop(Iop_RoundF32x4_RN, mkexpr(vB)) );
18571       break;
18572 
18573    case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233)
18574       DIP("vrfiz v%d,v%d\n", vD_addr, vB_addr);
18575       putVReg( vD_addr, unop(Iop_RoundF32x4_RZ, mkexpr(vB)) );
18576       break;
18577 
18578    case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232)
18579       DIP("vrfip v%d,v%d\n", vD_addr, vB_addr);
18580       putVReg( vD_addr, unop(Iop_RoundF32x4_RP, mkexpr(vB)) );
18581       break;
18582 
18583    case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230)
18584       DIP("vrfim v%d,v%d\n", vD_addr, vB_addr);
18585       putVReg( vD_addr, unop(Iop_RoundF32x4_RM, mkexpr(vB)) );
18586       break;
18587 
18588    default:
18589       vex_printf("dis_av_fp_convert(ppc)(opc2)\n");
18590       return False;
18591    }
18592    return True;
18593 }
18594 
dis_transactional_memory(UInt theInstr,UInt nextInstr,const VexAbiInfo * vbi,DisResult * dres,Bool (* resteerOkFn)(void *,Addr),void * callback_opaque)18595 static Bool dis_transactional_memory ( UInt theInstr, UInt nextInstr,
18596                                        const VexAbiInfo* vbi,
18597                                        /*OUT*/DisResult* dres,
18598                                        Bool (*resteerOkFn)(void*,Addr),
18599                                        void* callback_opaque )
18600 {
18601    UInt   opc2      = IFIELD( theInstr, 1, 10 );
18602 
18603    switch (opc2) {
18604    case 0x28E: {        //tbegin.
18605       /* The current implementation is to just fail the tbegin and execute
18606        * the failure path.  The failure path is assumed to be functionaly
18607        * equivalent to the transactional path with the needed data locking
18608        * to ensure correctness.  The tend is just a noop and shouldn't
18609        * actually get executed.
18610        *   1) set cr0 to 0x2
18611        *   2) Initialize TFHAR to CIA+4
18612        *   3) Initialize TEXASR
18613        *   4) Initialize TFIAR (probably to CIA, ie, the address of tbegin.)
18614        *   5) Continue executing at the next instruction.
18615        */
18616       UInt R = IFIELD( theInstr, 21, 1 );
18617 
18618       ULong tm_reason;
18619       UInt failure_code = 0;  /* Forcing failure, will not be due to tabort
18620                                * or treclaim.
18621                                */
18622       UInt persistant = 1;    /* set persistant since we are always failing
18623                                * the tbegin.
18624                                */
18625       UInt nest_overflow = 1; /* Alowed nesting depth overflow, we use this
18626                                  as the reason for failing the trasaction */
18627       UInt tm_exact   = 1;    /* have exact address for failure */
18628 
18629       DIP("tbegin. %u\n", R);
18630 
18631       /* Set the CR0 field to indicate the tbegin failed.  Then let
18632        * the code do the branch to the failure path.
18633        *
18634        * 000 || 0  Transaction initiation successful,
18635        *           unnested (Transaction state of
18636        *           Non-transactional prior to tbegin.)
18637        * 010 || 0  Transaction initiation successful, nested
18638        *           (Transaction state of Transactional
18639        *           prior to tbegin.)
18640        * 001 || 0  Transaction initiation unsuccessful,
18641        *           (Transaction state of Suspended prior
18642        *           to tbegin.)
18643        */
18644       putCR321( 0, mkU8( 0x2 ) );
18645 
18646       tm_reason = generate_TMreason( failure_code, persistant,
18647                                      nest_overflow, tm_exact );
18648 
18649       storeTMfailure( guest_CIA_curr_instr, tm_reason,
18650                       guest_CIA_curr_instr+4 );
18651 
18652       return True;
18653 
18654       break;
18655    }
18656 
18657    case 0x2AE: {        //tend.
18658       /* The tend. is just a noop.  Do nothing */
18659       UInt A = IFIELD( theInstr, 25, 1 );
18660 
18661       DIP("tend. %u\n", A);
18662       break;
18663    }
18664 
18665    case 0x2EE: {        //tsr.
18666       /* The tsr. is just a noop.  Do nothing */
18667       UInt L = IFIELD( theInstr, 21, 1 );
18668 
18669       DIP("tsr. %u\n", L);
18670       break;
18671    }
18672 
18673    case 0x2CE: {        //tcheck.
18674       /* The tcheck. is just a noop.  Do nothing */
18675       UInt BF = IFIELD( theInstr, 25, 1 );
18676 
18677       DIP("tcheck. %u\n", BF);
18678       break;
18679    }
18680 
18681    case 0x30E: {        //tbortwc.
18682       /* The tabortwc. is just a noop.  Do nothing */
18683       UInt TO = IFIELD( theInstr, 25, 1 );
18684       UInt RA = IFIELD( theInstr, 16, 5 );
18685       UInt RB = IFIELD( theInstr, 11, 5 );
18686 
18687       DIP("tabortwc. %u,%u,%u\n", TO, RA, RB);
18688       break;
18689    }
18690 
18691    case 0x32E: {        //tbortdc.
18692       /* The tabortdc. is just a noop.  Do nothing */
18693       UInt TO = IFIELD( theInstr, 25, 1 );
18694       UInt RA = IFIELD( theInstr, 16, 5 );
18695       UInt RB = IFIELD( theInstr, 11, 5 );
18696 
18697       DIP("tabortdc. %u,%u,%u\n", TO, RA, RB);
18698       break;
18699    }
18700 
18701    case 0x34E: {        //tbortwci.
18702       /* The tabortwci. is just a noop.  Do nothing */
18703       UInt TO = IFIELD( theInstr, 25, 1 );
18704       UInt RA = IFIELD( theInstr, 16, 5 );
18705       UInt SI = IFIELD( theInstr, 11, 5 );
18706 
18707       DIP("tabortwci. %u,%u,%u\n", TO, RA, SI);
18708       break;
18709    }
18710 
18711    case 0x36E: {        //tbortdci.
18712       /* The tabortdci. is just a noop.  Do nothing */
18713       UInt TO = IFIELD( theInstr, 25, 1 );
18714       UInt RA = IFIELD( theInstr, 16, 5 );
18715       UInt SI = IFIELD( theInstr, 11, 5 );
18716 
18717       DIP("tabortdci. %u,%u,%u\n", TO, RA, SI);
18718       break;
18719    }
18720 
18721    case 0x38E: {        //tbort.
18722       /* The tabort. is just a noop.  Do nothing */
18723       UInt RA = IFIELD( theInstr, 16, 5 );
18724 
18725       DIP("tabort. %u\n", RA);
18726       break;
18727    }
18728 
18729    case 0x3AE: {        //treclaim.
18730       /* The treclaim. is just a noop.  Do nothing */
18731       UInt RA = IFIELD( theInstr, 16, 5 );
18732 
18733       DIP("treclaim. %u\n", RA);
18734       break;
18735    }
18736 
18737    case 0x3EE: {        //trechkpt.
18738       /* The trechkpt. is just a noop.  Do nothing */
18739       DIP("trechkpt.\n");
18740       break;
18741    }
18742 
18743    default:
18744       vex_printf("dis_transactional_memory(ppc): unrecognized instruction\n");
18745       return False;
18746    }
18747 
18748    return True;
18749 }
18750 
18751 
18752 /* The 0x3C primary opcode (VSX category) uses several different forms of
18753  * extended opcodes:
18754  *   o XX2-form:
18755  *      - [10:2] (IBM notation [21:29])
18756  *   o XX3-form variants:
18757  *       - variant 1: [10:3] (IBM notation [21:28])
18758  *       - variant 2: [9:3] (IBM notation [22:28])
18759  *       - variant 3: [7:3] (IBM notation [24:28])
18760  *   o XX-4 form:
18761  *      - [10:6] (IBM notation [21:25])
18762  *
18763  * The XX2-form needs bit 0 masked from the standard extended opcode
18764  * as returned by ifieldOPClo10; the XX3-form needs bits 0 and 1 masked;
18765  * and the XX4-form needs bits 0, 1, and 2 masked.  Additionally, the
18766  * XX4 and XX3 (variants 2 and 3) forms need certain bits masked on the
18767  * front end since their encoding does not begin at bit 21 like the standard
18768  * format.
18769  *
18770  * The get_VSX60_opc2() function uses the vsx_insn array below to obtain the
18771  * secondary opcode for such VSX instructions.
18772  *
18773 */
18774 
18775 
18776 struct vsx_insn {
18777    UInt opcode;
18778    const HChar * name;
18779 };
18780 
18781 //  ATTENTION:  Keep this array sorted on the opcocde!!!
18782 static struct vsx_insn vsx_all[] = {
18783       { 0x0, "xsaddsp" },
18784       { 0x4, "xsmaddasp" },
18785       { 0x8, "xxsldwi" },
18786       { 0x14, "xsrsqrtesp" },
18787       { 0x16, "xssqrtsp" },
18788       { 0x18, "xxsel" },
18789       { 0x20, "xssubsp" },
18790       { 0x24, "xsmaddmsp" },
18791       { 0x28, "xxpermdi" },
18792       { 0x34, "xsresp" },
18793       { 0x40, "xsmulsp" },
18794       { 0x44, "xsmsubasp" },
18795       { 0x48, "xxmrghw" },
18796       { 0x60, "xsdivsp" },
18797       { 0x64, "xsmsubmsp" },
18798       { 0x80, "xsadddp" },
18799       { 0x84, "xsmaddadp" },
18800       { 0x8c, "xscmpudp" },
18801       { 0x90, "xscvdpuxws" },
18802       { 0x92, "xsrdpi" },
18803       { 0x94, "xsrsqrtedp" },
18804       { 0x96, "xssqrtdp" },
18805       { 0xa0, "xssubdp" },
18806       { 0xa4, "xsmaddmdp" },
18807       { 0xac, "xscmpodp" },
18808       { 0xb0, "xscvdpsxws" },
18809       { 0xb2, "xsrdpiz" },
18810       { 0xb4, "xsredp" },
18811       { 0xc0, "xsmuldp" },
18812       { 0xc4, "xsmsubadp" },
18813       { 0xc8, "xxmrglw" },
18814       { 0xd2, "xsrdpip" },
18815       { 0xd4, "xstsqrtdp" },
18816       { 0xd6, "xsrdpic" },
18817       { 0xe0, "xsdivdp" },
18818       { 0xe4, "xsmsubmdp" },
18819       { 0xf2, "xsrdpim" },
18820       { 0xf4, "xstdivdp" },
18821       { 0x100, "xvaddsp" },
18822       { 0x104, "xvmaddasp" },
18823       { 0x10c, "xvcmpeqsp" },
18824       { 0x110, "xvcvspuxws" },
18825       { 0x112, "xvrspi" },
18826       { 0x114, "xvrsqrtesp" },
18827       { 0x116, "xvsqrtsp" },
18828       { 0x120, "xvsubsp" },
18829       { 0x124, "xvmaddmsp" },
18830       { 0x12c, "xvcmpgtsp" },
18831       { 0x130, "xvcvspsxws" },
18832       { 0x132, "xvrspiz" },
18833       { 0x134, "xvresp" },
18834       { 0x140, "xvmulsp" },
18835       { 0x144, "xvmsubasp" },
18836       { 0x148, "xxspltw" },
18837       { 0x14c, "xvcmpgesp" },
18838       { 0x150, "xvcvuxwsp" },
18839       { 0x152, "xvrspip" },
18840       { 0x154, "xvtsqrtsp" },
18841       { 0x156, "xvrspic" },
18842       { 0x160, "xvdivsp" },
18843       { 0x164, "xvmsubmsp" },
18844       { 0x170, "xvcvsxwsp" },
18845       { 0x172, "xvrspim" },
18846       { 0x174, "xvtdivsp" },
18847       { 0x180, "xvadddp" },
18848       { 0x184, "xvmaddadp" },
18849       { 0x18c, "xvcmpeqdp" },
18850       { 0x190, "xvcvdpuxws" },
18851       { 0x192, "xvrdpi" },
18852       { 0x194, "xvrsqrtedp" },
18853       { 0x196, "xvsqrtdp" },
18854       { 0x1a0, "xvsubdp" },
18855       { 0x1a4, "xvmaddmdp" },
18856       { 0x1ac, "xvcmpgtdp" },
18857       { 0x1b0, "xvcvdpsxws" },
18858       { 0x1b2, "xvrdpiz" },
18859       { 0x1b4, "xvredp" },
18860       { 0x1c0, "xvmuldp" },
18861       { 0x1c4, "xvmsubadp" },
18862       { 0x1cc, "xvcmpgedp" },
18863       { 0x1d0, "xvcvuxwdp" },
18864       { 0x1d2, "xvrdpip" },
18865       { 0x1d4, "xvtsqrtdp" },
18866       { 0x1d6, "xvrdpic" },
18867       { 0x1e0, "xvdivdp" },
18868       { 0x1e4, "xvmsubmdp" },
18869       { 0x1f0, "xvcvsxwdp" },
18870       { 0x1f2, "xvrdpim" },
18871       { 0x1f4, "xvtdivdp" },
18872       { 0x204, "xsnmaddasp" },
18873       { 0x208, "xxland" },
18874       { 0x212, "xscvdpsp" },
18875       { 0x216, "xscvdpspn" },
18876       { 0x224, "xsnmaddmsp" },
18877       { 0x228, "xxlandc" },
18878       { 0x232, "xxrsp" },
18879       { 0x244, "xsnmsubasp" },
18880       { 0x248, "xxlor" },
18881       { 0x250, "xscvuxdsp" },
18882       { 0x264, "xsnmsubmsp" },
18883       { 0x268, "xxlxor" },
18884       { 0x270, "xscvsxdsp" },
18885       { 0x280, "xsmaxdp" },
18886       { 0x284, "xsnmaddadp" },
18887       { 0x288, "xxlnor" },
18888       { 0x290, "xscvdpuxds" },
18889       { 0x292, "xscvspdp" },
18890       { 0x296, "xscvspdpn" },
18891       { 0x2a0, "xsmindp" },
18892       { 0x2a4, "xsnmaddmdp" },
18893       { 0x2a8, "xxlorc" },
18894       { 0x2b0, "xscvdpsxds" },
18895       { 0x2b2, "xsabsdp" },
18896       { 0x2c0, "xscpsgndp" },
18897       { 0x2c4, "xsnmsubadp" },
18898       { 0x2c8, "xxlnand" },
18899       { 0x2d0, "xscvuxddp" },
18900       { 0x2d2, "xsnabsdp" },
18901       { 0x2e4, "xsnmsubmdp" },
18902       { 0x2e8, "xxleqv" },
18903       { 0x2f0, "xscvsxddp" },
18904       { 0x2f2, "xsnegdp" },
18905       { 0x300, "xvmaxsp" },
18906       { 0x304, "xvnmaddasp" },
18907       { 0x30c, "xvcmpeqsp." },
18908       { 0x310, "xvcvspuxds" },
18909       { 0x312, "xvcvdpsp" },
18910       { 0x320, "xvminsp" },
18911       { 0x324, "xvnmaddmsp" },
18912       { 0x32c, "xvcmpgtsp." },
18913       { 0x330, "xvcvspsxds" },
18914       { 0x332, "xvabssp" },
18915       { 0x340, "xvcpsgnsp" },
18916       { 0x344, "xvnmsubasp" },
18917       { 0x34c, "xvcmpgesp." },
18918       { 0x350, "xvcvuxdsp" },
18919       { 0x352, "xvnabssp" },
18920       { 0x364, "xvnmsubmsp" },
18921       { 0x370, "xvcvsxdsp" },
18922       { 0x372, "xvnegsp" },
18923       { 0x380, "xvmaxdp" },
18924       { 0x384, "xvnmaddadp" },
18925       { 0x38c, "xvcmpeqdp." },
18926       { 0x390, "xvcvdpuxds" },
18927       { 0x392, "xvcvspdp" },
18928       { 0x3a0, "xvmindp" },
18929       { 0x3a4, "xvnmaddmdp" },
18930       { 0x3ac, "xvcmpgtdp." },
18931       { 0x3b0, "xvcvdpsxds" },
18932       { 0x3b2, "xvabsdp" },
18933       { 0x3c0, "xvcpsgndp" },
18934       { 0x3c4, "xvnmsubadp" },
18935       { 0x3cc, "xvcmpgedp." },
18936       { 0x3d0, "xvcvuxddp" },
18937       { 0x3d2, "xvnabsdp" },
18938       { 0x3e4, "xvnmsubmdp" },
18939       { 0x3f0, "xvcvsxddp" },
18940       { 0x3f2, "xvnegdp" }
18941 };
18942 #define VSX_ALL_LEN (sizeof vsx_all / sizeof *vsx_all)
18943 
18944 
18945 // ATTENTION: This search function assumes vsx_all array is sorted.
findVSXextOpCode(UInt opcode)18946 static Int findVSXextOpCode(UInt opcode)
18947 {
18948    Int low, mid, high;
18949    low = 0;
18950    high = VSX_ALL_LEN - 1;
18951    while (low <= high) {
18952       mid = (low + high)/2;
18953       if (opcode < vsx_all[mid].opcode)
18954          high = mid - 1;
18955       else if (opcode > vsx_all[mid].opcode)
18956          low = mid + 1;
18957       else
18958          return mid;
18959    }
18960    return -1;
18961 }
18962 
18963 
18964 /* The full 10-bit extended opcode retrieved via ifieldOPClo10 is
18965  * passed, and we then try to match it up with one of the VSX forms
18966  * below.
18967  */
get_VSX60_opc2(UInt opc2_full)18968 static UInt get_VSX60_opc2(UInt opc2_full)
18969 {
18970 #define XX2_MASK 0x000003FE
18971 #define XX3_1_MASK 0x000003FC
18972 #define XX3_2_MASK 0x000001FC
18973 #define XX3_3_MASK 0x0000007C
18974 #define XX4_MASK 0x00000018
18975    Int ret;
18976    UInt vsxExtOpcode = 0;
18977 
18978    if (( ret = findVSXextOpCode(opc2_full & XX2_MASK)) >= 0)
18979       vsxExtOpcode = vsx_all[ret].opcode;
18980    else if (( ret = findVSXextOpCode(opc2_full & XX3_1_MASK)) >= 0)
18981       vsxExtOpcode = vsx_all[ret].opcode;
18982    else if (( ret = findVSXextOpCode(opc2_full & XX3_2_MASK)) >= 0)
18983       vsxExtOpcode = vsx_all[ret].opcode;
18984    else if (( ret = findVSXextOpCode(opc2_full & XX3_3_MASK)) >= 0)
18985       vsxExtOpcode = vsx_all[ret].opcode;
18986    else if (( ret = findVSXextOpCode(opc2_full & XX4_MASK)) >= 0)
18987       vsxExtOpcode = vsx_all[ret].opcode;
18988 
18989    return vsxExtOpcode;
18990 }
18991 
18992 /*------------------------------------------------------------*/
18993 /*--- Disassemble a single instruction                     ---*/
18994 /*------------------------------------------------------------*/
18995 
18996 /* Disassemble a single instruction into IR.  The instruction
18997    is located in host memory at &guest_code[delta]. */
18998 
18999 static
disInstr_PPC_WRK(Bool (* resteerOkFn)(void *,Addr),Bool resteerCisOk,void * callback_opaque,Long delta64,const VexArchInfo * archinfo,const VexAbiInfo * abiinfo,Bool sigill_diag)19000 DisResult disInstr_PPC_WRK (
19001              Bool         (*resteerOkFn) ( /*opaque*/void*, Addr ),
19002              Bool         resteerCisOk,
19003              void*        callback_opaque,
19004              Long         delta64,
19005              const VexArchInfo* archinfo,
19006              const VexAbiInfo*  abiinfo,
19007              Bool         sigill_diag
19008           )
19009 {
19010    UChar     opc1;
19011    UInt      opc2;
19012    DisResult dres;
19013    UInt      theInstr;
19014    IRType    ty = mode64 ? Ity_I64 : Ity_I32;
19015    Bool      allow_F  = False;
19016    Bool      allow_V  = False;
19017    Bool      allow_FX = False;
19018    Bool      allow_GX = False;
19019    Bool      allow_VX = False;  // Equates to "supports Power ISA 2.06
19020    Bool      allow_DFP = False;
19021    Bool      allow_isa_2_07 = False;
19022    UInt      hwcaps = archinfo->hwcaps;
19023    Long      delta;
19024 
19025    /* What insn variants are we supporting today? */
19026    if (mode64) {
19027       allow_F  = True;
19028       allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC64_V));
19029       allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC64_FX));
19030       allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC64_GX));
19031       allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC64_VX));
19032       allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC64_DFP));
19033       allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC64_ISA2_07));
19034    } else {
19035       allow_F  = (0 != (hwcaps & VEX_HWCAPS_PPC32_F));
19036       allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC32_V));
19037       allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC32_FX));
19038       allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC32_GX));
19039       allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC32_VX));
19040       allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC32_DFP));
19041       allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC32_ISA2_07));
19042    }
19043 
19044    /* The running delta */
19045    delta = (Long)mkSzAddr(ty, (ULong)delta64);
19046 
19047    /* Set result defaults. */
19048    dres.whatNext    = Dis_Continue;
19049    dres.len         = 0;
19050    dres.continueAt  = 0;
19051    dres.jk_StopHere = Ijk_INVALID;
19052 
19053    /* At least this is simple on PPC32: insns are all 4 bytes long, and
19054       4-aligned.  So just fish the whole thing out of memory right now
19055       and have done. */
19056    theInstr = getUIntPPCendianly( &guest_code[delta] );
19057 
19058    if (0) vex_printf("insn: 0x%x\n", theInstr);
19059 
19060    DIP("\t0x%llx:  ", (ULong)guest_CIA_curr_instr);
19061 
19062    /* Spot "Special" instructions (see comment at top of file). */
19063    {
19064       const UChar* code = guest_code + delta;
19065       /* Spot the 16-byte preamble:
19066          32-bit mode:
19067             5400183E  rlwinm 0,0,3,0,31
19068             5400683E  rlwinm 0,0,13,0,31
19069             5400E83E  rlwinm 0,0,29,0,31
19070             5400983E  rlwinm 0,0,19,0,31
19071          64-bit mode:
19072             78001800  rotldi 0,0,3
19073             78006800  rotldi 0,0,13
19074             7800E802  rotldi 0,0,61
19075             78009802  rotldi 0,0,51
19076       */
19077       UInt word1 = mode64 ? 0x78001800 : 0x5400183E;
19078       UInt word2 = mode64 ? 0x78006800 : 0x5400683E;
19079       UInt word3 = mode64 ? 0x7800E802 : 0x5400E83E;
19080       UInt word4 = mode64 ? 0x78009802 : 0x5400983E;
19081       Bool is_special_preamble = False;
19082       if (getUIntPPCendianly(code+ 0) == word1 &&
19083           getUIntPPCendianly(code+ 4) == word2 &&
19084           getUIntPPCendianly(code+ 8) == word3 &&
19085           getUIntPPCendianly(code+12) == word4) {
19086          is_special_preamble = True;
19087       } else if (! mode64 &&
19088                  getUIntPPCendianly(code+ 0) == 0x54001800 &&
19089                  getUIntPPCendianly(code+ 4) == 0x54006800 &&
19090                  getUIntPPCendianly(code+ 8) == 0x5400E800 &&
19091                  getUIntPPCendianly(code+12) == 0x54009800) {
19092          static Bool reported = False;
19093          if (!reported) {
19094             vex_printf("disInstr(ppc): old ppc32 instruction magic detected. Code might clobber r0.\n");
19095             vex_printf("disInstr(ppc): source needs to be recompiled against latest valgrind.h.\n");
19096             reported = True;
19097          }
19098          is_special_preamble = True;
19099       }
19100       if (is_special_preamble) {
19101          /* Got a "Special" instruction preamble.  Which one is it? */
19102          if (getUIntPPCendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) {
19103             /* %R3 = client_request ( %R4 ) */
19104             DIP("r3 = client_request ( %%r4 )\n");
19105             delta += 20;
19106             putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta ));
19107             dres.jk_StopHere = Ijk_ClientReq;
19108             dres.whatNext    = Dis_StopHere;
19109             goto decode_success;
19110          }
19111          else
19112          if (getUIntPPCendianly(code+16) == 0x7C421378 /* or 2,2,2 */) {
19113             /* %R3 = guest_NRADDR */
19114             DIP("r3 = guest_NRADDR\n");
19115             delta += 20;
19116             dres.len = 20;
19117             putIReg(3, IRExpr_Get( OFFB_NRADDR, ty ));
19118             goto decode_success;
19119          }
19120          else
19121          if (getUIntPPCendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) {
19122             delta += 20;
19123             if (host_endness == VexEndnessLE) {
19124                 /*  branch-and-link-to-noredir %R12 */
19125                 DIP("branch-and-link-to-noredir r12\n");
19126                 putGST( PPC_GST_LR,
19127                         mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
19128                 putGST( PPC_GST_CIA, getIReg(12));
19129             } else {
19130                 /*  branch-and-link-to-noredir %R11 */
19131                 DIP("branch-and-link-to-noredir r11\n");
19132                 putGST( PPC_GST_LR,
19133                         mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
19134                 putGST( PPC_GST_CIA, getIReg(11));
19135             }
19136             dres.jk_StopHere = Ijk_NoRedir;
19137             dres.whatNext    = Dis_StopHere;
19138             goto decode_success;
19139          }
19140          else
19141          if (getUIntPPCendianly(code+16) == 0x7C842378 /* or 4,4,4 */) {
19142             /* %R3 = guest_NRADDR_GPR2 */
19143             DIP("r3 = guest_NRADDR_GPR2\n");
19144             delta += 20;
19145             dres.len = 20;
19146             putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty ));
19147             goto decode_success;
19148          }
19149          else
19150          if (getUIntPPCendianly(code+16) == 0x7CA52B78 /* or 5,5,5 */) {
19151             DIP("IR injection\n");
19152             if (host_endness == VexEndnessBE)
19153                vex_inject_ir(irsb, Iend_BE);
19154             else
19155                vex_inject_ir(irsb, Iend_LE);
19156 
19157             delta += 20;
19158             dres.len = 20;
19159 
19160             // Invalidate the current insn. The reason is that the IRop we're
19161             // injecting here can change. In which case the translation has to
19162             // be redone. For ease of handling, we simply invalidate all the
19163             // time.
19164 
19165             stmt(IRStmt_Put(OFFB_CMSTART, mkSzImm(ty, guest_CIA_curr_instr)));
19166             stmt(IRStmt_Put(OFFB_CMLEN,   mkSzImm(ty, 20)));
19167 
19168             putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta ));
19169             dres.whatNext    = Dis_StopHere;
19170             dres.jk_StopHere = Ijk_InvalICache;
19171             goto decode_success;
19172          }
19173          /* We don't know what it is.  Set opc1/opc2 so decode_failure
19174             can print the insn following the Special-insn preamble. */
19175          theInstr = getUIntPPCendianly(code+16);
19176          opc1     = ifieldOPC(theInstr);
19177          opc2     = ifieldOPClo10(theInstr);
19178          goto decode_failure;
19179          /*NOTREACHED*/
19180       }
19181    }
19182 
19183    opc1 = ifieldOPC(theInstr);
19184    opc2 = ifieldOPClo10(theInstr);
19185 
19186    // Note: all 'reserved' bits must be cleared, else invalid
19187    switch (opc1) {
19188 
19189    /* Integer Arithmetic Instructions */
19190    case 0x0C: case 0x0D: case 0x0E:  // addic, addic., addi
19191    case 0x0F: case 0x07: case 0x08:  // addis, mulli,  subfic
19192       if (dis_int_arith( theInstr )) goto decode_success;
19193       goto decode_failure;
19194 
19195    /* Integer Compare Instructions */
19196    case 0x0B: case 0x0A: // cmpi, cmpli
19197       if (dis_int_cmp( theInstr )) goto decode_success;
19198       goto decode_failure;
19199 
19200    /* Integer Logical Instructions */
19201    case 0x1C: case 0x1D: case 0x18: // andi., andis., ori
19202    case 0x19: case 0x1A: case 0x1B: // oris,  xori,   xoris
19203       if (dis_int_logic( theInstr )) goto decode_success;
19204       goto decode_failure;
19205 
19206    /* Integer Rotate Instructions */
19207    case 0x14: case 0x15:  case 0x17: // rlwimi, rlwinm, rlwnm
19208       if (dis_int_rot( theInstr )) goto decode_success;
19209       goto decode_failure;
19210 
19211    /* 64bit Integer Rotate Instructions */
19212    case 0x1E: // rldcl, rldcr, rldic, rldicl, rldicr, rldimi
19213       if (!mode64) goto decode_failure;
19214       if (dis_int_rot( theInstr )) goto decode_success;
19215       goto decode_failure;
19216 
19217    /* Integer Load Instructions */
19218    case 0x22: case 0x23: case 0x2A: // lbz,  lbzu, lha
19219    case 0x2B: case 0x28: case 0x29: // lhau, lhz,  lhzu
19220    case 0x20: case 0x21:            // lwz,  lwzu
19221       if (dis_int_load( theInstr )) goto decode_success;
19222       goto decode_failure;
19223 
19224    /* Integer Store Instructions */
19225    case 0x26: case 0x27: case 0x2C: // stb,  stbu, sth
19226    case 0x2D: case 0x24: case 0x25: // sthu, stw,  stwu
19227       if (dis_int_store( theInstr, abiinfo )) goto decode_success;
19228       goto decode_failure;
19229 
19230    /* Integer Load and Store Multiple Instructions */
19231    case 0x2E: case 0x2F: // lmw, stmw
19232       if (dis_int_ldst_mult( theInstr )) goto decode_success;
19233       goto decode_failure;
19234 
19235    /* Branch Instructions */
19236    case 0x12: case 0x10: // b, bc
19237       if (dis_branch(theInstr, abiinfo, &dres,
19238                                resteerOkFn, callback_opaque))
19239          goto decode_success;
19240       goto decode_failure;
19241 
19242    /* System Linkage Instructions */
19243    case 0x11: // sc
19244       if (dis_syslink(theInstr, abiinfo, &dres)) goto decode_success;
19245       goto decode_failure;
19246 
19247    /* Trap Instructions */
19248    case 0x02:    // tdi
19249       if (!mode64) goto decode_failure;
19250       if (dis_trapi(theInstr, &dres)) goto decode_success;
19251       goto decode_failure;
19252 
19253    case 0x03:   // twi
19254       if (dis_trapi(theInstr, &dres)) goto decode_success;
19255       goto decode_failure;
19256 
19257    /* Floating Point Load Instructions */
19258    case 0x30: case 0x31: case 0x32: // lfs, lfsu, lfd
19259    case 0x33:                       // lfdu
19260       if (!allow_F) goto decode_noF;
19261       if (dis_fp_load( theInstr )) goto decode_success;
19262       goto decode_failure;
19263 
19264    /* Floating Point Store Instructions */
19265    case 0x34: case 0x35: case 0x36: // stfsx, stfsux, stfdx
19266    case 0x37:                       // stfdux
19267       if (!allow_F) goto decode_noF;
19268       if (dis_fp_store( theInstr )) goto decode_success;
19269       goto decode_failure;
19270 
19271       /* Floating Point Load Double Pair Instructions */
19272    case 0x39: case 0x3D:
19273       if (!allow_F) goto decode_noF;
19274       if (dis_fp_pair( theInstr )) goto decode_success;
19275       goto decode_failure;
19276 
19277    /* 128-bit Integer Load */
19278    case 0x38:  // lq
19279       if (dis_int_load( theInstr )) goto decode_success;
19280       goto decode_failure;
19281 
19282    /* 64bit Integer Loads */
19283    case 0x3A:  // ld, ldu, lwa
19284       if (!mode64) goto decode_failure;
19285       if (dis_int_load( theInstr )) goto decode_success;
19286       goto decode_failure;
19287 
19288    case 0x3B:
19289       if (!allow_F) goto decode_noF;
19290       opc2 = ifieldOPClo10(theInstr);
19291 
19292       switch (opc2) {
19293          case 0x2:    // dadd - DFP Add
19294          case 0x202:  // dsub - DFP Subtract
19295          case 0x22:   // dmul - DFP Mult
19296          case 0x222:  // ddiv - DFP Divide
19297             if (!allow_DFP) goto decode_noDFP;
19298             if (dis_dfp_arith( theInstr ))
19299                goto decode_success;
19300          case 0x82:   // dcmpo, DFP comparison ordered instruction
19301          case 0x282:  // dcmpu, DFP comparison unordered instruction
19302             if (!allow_DFP) goto decode_noDFP;
19303             if (dis_dfp_compare( theInstr ) )
19304                goto decode_success;
19305             goto decode_failure;
19306          case 0x102: // dctdp  - DFP convert to DFP long
19307          case 0x302: // drsp   - DFP round to dfp short
19308          case 0x122: // dctfix - DFP convert to fixed
19309             if (!allow_DFP) goto decode_noDFP;
19310             if (dis_dfp_fmt_conv( theInstr ))
19311                goto decode_success;
19312             goto decode_failure;
19313          case 0x322: // POWER 7 inst, dcffix - DFP convert from fixed
19314             if (!allow_VX)
19315                goto decode_failure;
19316             if (!allow_DFP) goto decode_noDFP;
19317             if (dis_dfp_fmt_conv( theInstr ))
19318                goto decode_success;
19319             goto decode_failure;
19320          case 0x2A2: // dtstsf - DFP number of significant digits
19321             if (!allow_DFP) goto decode_noDFP;
19322             if (dis_dfp_significant_digits(theInstr))
19323                goto decode_success;
19324             goto decode_failure;
19325          case 0x142: // ddedpd   DFP Decode DPD to BCD
19326          case 0x342: // denbcd   DFP Encode BCD to DPD
19327             if (!allow_DFP) goto decode_noDFP;
19328             if (dis_dfp_bcd(theInstr))
19329                goto decode_success;
19330             goto decode_failure;
19331          case 0x162:  // dxex - Extract exponent
19332          case 0x362:  // diex - Insert exponent
19333             if (!allow_DFP) goto decode_noDFP;
19334             if (dis_dfp_extract_insert( theInstr ) )
19335                goto decode_success;
19336             goto decode_failure;
19337          case 0x3CE: // fcfidus (implemented as native insn)
19338             if (!allow_VX)
19339                goto decode_noVX;
19340             if (dis_fp_round( theInstr ))
19341                goto decode_success;
19342             goto decode_failure;
19343          case 0x34E: // fcfids
19344             if (dis_fp_round( theInstr ))
19345                goto decode_success;
19346             goto decode_failure;
19347       }
19348 
19349       opc2 = ifieldOPClo9( theInstr );
19350       switch (opc2) {
19351       case 0x42: // dscli, DFP shift left
19352       case 0x62: // dscri, DFP shift right
19353          if (!allow_DFP) goto decode_noDFP;
19354          if (dis_dfp_shift( theInstr ))
19355             goto decode_success;
19356          goto decode_failure;
19357       case 0xc2:  // dtstdc, DFP test data class
19358       case 0xe2:  // dtstdg, DFP test data group
19359          if (!allow_DFP) goto decode_noDFP;
19360          if (dis_dfp_class_test( theInstr ))
19361             goto decode_success;
19362          goto decode_failure;
19363       }
19364 
19365       opc2 = ifieldOPClo8( theInstr );
19366       switch (opc2) {
19367       case 0x3:   // dqua  - DFP Quantize
19368       case 0x23:  // drrnd - DFP Reround
19369       case 0x43:  // dquai - DFP Quantize immediate
19370          if (!allow_DFP) goto decode_noDFP;
19371          if (dis_dfp_quantize_sig_rrnd( theInstr ) )
19372             goto decode_success;
19373          goto decode_failure;
19374       case 0xA2: // dtstex - DFP Test exponent
19375          if (!allow_DFP) goto decode_noDFP;
19376          if (dis_dfp_exponent_test( theInstr ) )
19377             goto decode_success;
19378          goto decode_failure;
19379       case 0x63: // drintx - Round to an integer value
19380       case 0xE3: // drintn - Round to an integer value
19381          if (!allow_DFP) goto decode_noDFP;
19382          if (dis_dfp_round( theInstr ) ) {
19383             goto decode_success;
19384          }
19385          goto decode_failure;
19386       default:
19387          break;  /* fall through to next opc2 check */
19388       }
19389 
19390       opc2 = IFIELD(theInstr, 1, 5);
19391       switch (opc2) {
19392       /* Floating Point Arith Instructions */
19393       case 0x12: case 0x14: case 0x15: // fdivs,  fsubs, fadds
19394       case 0x19:                       // fmuls
19395          if (dis_fp_arith(theInstr)) goto decode_success;
19396          goto decode_failure;
19397       case 0x16:                       // fsqrts
19398          if (!allow_FX) goto decode_noFX;
19399          if (dis_fp_arith(theInstr)) goto decode_success;
19400          goto decode_failure;
19401       case 0x18:                       // fres
19402          if (!allow_GX) goto decode_noGX;
19403          if (dis_fp_arith(theInstr)) goto decode_success;
19404          goto decode_failure;
19405 
19406       /* Floating Point Mult-Add Instructions */
19407       case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs
19408       case 0x1F:                       // fnmadds
19409          if (dis_fp_multadd(theInstr)) goto decode_success;
19410          goto decode_failure;
19411 
19412       case 0x1A:                       // frsqrtes
19413          if (!allow_GX) goto decode_noGX;
19414          if (dis_fp_arith(theInstr)) goto decode_success;
19415          goto decode_failure;
19416 
19417       default:
19418          goto decode_failure;
19419       }
19420       break;
19421 
19422    case 0x3C: // VSX instructions (except load/store)
19423    {
19424       // All of these VSX instructions use some VMX facilities, so
19425       // if allow_V is not set, we'll skip trying to decode.
19426       if (!allow_V) goto decode_noVX;
19427 
19428       UInt vsxOpc2 = get_VSX60_opc2(opc2);
19429       /* The vsxOpc2 returned is the "normalized" value, representing the
19430        * instructions secondary opcode as taken from the standard secondary
19431        * opcode field [21:30] (IBM notatition), even if the actual field
19432        * is non-standard.  These normalized values are given in the opcode
19433        * appendices of the ISA 2.06 document.
19434        */
19435 
19436       switch (vsxOpc2) {
19437          case 0x8: case 0x28: case 0x48: case 0xc8: // xxsldwi, xxpermdi, xxmrghw, xxmrglw
19438          case 0x018: case 0x148: // xxsel, xxspltw
19439             if (dis_vx_permute_misc(theInstr, vsxOpc2)) goto decode_success;
19440             goto decode_failure;
19441          case 0x268: case 0x248: case 0x288: // xxlxor, xxlor, xxlnor,
19442          case 0x208: case 0x228: case 0x2A8: // xxland, xxlandc, xxlorc
19443          case 0x2C8: case 0x2E8: // xxlnand, xxleqv
19444             if (dis_vx_logic(theInstr, vsxOpc2)) goto decode_success;
19445             goto decode_failure;
19446          case 0x2B2: case 0x2C0: // xsabsdp, xscpsgndp
19447          case 0x2D2: case 0x2F2: // xsnabsdp, xsnegdp
19448          case 0x280: case 0x2A0: // xsmaxdp, xsmindp
19449          case 0x0F2: case 0x0D2: // xsrdpim, xsrdpip
19450          case 0x034: case 0x014: // xsresp, xsrsqrtesp
19451          case 0x0B4: case 0x094: // xsredp, xsrsqrtedp
19452          case 0x0D6: case 0x0B2: // xsrdpic, xsrdpiz
19453          case 0x092: case 0x232: // xsrdpi, xsrsp
19454             if (dis_vxs_misc(theInstr, vsxOpc2)) goto decode_success;
19455             goto decode_failure;
19456          case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
19457             if (dis_vx_cmp(theInstr, vsxOpc2)) goto decode_success;
19458             goto decode_failure;
19459          case 0x0:   case 0x020: // xsaddsp, xssubsp
19460          case 0x080:             // xsadddp
19461          case 0x060: case 0x0E0: // xsdivsp, xsdivdp
19462          case 0x004: case 0x024: // xsmaddasp, xsmaddmsp
19463          case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp
19464          case 0x044: case 0x064: // xsmsubasp, xsmsubmsp
19465          case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp
19466          case 0x204: case 0x224: // xsnmaddasp, xsnmaddmsp
19467          case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp
19468          case 0x244: case 0x264: // xsnmsubasp, xsnmsubmsp
19469          case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp
19470          case 0x040: case 0x0C0: // xsmulsp, xsmuldp
19471          case 0x0A0:             // xssubdp
19472          case 0x016: case 0x096: // xssqrtsp,xssqrtdp
19473          case 0x0F4: case 0x0D4: // xstdivdp, xstsqrtdp
19474             if (dis_vxs_arith(theInstr, vsxOpc2)) goto decode_success;
19475             goto decode_failure;
19476          case 0x180: // xvadddp
19477          case 0x1E0: // xvdivdp
19478          case 0x1C0: // xvmuldp
19479          case 0x1A0: // xvsubdp
19480          case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp
19481          case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp
19482          case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp
19483          case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp
19484          case 0x1D4: case 0x1F4: // xvtsqrtdp, xvtdivdp
19485          case 0x196: // xvsqrtdp
19486             if (dis_vxv_dp_arith(theInstr, vsxOpc2)) goto decode_success;
19487             goto decode_failure;
19488          case 0x100: // xvaddsp
19489          case 0x160: // xvdivsp
19490          case 0x140: // xvmulsp
19491          case 0x120: // xvsubsp
19492          case 0x104: case 0x124: // xvmaddasp, xvmaddmsp
19493          case 0x144: case 0x164: // xvmsubasp, xvmsubmsp
19494          case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp
19495          case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp
19496          case 0x154: case 0x174: // xvtsqrtsp, xvtdivsp
19497          case 0x116: // xvsqrtsp
19498             if (dis_vxv_sp_arith(theInstr, vsxOpc2)) goto decode_success;
19499             goto decode_failure;
19500 
19501          case 0x250:             // xscvuxdsp
19502          case 0x2D0: case 0x3d0: // xscvuxddp, xvcvuxddp
19503          case 0x350: case 0x1d0: // xvcvuxdsp, xvcvuxwdp
19504          case 0x090: // xscvdpuxws
19505             // The above VSX conversion instructions employ some ISA 2.06
19506             // floating point conversion instructions under the covers,
19507             // so if allow_VX (which means "supports ISA 2.06") is not set,
19508             // we'll skip the decode.
19509             if (!allow_VX) goto decode_noVX;
19510             if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
19511             goto decode_failure;
19512 
19513          case 0x2B0: // xscvdpsxds
19514          case 0x270: case 0x2F0: // xscvsxdsp, xscvsxddp
19515          case 0x1b0: case 0x130: // xvcvdpsxws, xvcvspsxws
19516          case 0x0b0: case 0x290: // xscvdpsxws, xscvdpuxds
19517          case 0x212: case 0x216: // xscvdpsp, xscvdpspn
19518          case 0x292: case 0x296: // xscvspdp, xscvspdpn
19519          case 0x312: // xvcvdpsp
19520          case 0x390: case 0x190: // xvcvdpuxds, xvcvdpuxws
19521          case 0x3B0: case 0x310: // xvcvdpsxds, xvcvspuxds
19522          case 0x392: case 0x330: // xvcvspdp, xvcvspsxds
19523          case 0x110: case 0x3f0: // xvcvspuxws, xvcvsxddp
19524          case 0x370: case 0x1f0: // xvcvsxdsp, xvcvsxwdp
19525          case 0x170: case 0x150: // xvcvsxwsp, xvcvuxwsp
19526             if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
19527             goto decode_failure;
19528 
19529          case 0x18C: case 0x38C: // xvcmpeqdp[.]
19530          case 0x10C: case 0x30C: // xvcmpeqsp[.]
19531          case 0x14C: case 0x34C: // xvcmpgesp[.]
19532          case 0x12C: case 0x32C: // xvcmpgtsp[.]
19533          case 0x1CC: case 0x3CC: // xvcmpgedp[.]
19534          case 0x1AC: case 0x3AC: // xvcmpgtdp[.]
19535              if (dis_vvec_cmp(theInstr, vsxOpc2)) goto decode_success;
19536              goto decode_failure;
19537 
19538          case 0x134:  // xvresp
19539          case 0x1B4:  // xvredp
19540          case 0x194: case 0x114: // xvrsqrtedp, xvrsqrtesp
19541          case 0x380: case 0x3A0: // xvmaxdp, xvmindp
19542          case 0x300: case 0x320: // xvmaxsp, xvminsp
19543          case 0x3C0: case 0x340: // xvcpsgndp, xvcpsgnsp
19544          case 0x3B2: case 0x332: // xvabsdp, xvabssp
19545          case 0x3D2: case 0x352: // xvnabsdp, xvnabssp
19546          case 0x192: case 0x1D6: // xvrdpi, xvrdpic
19547          case 0x1F2: case 0x1D2: // xvrdpim, xvrdpip
19548          case 0x1B2: case 0x3F2: // xvrdpiz, xvnegdp
19549          case 0x112: case 0x156: // xvrspi, xvrspic
19550          case 0x172: case 0x152: // xvrspim, xvrspip
19551          case 0x132: // xvrspiz
19552             if (dis_vxv_misc(theInstr, vsxOpc2)) goto decode_success;
19553             goto decode_failure;
19554 
19555          default:
19556             goto decode_failure;
19557       }
19558       break;
19559    }
19560 
19561    /* 64bit Integer Stores */
19562    case 0x3E:  // std, stdu, stq
19563       if (dis_int_store( theInstr, abiinfo )) goto decode_success;
19564       goto decode_failure;
19565 
19566    case 0x3F:
19567       if (!allow_F) goto decode_noF;
19568       /* Instrs using opc[1:5] never overlap instrs using opc[1:10],
19569          so we can simply fall through the first switch statement */
19570 
19571       opc2 = IFIELD(theInstr, 1, 5);
19572       switch (opc2) {
19573       /* Floating Point Arith Instructions */
19574       case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd
19575       case 0x19:                       // fmul
19576          if (dis_fp_arith(theInstr)) goto decode_success;
19577          goto decode_failure;
19578       case 0x16:                       // fsqrt
19579          if (!allow_FX) goto decode_noFX;
19580          if (dis_fp_arith(theInstr)) goto decode_success;
19581          goto decode_failure;
19582       case 0x17: case 0x1A:            // fsel, frsqrte
19583          if (!allow_GX) goto decode_noGX;
19584          if (dis_fp_arith(theInstr)) goto decode_success;
19585          goto decode_failure;
19586 
19587       /* Floating Point Mult-Add Instructions */
19588       case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub
19589       case 0x1F:                       // fnmadd
19590          if (dis_fp_multadd(theInstr)) goto decode_success;
19591          goto decode_failure;
19592 
19593       case 0x18:                       // fre
19594          if (!allow_GX) goto decode_noGX;
19595          if (dis_fp_arith(theInstr)) goto decode_success;
19596          goto decode_failure;
19597 
19598       default:
19599          break; // Fall through
19600       }
19601 
19602       opc2 = IFIELD(theInstr, 1, 10);
19603       switch (opc2) {
19604       /* 128-bit DFP instructions */
19605       case 0x2:    // daddq - DFP Add
19606       case 0x202:  // dsubq - DFP Subtract
19607       case 0x22:   // dmulq - DFP Mult
19608       case 0x222:  // ddivq - DFP Divide
19609          if (!allow_DFP) goto decode_noDFP;
19610          if (dis_dfp_arithq( theInstr ))
19611             goto decode_success;
19612          goto decode_failure;
19613       case 0x162:  // dxexq - DFP Extract exponent
19614       case 0x362:  // diexq - DFP Insert exponent
19615          if (!allow_DFP) goto decode_noDFP;
19616          if (dis_dfp_extract_insertq( theInstr ))
19617             goto decode_success;
19618          goto decode_failure;
19619 
19620       case 0x82:   // dcmpoq, DFP comparison ordered instruction
19621       case 0x282:  // dcmpuq, DFP comparison unordered instruction
19622          if (!allow_DFP) goto decode_noDFP;
19623          if (dis_dfp_compare( theInstr ) )
19624             goto decode_success;
19625          goto decode_failure;
19626 
19627       case 0x102: // dctqpq  - DFP convert to DFP extended
19628       case 0x302: // drdpq   - DFP round to dfp Long
19629       case 0x122: // dctfixq - DFP convert to fixed quad
19630       case 0x322: // dcffixq - DFP convert from fixed quad
19631          if (!allow_DFP) goto decode_noDFP;
19632          if (dis_dfp_fmt_convq( theInstr ))
19633             goto decode_success;
19634          goto decode_failure;
19635 
19636       case 0x2A2: // dtstsfq - DFP number of significant digits
19637          if (!allow_DFP) goto decode_noDFP;
19638          if (dis_dfp_significant_digits(theInstr))
19639             goto decode_success;
19640          goto decode_failure;
19641 
19642       case 0x142: // ddedpdq   DFP Decode DPD to BCD
19643       case 0x342: // denbcdq   DFP Encode BCD to DPD
19644          if (!allow_DFP) goto decode_noDFP;
19645          if (dis_dfp_bcdq(theInstr))
19646             goto decode_success;
19647          goto decode_failure;
19648 
19649       /* Floating Point Compare Instructions */
19650       case 0x000: // fcmpu
19651       case 0x020: // fcmpo
19652          if (dis_fp_cmp(theInstr)) goto decode_success;
19653          goto decode_failure;
19654 
19655       case 0x080: // ftdiv
19656       case 0x0A0: // ftsqrt
19657          if (dis_fp_tests(theInstr)) goto decode_success;
19658          goto decode_failure;
19659 
19660       /* Floating Point Rounding/Conversion Instructions */
19661       case 0x00C: // frsp
19662       case 0x00E: // fctiw
19663       case 0x00F: // fctiwz
19664       case 0x32E: // fctid
19665       case 0x32F: // fctidz
19666       case 0x34E: // fcfid
19667          if (dis_fp_round(theInstr)) goto decode_success;
19668          goto decode_failure;
19669       case 0x3CE: case 0x3AE: case 0x3AF: // fcfidu, fctidu[z] (implemented as native insns)
19670       case 0x08F: case 0x08E: // fctiwu[z] (implemented as native insns)
19671          if (!allow_VX) goto decode_noVX;
19672          if (dis_fp_round(theInstr)) goto decode_success;
19673          goto decode_failure;
19674 
19675       /* Power6 rounding stuff */
19676       case 0x1E8: // frim
19677       case 0x1C8: // frip
19678       case 0x188: // frin
19679       case 0x1A8: // friz
19680          /* A hack to check for P6 capability . . . */
19681          if ((allow_F && allow_V && allow_FX && allow_GX) &&
19682              (dis_fp_round(theInstr)))
19683             goto decode_success;
19684          goto decode_failure;
19685 
19686       /* Floating Point Move Instructions */
19687       case 0x008: // fcpsgn
19688       case 0x028: // fneg
19689       case 0x048: // fmr
19690       case 0x088: // fnabs
19691       case 0x108: // fabs
19692          if (dis_fp_move( theInstr )) goto decode_success;
19693          goto decode_failure;
19694 
19695       case 0x3c6: case 0x346:          // fmrgew, fmrgow
19696          if (dis_fp_merge( theInstr )) goto decode_success;
19697          goto decode_failure;
19698 
19699       /* Floating Point Status/Control Register Instructions */
19700       case 0x026: // mtfsb1
19701       case 0x040: // mcrfs
19702       case 0x046: // mtfsb0
19703       case 0x086: // mtfsfi
19704       case 0x247: // mffs
19705       case 0x2C7: // mtfsf
19706          // Some of the above instructions need to know more about the
19707          // ISA level supported by the host.
19708          if (dis_fp_scr( theInstr, allow_GX )) goto decode_success;
19709          goto decode_failure;
19710 
19711       default:
19712          break; // Fall through...
19713       }
19714 
19715       opc2 = ifieldOPClo9( theInstr );
19716       switch (opc2) {
19717       case 0x42: // dscli, DFP shift left
19718       case 0x62: // dscri, DFP shift right
19719          if (!allow_DFP) goto decode_noDFP;
19720          if (dis_dfp_shiftq( theInstr ))
19721             goto decode_success;
19722          goto decode_failure;
19723       case 0xc2:  // dtstdc, DFP test data class
19724       case 0xe2:  // dtstdg, DFP test data group
19725          if (!allow_DFP) goto decode_noDFP;
19726          if (dis_dfp_class_test( theInstr ))
19727             goto decode_success;
19728          goto decode_failure;
19729       default:
19730          break;
19731       }
19732 
19733       opc2 = ifieldOPClo8( theInstr );
19734       switch (opc2) {
19735       case 0x3:   // dquaq  - DFP Quantize Quad
19736       case 0x23:  // drrndq - DFP Reround Quad
19737       case 0x43:  // dquaiq - DFP Quantize immediate Quad
19738          if (!allow_DFP) goto decode_noDFP;
19739          if (dis_dfp_quantize_sig_rrndq( theInstr ))
19740             goto decode_success;
19741          goto decode_failure;
19742       case 0xA2: // dtstexq - DFP Test exponent Quad
19743          if (!allow_DFP) goto decode_noDFP;
19744          if (dis_dfp_exponent_test( theInstr ) )
19745             goto decode_success;
19746          goto decode_failure;
19747       case 0x63:  // drintxq - DFP Round to an integer value
19748       case 0xE3:  // drintnq - DFP Round to an integer value
19749          if (!allow_DFP) goto decode_noDFP;
19750          if (dis_dfp_roundq( theInstr ))
19751             goto decode_success;
19752          goto decode_failure;
19753 
19754       default:
19755          goto decode_failure;
19756       }
19757       break;
19758 
19759    case 0x13:
19760       switch (opc2) {
19761 
19762       /* Condition Register Logical Instructions */
19763       case 0x101: case 0x081: case 0x121: // crand,  crandc, creqv
19764       case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor,  cror
19765       case 0x1A1: case 0x0C1: case 0x000: // crorc,  crxor,  mcrf
19766          if (dis_cond_logic( theInstr )) goto decode_success;
19767          goto decode_failure;
19768 
19769       /* Branch Instructions */
19770       case 0x210: case 0x010: // bcctr, bclr
19771          if (dis_branch(theInstr, abiinfo, &dres,
19772                                   resteerOkFn, callback_opaque))
19773             goto decode_success;
19774          goto decode_failure;
19775 
19776       /* Memory Synchronization Instructions */
19777       case 0x096: // isync
19778          if (dis_memsync( theInstr )) goto decode_success;
19779          goto decode_failure;
19780 
19781       default:
19782          goto decode_failure;
19783       }
19784       break;
19785 
19786 
19787    case 0x1F:
19788 
19789       /* For arith instns, bit10 is the OE flag (overflow enable) */
19790 
19791       opc2 = IFIELD(theInstr, 1, 9);
19792       switch (opc2) {
19793       /* Integer Arithmetic Instructions */
19794       case 0x10A: case 0x00A: case 0x08A: // add,   addc,  adde
19795       case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw
19796       case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu
19797       case 0x0EB: case 0x068: case 0x028: // mullw, neg,   subf
19798       case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme
19799       case 0x0C8: // subfze
19800          if (dis_int_arith( theInstr )) goto decode_success;
19801          goto decode_failure;
19802 
19803       case 0x18B: // divweu (implemented as native insn)
19804       case 0x1AB: // divwe (implemented as native insn)
19805          if (!allow_VX) goto decode_noVX;
19806          if (dis_int_arith( theInstr )) goto decode_success;
19807          goto decode_failure;
19808 
19809       /* 64bit Integer Arithmetic */
19810       case 0x009: case 0x049: case 0x0E9: // mulhdu, mulhd, mulld
19811       case 0x1C9: case 0x1E9: // divdu, divd
19812          if (!mode64) goto decode_failure;
19813          if (dis_int_arith( theInstr )) goto decode_success;
19814          goto decode_failure;
19815 
19816       case 0x1A9: //  divde (implemented as native insn)
19817       case 0x189: //  divdeuo (implemented as native insn)
19818          if (!allow_VX) goto decode_noVX;
19819          if (!mode64) goto decode_failure;
19820          if (dis_int_arith( theInstr )) goto decode_success;
19821          goto decode_failure;
19822 
19823       case 0x1FC:                         // cmpb
19824          if (dis_int_logic( theInstr )) goto decode_success;
19825          goto decode_failure;
19826 
19827       default:
19828          break;  // Fall through...
19829       }
19830 
19831       /* All remaining opcodes use full 10 bits. */
19832 
19833       opc2 = IFIELD(theInstr, 1, 10);
19834       switch (opc2) {
19835       /* Integer Compare Instructions  */
19836       case 0x000: case 0x020: // cmp, cmpl
19837          if (dis_int_cmp( theInstr )) goto decode_success;
19838          goto decode_failure;
19839 
19840       /* Integer Logical Instructions */
19841       case 0x01C: case 0x03C: case 0x01A: // and,  andc,  cntlzw
19842       case 0x11C: case 0x3BA: case 0x39A: // eqv,  extsb, extsh
19843       case 0x1DC: case 0x07C: case 0x1BC: // nand, nor,   or
19844       case 0x19C: case 0x13C:             // orc,  xor
19845       case 0x2DF: case 0x25F:            // mftgpr, mffgpr
19846          if (dis_int_logic( theInstr )) goto decode_success;
19847          goto decode_failure;
19848 
19849       case 0x28E: case 0x2AE:             // tbegin., tend.
19850       case 0x2EE: case 0x2CE: case 0x30E: // tsr., tcheck., tabortwc.
19851       case 0x32E: case 0x34E: case 0x36E: // tabortdc., tabortwci., tabortdci.
19852       case 0x38E: case 0x3AE: case 0x3EE: // tabort., treclaim., trechkpt.
19853       if (dis_transactional_memory( theInstr,
19854                                     getUIntPPCendianly( &guest_code[delta + 4]),
19855                                     abiinfo, &dres,
19856                                     resteerOkFn, callback_opaque))
19857             goto decode_success;
19858          goto decode_failure;
19859 
19860       /* 64bit Integer Logical Instructions */
19861       case 0x3DA: case 0x03A: // extsw, cntlzd
19862          if (!mode64) goto decode_failure;
19863          if (dis_int_logic( theInstr )) goto decode_success;
19864          goto decode_failure;
19865 
19866          /* 64bit Integer Parity Instructions */
19867       case 0xba: // prtyd
19868          if (!mode64) goto decode_failure;
19869          if (dis_int_parity( theInstr )) goto decode_success;
19870          goto decode_failure;
19871 
19872       case 0x9a: // prtyw
19873          if (dis_int_parity( theInstr )) goto decode_success;
19874          goto decode_failure;
19875 
19876       /* Integer Shift Instructions */
19877       case 0x018: case 0x318: case 0x338: // slw, sraw, srawi
19878       case 0x218:                         // srw
19879          if (dis_int_shift( theInstr )) goto decode_success;
19880          goto decode_failure;
19881 
19882       /* 64bit Integer Shift Instructions */
19883       case 0x01B: case 0x31A: // sld, srad
19884       case 0x33A: case 0x33B: // sradi
19885       case 0x21B:             // srd
19886          if (!mode64) goto decode_failure;
19887          if (dis_int_shift( theInstr )) goto decode_success;
19888          goto decode_failure;
19889 
19890       /* Integer Load Instructions */
19891       case 0x057: case 0x077: case 0x157: // lbzx,  lbzux, lhax
19892       case 0x177: case 0x117: case 0x137: // lhaux, lhzx,  lhzux
19893       case 0x017: case 0x037:             // lwzx,  lwzux
19894          if (dis_int_load( theInstr )) goto decode_success;
19895          goto decode_failure;
19896 
19897       /* 64bit Integer Load Instructions */
19898       case 0x035: case 0x015:             // ldux,  ldx
19899       case 0x175: case 0x155:             // lwaux, lwax
19900          if (!mode64) goto decode_failure;
19901          if (dis_int_load( theInstr )) goto decode_success;
19902          goto decode_failure;
19903 
19904       /* Integer Store Instructions */
19905       case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx,  sthux
19906       case 0x197: case 0x0B7: case 0x097: // sthx,  stwux, stwx
19907          if (dis_int_store( theInstr, abiinfo )) goto decode_success;
19908          goto decode_failure;
19909 
19910       /* 64bit Integer Store Instructions */
19911       case 0x0B5: case 0x095: // stdux, stdx
19912          if (!mode64) goto decode_failure;
19913          if (dis_int_store( theInstr, abiinfo )) goto decode_success;
19914          goto decode_failure;
19915 
19916       /* Integer Load and Store with Byte Reverse Instructions */
19917       case 0x214: case 0x294: // ldbrx, stdbrx
19918          if (!mode64) goto decode_failure;
19919          if (dis_int_ldst_rev( theInstr )) goto decode_success;
19920          goto decode_failure;
19921 
19922       case 0x216: case 0x316: case 0x296:    // lwbrx, lhbrx, stwbrx
19923       case 0x396:                            // sthbrx
19924          if (dis_int_ldst_rev( theInstr )) goto decode_success;
19925          goto decode_failure;
19926 
19927       /* Integer Load and Store String Instructions */
19928       case 0x255: case 0x215: case 0x2D5: // lswi, lswx, stswi
19929       case 0x295: {                       // stswx
19930          Bool stopHere = False;
19931          Bool ok = dis_int_ldst_str( theInstr, &stopHere );
19932          if (!ok) goto decode_failure;
19933          if (stopHere) {
19934             putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()) );
19935             dres.jk_StopHere = Ijk_Boring;
19936             dres.whatNext    = Dis_StopHere;
19937          }
19938          goto decode_success;
19939       }
19940 
19941       /* Memory Synchronization Instructions */
19942       case 0x034: case 0x074:             // lbarx, lharx
19943       case 0x2B6: case 0x2D6:             // stbcx, sthcx
19944          if (!allow_isa_2_07) goto decode_noP8;
19945          if (dis_memsync( theInstr )) goto decode_success;
19946          goto decode_failure;
19947 
19948       case 0x356: case 0x014: case 0x096: // eieio, lwarx, stwcx.
19949       case 0x256:                         // sync
19950          if (dis_memsync( theInstr )) goto decode_success;
19951          goto decode_failure;
19952 
19953       /* 64bit Memory Synchronization Instructions */
19954       case 0x054: case 0x0D6: // ldarx, stdcx.
19955          if (!mode64) goto decode_failure;
19956          if (dis_memsync( theInstr )) goto decode_success;
19957          goto decode_failure;
19958 
19959       case 0x114: case 0x0B6: // lqarx, stqcx.
19960          if (dis_memsync( theInstr )) goto decode_success;
19961          goto decode_failure;
19962 
19963       /* Processor Control Instructions */
19964       case 0x33:  case 0x73: // mfvsrd, mfvsrwz
19965       case 0xB3:  case 0xD3: case 0xF3: // mtvsrd, mtvsrwa, mtvsrwz
19966       case 0x200: case 0x013: case 0x153: // mcrxr, mfcr,  mfspr
19967       case 0x173: case 0x090: case 0x1D3: // mftb,  mtcrf, mtspr
19968       case 0x220:                         // mcrxrt
19969          if (dis_proc_ctl( abiinfo, theInstr )) goto decode_success;
19970          goto decode_failure;
19971 
19972       /* Cache Management Instructions */
19973       case 0x2F6: case 0x056: case 0x036: // dcba, dcbf,   dcbst
19974       case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz
19975       case 0x3D6:                         // icbi
19976          if (dis_cache_manage( theInstr, &dres, archinfo ))
19977             goto decode_success;
19978          goto decode_failure;
19979 
19980 //zz       /* External Control Instructions */
19981 //zz       case 0x136: case 0x1B6: // eciwx, ecowx
19982 //zz          DIP("external control op => not implemented\n");
19983 //zz          goto decode_failure;
19984 
19985       /* Trap Instructions */
19986       case 0x004:             // tw
19987          if (dis_trap(theInstr, &dres)) goto decode_success;
19988          goto decode_failure;
19989 
19990       case 0x044:             // td
19991          if (!mode64) goto decode_failure;
19992          if (dis_trap(theInstr, &dres)) goto decode_success;
19993          goto decode_failure;
19994 
19995       /* Floating Point Load Instructions */
19996       case 0x217: case 0x237: case 0x257: // lfsx, lfsux, lfdx
19997       case 0x277:                         // lfdux
19998          if (!allow_F) goto decode_noF;
19999          if (dis_fp_load( theInstr )) goto decode_success;
20000          goto decode_failure;
20001 
20002       /* Floating Point Store Instructions */
20003       case 0x297: case 0x2B7: case 0x2D7: // stfs,  stfsu, stfd
20004       case 0x2F7:                         // stfdu, stfiwx
20005          if (!allow_F) goto decode_noF;
20006          if (dis_fp_store( theInstr )) goto decode_success;
20007          goto decode_failure;
20008       case 0x3D7:                         // stfiwx
20009          if (!allow_F) goto decode_noF;
20010          if (!allow_GX) goto decode_noGX;
20011          if (dis_fp_store( theInstr )) goto decode_success;
20012          goto decode_failure;
20013 
20014          /* Floating Point Double Pair Indexed Instructions */
20015       case 0x317: // lfdpx (Power6)
20016       case 0x397: // stfdpx (Power6)
20017          if (!allow_F) goto decode_noF;
20018          if (dis_fp_pair(theInstr)) goto decode_success;
20019          goto decode_failure;
20020 
20021       case 0x357:                         // lfiwax
20022          if (!allow_F) goto decode_noF;
20023          if (dis_fp_load( theInstr )) goto decode_success;
20024          goto decode_failure;
20025 
20026       case 0x377:                         // lfiwzx
20027          if (!allow_F) goto decode_noF;
20028          if (dis_fp_load( theInstr )) goto decode_success;
20029          goto decode_failure;
20030 
20031       /* AltiVec instructions */
20032 
20033       /* AV Cache Control - Data streams */
20034       case 0x156: case 0x176: case 0x336: // dst, dstst, dss
20035          if (!allow_V) goto decode_noV;
20036          if (dis_av_datastream( theInstr )) goto decode_success;
20037          goto decode_failure;
20038 
20039       /* AV Load */
20040       case 0x006: case 0x026:             // lvsl, lvsr
20041       case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx
20042       case 0x067: case 0x167:             // lvx, lvxl
20043          if (!allow_V) goto decode_noV;
20044          if (dis_av_load( abiinfo, theInstr )) goto decode_success;
20045          goto decode_failure;
20046 
20047       /* AV Store */
20048       case 0x087: case 0x0A7: case 0x0C7: // stvebx, stvehx, stvewx
20049       case 0x0E7: case 0x1E7:             // stvx, stvxl
20050          if (!allow_V) goto decode_noV;
20051          if (dis_av_store( theInstr )) goto decode_success;
20052          goto decode_failure;
20053 
20054       /* VSX Load */
20055       case 0x00C: // lxsiwzx
20056       case 0x04C: // lxsiwax
20057       case 0x20C: // lxsspx
20058       case 0x24C: // lxsdx
20059       case 0x34C: // lxvd2x
20060       case 0x14C: // lxvdsx
20061       case 0x30C: // lxvw4x
20062         // All of these VSX load instructions use some VMX facilities, so
20063         // if allow_V is not set, we'll skip trying to decode.
20064         if (!allow_V) goto decode_noV;
20065 
20066 	if (dis_vx_load( theInstr )) goto decode_success;
20067           goto decode_failure;
20068 
20069       /* VSX Store */
20070       case 0x08C: // stxsiwx
20071       case 0x28C: // stxsspx
20072       case 0x2CC: // stxsdx
20073       case 0x3CC: // stxvd2x
20074       case 0x38C: // stxvw4x
20075         // All of these VSX store instructions use some VMX facilities, so
20076         // if allow_V is not set, we'll skip trying to decode.
20077         if (!allow_V) goto decode_noV;
20078 
20079 	if (dis_vx_store( theInstr )) goto decode_success;
20080     	  goto decode_failure;
20081 
20082       /* Miscellaneous ISA 2.06 instructions */
20083       case 0x1FA: // popcntd
20084       case 0x17A: // popcntw
20085       case 0x7A:  // popcntb
20086 	  if (dis_int_logic( theInstr )) goto decode_success;
20087     	  goto decode_failure;
20088 
20089       case 0x0FC: // bpermd
20090          if (!mode64) goto decode_failure;
20091          if (dis_int_logic( theInstr )) goto decode_success;
20092          goto decode_failure;
20093 
20094       default:
20095          /* Deal with some other cases that we would otherwise have
20096             punted on. */
20097          /* --- ISEL (PowerISA_V2.05.pdf, p74) --- */
20098          /* only decode this insn when reserved bit 0 (31 in IBM's
20099             notation) is zero */
20100          if (IFIELD(theInstr, 0, 6) == (15<<1)) {
20101             UInt rT = ifieldRegDS( theInstr );
20102             UInt rA = ifieldRegA( theInstr );
20103             UInt rB = ifieldRegB( theInstr );
20104             UInt bi = ifieldRegC( theInstr );
20105             putIReg(
20106                rT,
20107                IRExpr_ITE( binop(Iop_CmpNE32, getCRbit( bi ), mkU32(0)),
20108                            rA == 0 ? (mode64 ? mkU64(0) : mkU32(0))
20109                                    : getIReg(rA),
20110                            getIReg(rB))
20111 
20112             );
20113             DIP("isel r%u,r%u,r%u,crb%u\n", rT,rA,rB,bi);
20114             goto decode_success;
20115          }
20116          goto decode_failure;
20117       }
20118       break;
20119 
20120 
20121    case 0x04:
20122       /* AltiVec instructions */
20123 
20124       opc2 = IFIELD(theInstr, 0, 6);
20125       switch (opc2) {
20126       /* AV Mult-Add, Mult-Sum */
20127       case 0x20: case 0x21: case 0x22: // vmhaddshs, vmhraddshs, vmladduhm
20128       case 0x24: case 0x25: case 0x26: // vmsumubm, vmsummbm, vmsumuhm
20129       case 0x27: case 0x28: case 0x29: // vmsumuhs, vmsumshm, vmsumshs
20130          if (!allow_V) goto decode_noV;
20131          if (dis_av_multarith( theInstr )) goto decode_success;
20132          goto decode_failure;
20133 
20134       /* AV Permutations */
20135       case 0x2A:                       // vsel
20136       case 0x2B:                       // vperm
20137       case 0x2C:                       // vsldoi
20138          if (!allow_V) goto decode_noV;
20139          if (dis_av_permute( theInstr )) goto decode_success;
20140          goto decode_failure;
20141 
20142       case 0x2D:                       // vpermxor
20143          if (!allow_isa_2_07) goto decode_noP8;
20144          if (dis_av_permute( theInstr )) goto decode_success;
20145          goto decode_failure;
20146 
20147       /* AV Floating Point Mult-Add/Sub */
20148       case 0x2E: case 0x2F:            // vmaddfp, vnmsubfp
20149          if (!allow_V) goto decode_noV;
20150          if (dis_av_fp_arith( theInstr )) goto decode_success;
20151          goto decode_failure;
20152 
20153       case 0x3D: case 0x3C:            // vaddecuq, vaddeuqm
20154       case 0x3F: case 0x3E:            // vsubecuq, vsubeuqm
20155          if (!allow_V) goto decode_noV;
20156          if (dis_av_quad( theInstr)) goto decode_success;
20157          goto decode_failure;
20158 
20159       default:
20160          break;  // Fall through...
20161       }
20162 
20163       opc2 = IFIELD(theInstr, 0, 9);
20164       switch (opc2) {
20165       /* BCD arithmetic */
20166       case 0x1: case 0x41:             // bcdadd, bcdsub
20167          if (!allow_isa_2_07) goto decode_noP8;
20168          if (dis_av_bcd( theInstr )) goto decode_success;
20169          goto decode_failure;
20170 
20171       default:
20172          break;  // Fall through...
20173       }
20174 
20175       opc2 = IFIELD(theInstr, 0, 11);
20176       switch (opc2) {
20177       /* AV Arithmetic */
20178       case 0x180:                         // vaddcuw
20179       case 0x000: case 0x040: case 0x080: // vaddubm, vadduhm, vadduwm
20180       case 0x200: case 0x240: case 0x280: // vaddubs, vadduhs, vadduws
20181       case 0x300: case 0x340: case 0x380: // vaddsbs, vaddshs, vaddsws
20182       case 0x580:                         // vsubcuw
20183       case 0x400: case 0x440: case 0x480: // vsububm, vsubuhm, vsubuwm
20184       case 0x600: case 0x640: case 0x680: // vsububs, vsubuhs, vsubuws
20185       case 0x700: case 0x740: case 0x780: // vsubsbs, vsubshs, vsubsws
20186       case 0x402: case 0x442: case 0x482: // vavgub, vavguh, vavguw
20187       case 0x502: case 0x542: case 0x582: // vavgsb, vavgsh, vavgsw
20188       case 0x002: case 0x042: case 0x082: // vmaxub, vmaxuh, vmaxuw
20189       case 0x102: case 0x142: case 0x182: // vmaxsb, vmaxsh, vmaxsw
20190       case 0x202: case 0x242: case 0x282: // vminub, vminuh, vminuw
20191       case 0x302: case 0x342: case 0x382: // vminsb, vminsh, vminsw
20192       case 0x008: case 0x048:             // vmuloub, vmulouh
20193       case 0x108: case 0x148:             // vmulosb, vmulosh
20194       case 0x208: case 0x248:             // vmuleub, vmuleuh
20195       case 0x308: case 0x348:             // vmulesb, vmulesh
20196       case 0x608: case 0x708: case 0x648: // vsum4ubs, vsum4sbs, vsum4shs
20197       case 0x688: case 0x788:             // vsum2sws, vsumsws
20198          if (!allow_V) goto decode_noV;
20199          if (dis_av_arith( theInstr )) goto decode_success;
20200          goto decode_failure;
20201 
20202       case 0x088: case 0x089:             // vmulouw, vmuluwm
20203       case 0x0C0: case 0x0C2:             // vaddudm, vmaxud
20204       case 0x1C2: case 0x2C2: case 0x3C2: // vnaxsd, vminud, vminsd
20205       case 0x188: case 0x288: case 0x388: // vmulosw, vmuleuw, vmulesw
20206       case 0x4C0:                         // vsubudm
20207          if (!allow_isa_2_07) goto decode_noP8;
20208          if (dis_av_arith( theInstr )) goto decode_success;
20209          goto decode_failure;
20210 
20211       /* AV Polynomial Vector Multiply Add */
20212       case 0x408: case 0x448:            // vpmsumb, vpmsumd
20213       case 0x488: case 0x4C8:            // vpmsumw, vpmsumh
20214          if (!allow_isa_2_07) goto decode_noP8;
20215          if (dis_av_polymultarith( theInstr )) goto decode_success;
20216          goto decode_failure;
20217 
20218       /* AV Rotate, Shift */
20219       case 0x004: case 0x044: case 0x084: // vrlb, vrlh, vrlw
20220       case 0x104: case 0x144: case 0x184: // vslb, vslh, vslw
20221       case 0x204: case 0x244: case 0x284: // vsrb, vsrh, vsrw
20222       case 0x304: case 0x344: case 0x384: // vsrab, vsrah, vsraw
20223       case 0x1C4: case 0x2C4:             // vsl, vsr
20224       case 0x40C: case 0x44C:             // vslo, vsro
20225          if (!allow_V) goto decode_noV;
20226          if (dis_av_shift( theInstr )) goto decode_success;
20227          goto decode_failure;
20228 
20229       case 0x0C4:                         // vrld
20230       case 0x3C4: case 0x5C4: case 0x6C4: // vsrad, vsld, vsrd
20231           if (!allow_isa_2_07) goto decode_noP8;
20232           if (dis_av_shift( theInstr )) goto decode_success;
20233           goto decode_failure;
20234 
20235       /* AV Logic */
20236       case 0x404: case 0x444: case 0x484: // vand, vandc, vor
20237       case 0x4C4: case 0x504:             // vxor, vnor
20238          if (!allow_V) goto decode_noV;
20239          if (dis_av_logic( theInstr )) goto decode_success;
20240          goto decode_failure;
20241 
20242       case 0x544:                         // vorc
20243       case 0x584: case 0x684:             // vnand, veqv
20244          if (!allow_isa_2_07) goto decode_noP8;
20245          if (dis_av_logic( theInstr )) goto decode_success;
20246          goto decode_failure;
20247 
20248       /* AV Processor Control */
20249       case 0x604: case 0x644:             // mfvscr, mtvscr
20250          if (!allow_V) goto decode_noV;
20251          if (dis_av_procctl( theInstr )) goto decode_success;
20252          goto decode_failure;
20253 
20254       /* AV Floating Point Arithmetic */
20255       case 0x00A: case 0x04A:             // vaddfp, vsubfp
20256       case 0x10A: case 0x14A: case 0x18A: // vrefp, vrsqrtefp, vexptefp
20257       case 0x1CA:                         // vlogefp
20258       case 0x40A: case 0x44A:             // vmaxfp, vminfp
20259          if (!allow_V) goto decode_noV;
20260          if (dis_av_fp_arith( theInstr )) goto decode_success;
20261          goto decode_failure;
20262 
20263       /* AV Floating Point Round/Convert */
20264       case 0x20A: case 0x24A: case 0x28A: // vrfin, vrfiz, vrfip
20265       case 0x2CA:                         // vrfim
20266       case 0x30A: case 0x34A: case 0x38A: // vcfux, vcfsx, vctuxs
20267       case 0x3CA:                         // vctsxs
20268          if (!allow_V) goto decode_noV;
20269          if (dis_av_fp_convert( theInstr )) goto decode_success;
20270          goto decode_failure;
20271 
20272       /* AV Merge, Splat */
20273       case 0x00C: case 0x04C: case 0x08C: // vmrghb, vmrghh, vmrghw
20274       case 0x10C: case 0x14C: case 0x18C: // vmrglb, vmrglh, vmrglw
20275       case 0x20C: case 0x24C: case 0x28C: // vspltb, vsplth, vspltw
20276       case 0x30C: case 0x34C: case 0x38C: // vspltisb, vspltish, vspltisw
20277          if (!allow_V) goto decode_noV;
20278          if (dis_av_permute( theInstr )) goto decode_success;
20279          goto decode_failure;
20280 
20281       case 0x68C: case 0x78C:             // vmrgow, vmrgew
20282           if (!allow_isa_2_07) goto decode_noP8;
20283           if (dis_av_permute( theInstr )) goto decode_success;
20284           goto decode_failure;
20285 
20286       /* AV Pack, Unpack */
20287       case 0x00E: case 0x04E: case 0x08E: // vpkuhum, vpkuwum, vpkuhus
20288       case 0x0CE:                         // vpkuwus
20289       case 0x10E: case 0x14E: case 0x18E: // vpkshus, vpkswus, vpkshss
20290       case 0x1CE:                         // vpkswss
20291       case 0x20E: case 0x24E: case 0x28E: // vupkhsb, vupkhsh, vupklsb
20292       case 0x2CE:                         // vupklsh
20293       case 0x30E: case 0x34E: case 0x3CE: // vpkpx, vupkhpx, vupklpx
20294           if (!allow_V) goto decode_noV;
20295           if (dis_av_pack( theInstr )) goto decode_success;
20296           goto decode_failure;
20297 
20298       case 0x44E: case 0x4CE: case 0x54E: // vpkudum, vpkudus, vpksdus
20299       case 0x5CE: case 0x64E: case 0x6cE: // vpksdss, vupkhsw, vupklsw
20300          if (!allow_isa_2_07) goto decode_noP8;
20301          if (dis_av_pack( theInstr )) goto decode_success;
20302          goto decode_failure;
20303 
20304       case 0x508: case 0x509:             // vcipher, vcipherlast
20305       case 0x548: case 0x549:             // vncipher, vncipherlast
20306       case 0x5C8:                         // vsbox
20307          if (!allow_isa_2_07) goto decode_noP8;
20308          if (dis_av_cipher( theInstr )) goto decode_success;
20309          goto decode_failure;
20310 
20311       case 0x6C2: case 0x682:             // vshasigmaw, vshasigmad
20312          if (!allow_isa_2_07) goto decode_noP8;
20313          if (dis_av_hash( theInstr )) goto decode_success;
20314          goto decode_failure;
20315 
20316       case 0x702: case 0x742:             // vclzb, vclzh
20317       case 0x782: case 0x7c2:             // vclzw, vclzd
20318          if (!allow_isa_2_07) goto decode_noP8;
20319          if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
20320          goto decode_failure;
20321 
20322       case 0x703: case 0x743:             // vpopcntb, vpopcnth
20323       case 0x783: case 0x7c3:             // vpopcntw, vpopcntd
20324          if (!allow_isa_2_07) goto decode_noP8;
20325          if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
20326          goto decode_failure;
20327 
20328       case 0x50c:                         // vgbbd
20329          if (!allow_isa_2_07) goto decode_noP8;
20330          if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
20331          goto decode_failure;
20332 
20333       case 0x140: case 0x100:             // vaddcuq, vadduqm
20334       case 0x540: case 0x500:             // vsubcuq, vsubuqm
20335       case 0x54C:                         // vbpermq
20336          if (!allow_V) goto decode_noV;
20337          if (dis_av_quad( theInstr)) goto decode_success;
20338          goto decode_failure;
20339 
20340       default:
20341          break;  // Fall through...
20342       }
20343 
20344       opc2 = IFIELD(theInstr, 0, 10);
20345       switch (opc2) {
20346 
20347       /* AV Compare */
20348       case 0x006: case 0x046: case 0x086: // vcmpequb, vcmpequh, vcmpequw
20349       case 0x206: case 0x246: case 0x286: // vcmpgtub, vcmpgtuh, vcmpgtuw
20350       case 0x306: case 0x346: case 0x386: // vcmpgtsb, vcmpgtsh, vcmpgtsw
20351          if (!allow_V) goto decode_noV;
20352          if (dis_av_cmp( theInstr )) goto decode_success;
20353          goto decode_failure;
20354 
20355       case 0x0C7:                         // vcmpequd
20356       case 0x2C7:                         // vcmpgtud
20357       case 0x3C7:                         // vcmpgtsd
20358           if (!allow_isa_2_07) goto decode_noP8;
20359           if (dis_av_cmp( theInstr )) goto decode_success;
20360           goto decode_failure;
20361 
20362       /* AV Floating Point Compare */
20363       case 0x0C6: case 0x1C6: case 0x2C6: // vcmpeqfp, vcmpgefp, vcmpgtfp
20364       case 0x3C6:                         // vcmpbfp
20365          if (!allow_V) goto decode_noV;
20366          if (dis_av_fp_cmp( theInstr )) goto decode_success;
20367          goto decode_failure;
20368 
20369       default:
20370          goto decode_failure;
20371       }
20372       break;
20373 
20374    default:
20375       goto decode_failure;
20376 
20377    decode_noF:
20378       vassert(!allow_F);
20379       vex_printf("disInstr(ppc): found the Floating Point instruction 0x%x that\n"
20380 		 "can't be handled by Valgrind on this host.  This instruction\n"
20381 		 "requires a host that supports Floating Point instructions.\n",
20382 		 theInstr);
20383       goto not_supported;
20384    decode_noV:
20385       vassert(!allow_V);
20386       vex_printf("disInstr(ppc): found an AltiVec or an e500 instruction 0x%x\n"
20387 		 "that can't be handled by Valgrind.  If this instruction is an\n"
20388 		 "Altivec instruction, Valgrind must be run on a host that supports"
20389 		 "AltiVec instructions.  If the application was compiled for e500, then\n"
20390 		 "unfortunately Valgrind does not yet support e500 instructions.\n",
20391 		 theInstr);
20392       goto not_supported;
20393    decode_noVX:
20394       vassert(!allow_VX);
20395       vex_printf("disInstr(ppc): found the instruction 0x%x that is defined in the\n"
20396 		 "Power ISA 2.06 ABI but can't be handled by Valgrind on this host.\n"
20397 		 "This instruction \nrequires a host that supports the ISA 2.06 ABI.\n",
20398 		 theInstr);
20399       goto not_supported;
20400    decode_noFX:
20401       vassert(!allow_FX);
20402       vex_printf("disInstr(ppc): found the General Purpose-Optional instruction 0x%x\n"
20403 		 "that can't be handled by Valgrind on this host. This instruction\n"
20404 		 "requires a host that supports the General Purpose-Optional instructions.\n",
20405 		 theInstr);
20406       goto not_supported;
20407    decode_noGX:
20408       vassert(!allow_GX);
20409       vex_printf("disInstr(ppc): found the Graphics-Optional instruction 0x%x\n"
20410 		 "that can't be handled by Valgrind on this host. This instruction\n"
20411 		 "requires a host that supports the Graphic-Optional instructions.\n",
20412 		 theInstr);
20413       goto not_supported;
20414    decode_noDFP:
20415       vassert(!allow_DFP);
20416       vex_printf("disInstr(ppc): found the decimal floating point (DFP) instruction 0x%x\n"
20417 		 "that can't be handled by Valgrind on this host.  This instruction\n"
20418 		 "requires a host that supports DFP instructions.\n",
20419 		 theInstr);
20420       goto not_supported;
20421    decode_noP8:
20422       vassert(!allow_isa_2_07);
20423       vex_printf("disInstr(ppc): found the Power 8 instruction 0x%x that can't be handled\n"
20424 		 "by Valgrind on this host.  This instruction requires a host that\n"
20425 		 "supports Power 8 instructions.\n",
20426 		 theInstr);
20427       goto not_supported;
20428 
20429 
20430    decode_failure:
20431    /* All decode failures end up here. */
20432    opc2 = (theInstr) & 0x7FF;
20433    if (sigill_diag) {
20434       vex_printf("disInstr(ppc): unhandled instruction: "
20435                  "0x%x\n", theInstr);
20436       vex_printf("                 primary %d(0x%x), secondary %u(0x%x)\n",
20437                  opc1, opc1, opc2, opc2);
20438    }
20439 
20440    not_supported:
20441    /* Tell the dispatcher that this insn cannot be decoded, and so has
20442       not been executed, and (is currently) the next to be executed.
20443       CIA should be up-to-date since it made so at the start of each
20444       insn, but nevertheless be paranoid and update it again right
20445       now. */
20446    putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) );
20447    dres.len         = 0;
20448    dres.whatNext    = Dis_StopHere;
20449    dres.jk_StopHere = Ijk_NoDecode;
20450    dres.continueAt  = 0;
20451    return dres;
20452    } /* switch (opc) for the main (primary) opcode switch. */
20453 
20454   decode_success:
20455    /* All decode successes end up here. */
20456    switch (dres.whatNext) {
20457       case Dis_Continue:
20458          putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr + 4));
20459          break;
20460       case Dis_ResteerU:
20461       case Dis_ResteerC:
20462          putGST( PPC_GST_CIA, mkSzImm(ty, dres.continueAt));
20463          break;
20464       case Dis_StopHere:
20465          break;
20466       default:
20467          vassert(0);
20468    }
20469    DIP("\n");
20470 
20471    if (dres.len == 0) {
20472       dres.len = 4;
20473    } else {
20474       vassert(dres.len == 20);
20475    }
20476    return dres;
20477 }
20478 
20479 #undef DIP
20480 #undef DIS
20481 
20482 
20483 /*------------------------------------------------------------*/
20484 /*--- Top-level fn                                         ---*/
20485 /*------------------------------------------------------------*/
20486 
20487 /* Disassemble a single instruction into IR.  The instruction
20488    is located in host memory at &guest_code[delta]. */
20489 
disInstr_PPC(IRSB * irsb_IN,Bool (* resteerOkFn)(void *,Addr),Bool resteerCisOk,void * callback_opaque,const UChar * guest_code_IN,Long delta,Addr guest_IP,VexArch guest_arch,const VexArchInfo * archinfo,const VexAbiInfo * abiinfo,VexEndness host_endness_IN,Bool sigill_diag_IN)20490 DisResult disInstr_PPC ( IRSB*        irsb_IN,
20491                          Bool         (*resteerOkFn) ( void*, Addr ),
20492                          Bool         resteerCisOk,
20493                          void*        callback_opaque,
20494                          const UChar* guest_code_IN,
20495                          Long         delta,
20496                          Addr         guest_IP,
20497                          VexArch      guest_arch,
20498                          const VexArchInfo* archinfo,
20499                          const VexAbiInfo*  abiinfo,
20500                          VexEndness   host_endness_IN,
20501                          Bool         sigill_diag_IN )
20502 {
20503    IRType     ty;
20504    DisResult  dres;
20505    UInt       mask32, mask64;
20506    UInt hwcaps_guest = archinfo->hwcaps;
20507 
20508    vassert(guest_arch == VexArchPPC32 || guest_arch == VexArchPPC64);
20509 
20510    /* global -- ick */
20511    mode64 = guest_arch == VexArchPPC64;
20512    ty = mode64 ? Ity_I64 : Ity_I32;
20513    if (!mode64 && (host_endness_IN == VexEndnessLE)) {
20514       vex_printf("disInstr(ppc): Little Endian 32-bit mode is not supported\n");
20515       dres.len         = 0;
20516       dres.whatNext    = Dis_StopHere;
20517       dres.jk_StopHere = Ijk_NoDecode;
20518       dres.continueAt   = 0;
20519       return dres;
20520    }
20521 
20522    /* do some sanity checks */
20523    mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V
20524             | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX
20525             | VEX_HWCAPS_PPC32_DFP | VEX_HWCAPS_PPC32_ISA2_07;
20526 
20527    mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX
20528             | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX | VEX_HWCAPS_PPC64_DFP
20529             | VEX_HWCAPS_PPC64_ISA2_07;
20530 
20531    if (mode64) {
20532       vassert((hwcaps_guest & mask32) == 0);
20533    } else {
20534       vassert((hwcaps_guest & mask64) == 0);
20535    }
20536 
20537    /* Set globals (see top of this file) */
20538    guest_code           = guest_code_IN;
20539    irsb                 = irsb_IN;
20540    host_endness         = host_endness_IN;
20541 
20542    guest_CIA_curr_instr = mkSzAddr(ty, guest_IP);
20543    guest_CIA_bbstart    = mkSzAddr(ty, guest_IP - delta);
20544 
20545    dres = disInstr_PPC_WRK ( resteerOkFn, resteerCisOk, callback_opaque,
20546                              delta, archinfo, abiinfo, sigill_diag_IN);
20547 
20548    return dres;
20549 }
20550 
20551 
20552 /*------------------------------------------------------------*/
20553 /*--- Unused stuff                                         ---*/
20554 /*------------------------------------------------------------*/
20555 
20556 ///* A potentially more memcheck-friendly implementation of Clz32, with
20557 //   the boundary case Clz32(0) = 32, which is what ppc requires. */
20558 //
20559 //static IRExpr* /* :: Ity_I32 */ verbose_Clz32 ( IRTemp arg )
20560 //{
20561 //   /* Welcome ... to SSA R Us. */
20562 //   IRTemp n1  = newTemp(Ity_I32);
20563 //   IRTemp n2  = newTemp(Ity_I32);
20564 //   IRTemp n3  = newTemp(Ity_I32);
20565 //   IRTemp n4  = newTemp(Ity_I32);
20566 //   IRTemp n5  = newTemp(Ity_I32);
20567 //   IRTemp n6  = newTemp(Ity_I32);
20568 //   IRTemp n7  = newTemp(Ity_I32);
20569 //   IRTemp n8  = newTemp(Ity_I32);
20570 //   IRTemp n9  = newTemp(Ity_I32);
20571 //   IRTemp n10 = newTemp(Ity_I32);
20572 //   IRTemp n11 = newTemp(Ity_I32);
20573 //   IRTemp n12 = newTemp(Ity_I32);
20574 //
20575 //   /* First, propagate the most significant 1-bit into all lower
20576 //      positions in the word. */
20577 //   /* unsigned int clz ( unsigned int n )
20578 //      {
20579 //         n |= (n >> 1);
20580 //         n |= (n >> 2);
20581 //         n |= (n >> 4);
20582 //         n |= (n >> 8);
20583 //         n |= (n >> 16);
20584 //         return bitcount(~n);
20585 //      }
20586 //   */
20587 //   assign(n1, mkexpr(arg));
20588 //   assign(n2, binop(Iop_Or32, mkexpr(n1), binop(Iop_Shr32, mkexpr(n1), mkU8(1))));
20589 //   assign(n3, binop(Iop_Or32, mkexpr(n2), binop(Iop_Shr32, mkexpr(n2), mkU8(2))));
20590 //   assign(n4, binop(Iop_Or32, mkexpr(n3), binop(Iop_Shr32, mkexpr(n3), mkU8(4))));
20591 //   assign(n5, binop(Iop_Or32, mkexpr(n4), binop(Iop_Shr32, mkexpr(n4), mkU8(8))));
20592 //   assign(n6, binop(Iop_Or32, mkexpr(n5), binop(Iop_Shr32, mkexpr(n5), mkU8(16))));
20593 //   /* This gives a word of the form 0---01---1.  Now invert it, giving
20594 //      a word of the form 1---10---0, then do a population-count idiom
20595 //      (to count the 1s, which is the number of leading zeroes, or 32
20596 //      if the original word was 0. */
20597 //   assign(n7, unop(Iop_Not32, mkexpr(n6)));
20598 //
20599 //   /* unsigned int bitcount ( unsigned int n )
20600 //      {
20601 //         n = n - ((n >> 1) & 0x55555555);
20602 //         n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
20603 //         n = (n + (n >> 4)) & 0x0F0F0F0F;
20604 //         n = n + (n >> 8);
20605 //         n = (n + (n >> 16)) & 0x3F;
20606 //         return n;
20607 //      }
20608 //   */
20609 //   assign(n8,
20610 //          binop(Iop_Sub32,
20611 //                mkexpr(n7),
20612 //                binop(Iop_And32,
20613 //                      binop(Iop_Shr32, mkexpr(n7), mkU8(1)),
20614 //                      mkU32(0x55555555))));
20615 //   assign(n9,
20616 //          binop(Iop_Add32,
20617 //                binop(Iop_And32, mkexpr(n8), mkU32(0x33333333)),
20618 //                binop(Iop_And32,
20619 //                      binop(Iop_Shr32, mkexpr(n8), mkU8(2)),
20620 //                      mkU32(0x33333333))));
20621 //   assign(n10,
20622 //          binop(Iop_And32,
20623 //                binop(Iop_Add32,
20624 //                      mkexpr(n9),
20625 //                      binop(Iop_Shr32, mkexpr(n9), mkU8(4))),
20626 //                mkU32(0x0F0F0F0F)));
20627 //   assign(n11,
20628 //          binop(Iop_Add32,
20629 //                mkexpr(n10),
20630 //                binop(Iop_Shr32, mkexpr(n10), mkU8(8))));
20631 //   assign(n12,
20632 //          binop(Iop_Add32,
20633 //                mkexpr(n11),
20634 //                binop(Iop_Shr32, mkexpr(n11), mkU8(16))));
20635 //   return
20636 //      binop(Iop_And32, mkexpr(n12), mkU32(0x3F));
20637 //}
20638 
20639 /*--------------------------------------------------------------------*/
20640 /*--- end                                         guest_ppc_toIR.c ---*/
20641 /*--------------------------------------------------------------------*/
20642